feat: add default applications page

This commit is contained in:
Michael Aaron Murphy 2024-11-22 00:42:00 +01:00
parent 4e310024b7
commit 508b05135a
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
24 changed files with 682 additions and 205 deletions

220
Cargo.lock generated
View file

@ -318,7 +318,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -575,7 +575,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -610,7 +610,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -760,7 +760,7 @@ dependencies = [
"regex",
"rustc-hash 1.1.0",
"shlex",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -885,7 +885,7 @@ dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -956,7 +956,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -979,9 +979,9 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
[[package]]
name = "calendrical_calculations"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cec493b209a1b81fa32312d7ceca1b547d341c7b5f16a3edbf32b1d8b455bbdf"
checksum = "f27ca2b6e2f7d75f43e001ded6f25e79b80bded5abbe764cbdf78c25a3051f4b"
dependencies = [
"core_maths",
"displaydoc",
@ -1135,7 +1135,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -1169,7 +1169,7 @@ version = "0.2.2"
source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265"
dependencies = [
"dnd",
"mime",
"mime 0.1.0",
"smithay-clipboard",
]
@ -1471,7 +1471,7 @@ dependencies = [
[[package]]
name = "cosmic-config"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"atomicwrites",
"cosmic-config-derive",
@ -1493,7 +1493,7 @@ dependencies = [
[[package]]
name = "cosmic-config-derive"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"quote",
"syn 1.0.109",
@ -1522,6 +1522,17 @@ dependencies = [
"serde",
]
[[package]]
name = "cosmic-mime-apps"
version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-mime-apps#3ac0e3d926f26c6f777111f530e613d3dfc75ac4"
dependencies = [
"freedesktop-desktop-entry",
"mime 0.3.17",
"quick-xml 0.37.1",
"xdg",
]
[[package]]
name = "cosmic-panel-config"
version = "0.1.0"
@ -1595,6 +1606,7 @@ dependencies = [
"cosmic-config",
"cosmic-dbus-networkmanager",
"cosmic-idle-config",
"cosmic-mime-apps",
"cosmic-panel-config",
"cosmic-randr",
"cosmic-randr-shell",
@ -1623,6 +1635,7 @@ dependencies = [
"itoa",
"libcosmic",
"locale1",
"mime 0.3.17",
"notify",
"once_cell",
"regex",
@ -1651,7 +1664,7 @@ dependencies = [
[[package]]
name = "cosmic-settings-config"
version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-settings-daemon#2f17f33875315a4cf463f82c5dceca4d83a75bfd"
source = "git+https://github.com/pop-os/cosmic-settings-daemon#f079ab7f98132787de385934915547f333dfbddc"
dependencies = [
"cosmic-config",
"serde",
@ -1764,7 +1777,7 @@ dependencies = [
[[package]]
name = "cosmic-theme"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"almost",
"cosmic-config",
@ -1780,9 +1793,9 @@ dependencies = [
[[package]]
name = "cpufeatures"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6"
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
dependencies = [
"libc",
]
@ -1945,7 +1958,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -1967,7 +1980,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core 0.20.10",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -2051,7 +2064,7 @@ dependencies = [
"darling 0.20.10",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -2109,7 +2122,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -2136,7 +2149,7 @@ version = "0.1.0"
source = "git+https://github.com/pop-os/window_clipboard.git?tag=pop-0.13#a83bf83784276aaa882ef13555295a2ad9edd265"
dependencies = [
"bitflags 2.6.0",
"mime",
"mime 0.1.0",
"raw-window-handle",
"smithay-client-toolkit",
"smithay-clipboard",
@ -2231,7 +2244,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -2549,7 +2562,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -2706,7 +2719,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -2974,9 +2987,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.15.1"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "hassle-rs"
@ -3096,7 +3109,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.87",
"syn 2.0.89",
"unic-langid",
]
@ -3110,7 +3123,7 @@ dependencies = [
"i18n-config",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -3139,7 +3152,7 @@ dependencies = [
[[package]]
name = "iced"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"dnd",
"iced_accessibility",
@ -3149,7 +3162,7 @@ dependencies = [
"iced_widget",
"iced_winit",
"image 0.24.9",
"mime",
"mime 0.1.0",
"thiserror",
"window_clipboard",
]
@ -3157,7 +3170,7 @@ dependencies = [
[[package]]
name = "iced_accessibility"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"accesskit",
"accesskit_winit",
@ -3166,7 +3179,7 @@ dependencies = [
[[package]]
name = "iced_core"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"bitflags 2.6.0",
"bytes",
@ -3174,7 +3187,7 @@ dependencies = [
"glam",
"iced_accessibility",
"log",
"mime",
"mime 0.1.0",
"num-traits",
"once_cell",
"palette",
@ -3191,7 +3204,7 @@ dependencies = [
[[package]]
name = "iced_futures"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"futures",
"iced_core",
@ -3217,7 +3230,7 @@ dependencies = [
[[package]]
name = "iced_graphics"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"bitflags 2.6.0",
"bytemuck",
@ -3239,7 +3252,7 @@ dependencies = [
[[package]]
name = "iced_renderer"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"iced_graphics",
"iced_tiny_skia",
@ -3251,7 +3264,7 @@ dependencies = [
[[package]]
name = "iced_runtime"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"bytes",
"dnd",
@ -3267,7 +3280,7 @@ dependencies = [
[[package]]
name = "iced_tiny_skia"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"bytemuck",
"cosmic-text",
@ -3283,7 +3296,7 @@ dependencies = [
[[package]]
name = "iced_wgpu"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"as-raw-xcb-connection",
"bitflags 2.6.0",
@ -3314,7 +3327,7 @@ dependencies = [
[[package]]
name = "iced_widget"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"dnd",
"iced_accessibility",
@ -3333,7 +3346,7 @@ dependencies = [
[[package]]
name = "iced_winit"
version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"dnd",
"iced_accessibility",
@ -3706,7 +3719,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -3875,7 +3888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown 0.15.1",
"hashbrown 0.15.2",
"serde",
]
@ -3944,7 +3957,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -4316,7 +4329,7 @@ checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
[[package]]
name = "libcosmic"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#525a14cfb1a735779a9fe970ff1726c8dbf1b217"
source = "git+https://github.com/pop-os/libcosmic#a9c7c3cdbfd586b090437647e3d380977780d520"
dependencies = [
"apply",
"ashpd 0.9.2",
@ -4476,9 +4489,9 @@ checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7"
[[package]]
name = "litemap"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]]
name = "litrs"
@ -4708,7 +4721,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -4719,6 +4732,12 @@ dependencies = [
"smithay-clipboard",
]
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -4965,7 +4984,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -5026,7 +5045,7 @@ dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -5333,7 +5352,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -5379,7 +5398,7 @@ dependencies = [
"by_address",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -5478,7 +5497,7 @@ dependencies = [
"phf_shared",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -5513,7 +5532,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -5682,14 +5701,14 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
name = "proc-macro2"
version = "1.0.89"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
@ -5702,7 +5721,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
"version_check",
"yansi",
]
@ -5746,7 +5765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
dependencies = [
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -5793,6 +5812,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "quick-xml"
version = "0.37.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f22f29bdff3987b4d8632ef95fd6424ec7e4e0a57e2f4fc63e489e75357f6a03"
dependencies = [
"memchr",
]
[[package]]
name = "quote"
version = "1.0.37"
@ -6157,7 +6185,7 @@ dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn 2.0.87",
"syn 2.0.89",
"walkdir",
]
@ -6365,7 +6393,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -6389,7 +6417,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -6428,7 +6456,7 @@ dependencies = [
"darling 0.20.10",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -6733,7 +6761,7 @@ dependencies = [
[[package]]
name = "superblock"
version = "0.1.0"
source = "git+https://github.com/serpent-os/blsforme.git#77c30adbfbc09cb54cd9f781fb7e5e5a563de3bf"
source = "git+https://github.com/serpent-os/blsforme.git#3c1ca74c220b2297338a2c4be8da55dcf3f438e8"
dependencies = [
"log",
"thiserror",
@ -6780,9 +6808,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.87"
version = "2.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
dependencies = [
"proc-macro2",
"quote",
@ -6797,7 +6825,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -6826,7 +6854,7 @@ dependencies = [
[[package]]
name = "system"
version = "0.1.0"
source = "git+https://github.com/serpent-os/lichen#f44a7c9e6faf48407d5d60b836517f40bae7b98b"
source = "git+https://github.com/serpent-os/lichen#ea0ed88d444068aeffbf505f1379dbc3d9757975"
dependencies = [
"fs-err",
"futures",
@ -6939,7 +6967,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -7102,7 +7130,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -7203,7 +7231,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -7408,9 +7436,9 @@ dependencies = [
[[package]]
name = "url"
version = "2.5.3"
version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
dependencies = [
"form_urlencoded",
"idna",
@ -7570,7 +7598,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
"wasm-bindgen-shared",
]
@ -7604,7 +7632,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -7725,7 +7753,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3"
dependencies = [
"proc-macro2",
"quick-xml",
"quick-xml 0.36.2",
"quote",
]
@ -7934,7 +7962,7 @@ dependencies = [
"clipboard_wayland",
"clipboard_x11",
"dnd",
"mime",
"mime 0.1.0",
"raw-window-handle",
"thiserror",
]
@ -8019,7 +8047,7 @@ checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -8030,7 +8058,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -8041,7 +8069,7 @@ checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -8052,7 +8080,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -8512,9 +8540,9 @@ checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1"
[[package]]
name = "yoke"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde",
"stable_deref_trait",
@ -8524,13 +8552,13 @@ dependencies = [
[[package]]
name = "yoke-derive"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
"synstructure",
]
@ -8632,7 +8660,7 @@ dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
"zvariant_utils 2.1.0",
]
@ -8682,27 +8710,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
name = "zerofrom"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
"synstructure",
]
@ -8742,7 +8770,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]
[[package]]
@ -8819,7 +8847,7 @@ dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
"zvariant_utils 2.1.0",
]
@ -8842,5 +8870,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.89",
]

View file

@ -42,6 +42,7 @@ itertools = "0.13.0"
itoa = "1.0.11"
libcosmic.workspace = true
locale1 = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
mime-apps = { package = "cosmic-mime-apps", git = "https://github.com/pop-os/cosmic-mime-apps", optional = true }
notify = "6.1.1"
once_cell = "1.19.0"
regex = "1.10.6"
@ -67,6 +68,7 @@ zbus = { version = "4.4.0", features = ["tokio"], optional = true }
ustr = "1.0.0"
fontdb = "0.16.2"
fixed_decimal = "0.5.6"
mime = "0.3.17"
[dependencies.cosmic-settings-subscriptions]
git = "https://github.com/pop-os/cosmic-settings-subscriptions"
@ -96,6 +98,7 @@ linux = [
"page-about",
"page-bluetooth",
"page-date",
"page-default-apps",
"page-input",
"page-networking",
"page-power",
@ -111,6 +114,7 @@ linux = [
page-about = ["dep:cosmic-settings-system", "dep:hostname1-zbus", "dep:zbus"]
page-bluetooth = ["dep:bluez-zbus", "dep:zbus"]
page-date = ["dep:timedate-zbus", "dep:zbus"]
page-default-apps = ["dep:mime-apps"]
page-input = [
"dep:cosmic-comp-config",
"dep:cosmic-settings-config",

View file

@ -51,7 +51,6 @@ use desktop::{
use event::wayland;
use page::Entity;
use std::collections::BTreeSet;
use std::time::Duration;
use std::{borrow::Cow, str::FromStr};
#[allow(clippy::struct_excessive_bools)]
@ -82,6 +81,8 @@ impl SettingsApp {
PageCommands::Bluetooth => self.pages.page_id::<bluetooth::Page>(),
#[cfg(feature = "page-date")]
PageCommands::DateTime => self.pages.page_id::<time::date::Page>(),
#[cfg(feature = "page-default-apps")]
PageCommands::DefaultApps => self.pages.page_id::<system::default_apps::Page>(),
PageCommands::Desktop => self.pages.page_id::<desktop::Page>(),
PageCommands::Displays => self.pages.page_id::<display::Page>(),
#[cfg(feature = "wayland")]
@ -212,10 +213,7 @@ impl cosmic::Application for SettingsApp {
}
.unwrap_or(desktop_id);
(
app,
cosmic::command::message(Message::DelayedInit(active_id)),
)
(app, cosmic::task::message(Message::DelayedInit(active_id)))
}
fn nav_model(&self) -> Option<&nav_bar::Model> {
@ -389,6 +387,13 @@ impl cosmic::Application for SettingsApp {
}
}
#[cfg(feature = "page-default-apps")]
crate::pages::Message::DefaultApps(message) => {
if let Some(page) = self.pages.page_mut::<system::default_apps::Page>() {
return page.update(message).map(Into::into);
}
}
crate::pages::Message::Desktop(message) => {
page::update!(self.pages, message, desktop::Page);
}
@ -718,7 +723,7 @@ impl cosmic::Application for SettingsApp {
// It is necessary to delay init to allow time for the page sender to be initialized
Message::DelayedInit(active_id) => {
if self.page_sender.is_none() {
return cosmic::command::message(Message::DelayedInit(active_id));
return cosmic::task::message(Message::DelayedInit(active_id));
}
return self.activate_page(active_id);
@ -832,7 +837,7 @@ impl SettingsApp {
Task::batch(vec![
leave_task,
page_task,
cosmic::command::future(async { Message::SetWindowTitle }),
cosmic::task::future(async { Message::SetWindowTitle }),
])
}
@ -1005,7 +1010,7 @@ impl SettingsApp {
if tasks.is_empty() {
Task::none()
} else {
cosmic::command::batch(tasks)
cosmic::task::batch(tasks)
.map(Message::PageMessage)
.map(Into::into)
}

View file

@ -49,6 +49,9 @@ pub enum PageCommands {
/// Date & Time settings page
#[cfg(feature = "page-date")]
DateTime,
/// Default application associations
#[cfg(feature = "page-default-apps")]
DefaultApps,
/// Desktop settings page
Desktop,
/// Displays settings page

View file

@ -78,7 +78,7 @@ impl page::Page<crate::pages::Message> for Page {
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> cosmic::Task<crate::pages::Message> {
// TODO start stream for new device
cosmic::command::future(async move {
cosmic::task::future(async move {
match zbus::Connection::system().await {
Ok(connection) => Message::DBusConnect(connection, sender),
Err(why) => Message::DBusError(why.to_string()),
@ -261,7 +261,7 @@ impl Page {
Active::Disabling
};
self.update_status();
return cosmic::command::future(change_adapter_status(
return cosmic::task::future(change_adapter_status(
connection.clone(),
path,
active,
@ -276,7 +276,7 @@ impl Page {
} else {
Active::Disabling
};
cosmic::command::future(change_adapter_status(
cosmic::task::future(change_adapter_status(
connection.clone(),
path.clone(),
active,
@ -284,7 +284,7 @@ impl Page {
})
.collect();
self.update_status();
return cosmic::command::batch(tasks);
return cosmic::task::batch(tasks);
}
tracing::warn!("No DBus connection ready");
}
@ -306,7 +306,7 @@ impl Page {
));
}
return cosmic::command::future(async move {
return cosmic::task::future(async move {
let result: zbus::Result<HashMap<OwnedObjectPath, Adapter>> = async {
futures::future::join_all(
bluez_zbus::get_adapters(&connection)
@ -342,7 +342,7 @@ impl Page {
self.update_status();
if self.selected_adapter.is_none() && self.adapters.len() == 1 {
return cosmic::command::message(Message::SelectAdapter(
return cosmic::task::message(Message::SelectAdapter(
self.adapters.keys().next().cloned(),
));
}
@ -365,7 +365,7 @@ impl Page {
tracing::debug!("Adapter {} added", adapter.address);
self.adapters.insert(path.clone(), adapter);
if self.selected_adapter.is_none() {
return cosmic::command::message(Message::SelectAdapter(Some(path)));
return cosmic::task::message(Message::SelectAdapter(Some(path)));
}
}
Message::UpdatedAdapter(path, update) => {
@ -381,7 +381,7 @@ impl Page {
&& existing.scanning == Active::Disabled =>
{
existing.scanning = Active::Enabling;
return cosmic::command::future(start_discovery(connection, path));
return cosmic::task::future(start_discovery(connection, path));
}
_ => {}
}
@ -412,19 +412,20 @@ impl Page {
if let Some(connection) = self.connection.as_ref() {
let connection = connection.clone();
if let Some((path, adapter)) = self.get_selected_adapter_mut() {
let mut fut: Vec<Task<Message>> = vec![cosmic::command::future(
get_devices(connection.clone(), path.clone()),
)];
let mut fut: Vec<Task<Message>> = vec![cosmic::task::future(get_devices(
connection.clone(),
path.clone(),
))];
if adapter.enabled == Active::Enabled
&& adapter.scanning == Active::Disabled
{
fut.push(cosmic::command::future(start_discovery(
fut.push(cosmic::task::future(start_discovery(
connection,
path.clone(),
)));
}
return cosmic::command::batch(fut);
return cosmic::task::batch(fut);
}
} else {
tracing::warn!("No DBus connection ready");
@ -440,7 +441,7 @@ impl Page {
let connection = connection.clone();
if let Some(device) = self.devices.get_mut(&path) {
device.enabled = Active::Disabling;
return cosmic::command::future(forget_device(connection, path.clone()));
return cosmic::task::future(forget_device(connection, path.clone()));
}
} else {
tracing::warn!("No DBus connection ready");
@ -458,7 +459,7 @@ impl Page {
return cosmic::Task::none();
}
device.enabled = Active::Enabling;
return cosmic::command::future(connect_device(connection, path));
return cosmic::task::future(connect_device(connection, path));
}
} else {
tracing::warn!("No DBus connection ready");
@ -474,7 +475,7 @@ impl Page {
return cosmic::Task::none();
}
device.enabled = Active::Disabling;
return cosmic::command::future(disconnect_device(connection, path));
return cosmic::task::future(disconnect_device(connection, path));
}
} else {
tracing::warn!("No DBus connection ready");

View file

@ -22,7 +22,7 @@ use cosmic::iced_widget::scrollable::{Direction, Scrollbar};
use cosmic::widget::icon::{from_name, icon};
use cosmic::widget::{
button, color_picker::ColorPickerUpdate, container, flex_row, horizontal_space, radio, row,
scrollable, settings, spin_button, text, ColorPickerModel,
scrollable, settings, text, ColorPickerModel,
};
use cosmic::{widget, Apply, Element, Task};
#[cfg(feature = "wayland")]
@ -387,7 +387,7 @@ impl Page {
)
),
// Icon theme previews
cosmic::widget::column::with_children(vec![
widget::column::with_children(vec![
text::heading(&*ICON_THEME).into(),
flex_row(
self.icon_themes
@ -424,7 +424,7 @@ impl Page {
self.context_view = Some(ContextView::MonospaceFont);
self.font_search.clear();
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
return cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
fl!("monospace-font").into(),
));
@ -434,7 +434,7 @@ impl Page {
self.context_view = Some(ContextView::SystemFont);
self.font_search.clear();
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
return cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
fl!("interface-font").into(),
));
@ -781,7 +781,7 @@ impl Page {
}
Message::Left => {
tasks.push(cosmic::command::message(app::Message::SetTheme(
tasks.push(cosmic::task::message(app::Message::SetTheme(
cosmic::theme::system_preference(),
)));
}
@ -865,7 +865,7 @@ impl Page {
#[cfg(feature = "ashpd")]
Message::StartImport => {
tasks.push(cosmic::command::future(async move {
tasks.push(cosmic::task::future(async move {
let res = SelectedFiles::open_file()
.modal(true)
.filter(FileFilter::glob(FileFilter::new("ron"), "*.ron"))
@ -888,7 +888,7 @@ impl Page {
let is_dark = self.theme_mode.is_dark;
let name = format!("{}.ron", if is_dark { fl!("dark") } else { fl!("light") });
tasks.push(cosmic::command::future(async move {
tasks.push(cosmic::task::future(async move {
let res = SelectedFiles::save_file()
.modal(true)
.current_name(Some(name.as_str()))
@ -918,7 +918,7 @@ impl Page {
return Task::none();
};
tasks.push(cosmic::command::future(async move {
tasks.push(cosmic::task::future(async move {
let res = tokio::fs::read_to_string(path).await;
if let Some(b) = res.ok().and_then(|s| ron::de::from_str(&s).ok()) {
Message::ImportSuccess(Box::new(b))
@ -944,7 +944,7 @@ impl Page {
let theme_builder = self.theme_builder.clone();
tasks.push(cosmic::command::future(async move {
tasks.push(cosmic::task::future(async move {
let Ok(builder) =
ron::ser::to_string_pretty(&theme_builder, PrettyConfig::default())
else {
@ -1062,7 +1062,7 @@ impl Page {
Message::IconsAndToolkit => {
self.context_view = Some(ContextView::IconsAndToolkit);
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
return cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
"".into(),
));
@ -1080,7 +1080,7 @@ impl Page {
let is_dark = self.theme_mode.is_dark;
let current_theme = self.theme.clone();
tasks.push(cosmic::command::future(async move {
tasks.push(cosmic::task::future(async move {
let config = if is_dark {
Theme::dark_config()
} else {
@ -1180,7 +1180,7 @@ impl Page {
let task = match message {
ColorPickerUpdate::AppliedColor | ColorPickerUpdate::Reset => {
needs_update = true;
cosmic::command::message(crate::app::Message::CloseContextDrawer)
cosmic::task::message(crate::app::Message::CloseContextDrawer)
}
ColorPickerUpdate::ActionFinished => {
@ -1189,12 +1189,12 @@ impl Page {
}
ColorPickerUpdate::Cancel => {
cosmic::command::message(crate::app::Message::CloseContextDrawer)
cosmic::task::message(crate::app::Message::CloseContextDrawer)
}
ColorPickerUpdate::ToggleColorPicker => {
self.context_view = Some(context_view);
cosmic::command::message(crate::app::Message::OpenContextDrawer(
cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
context_title,
))
@ -1436,11 +1436,11 @@ impl page::Page<crate::pages::Message> for Page {
&mut self,
_sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> Task<crate::pages::Message> {
let (task, handle) = cosmic::command::batch(vec![
let (task, handle) = cosmic::task::batch(vec![
// Load icon themes
cosmic::command::future(icon_themes::fetch()).map(crate::pages::Message::Appearance),
cosmic::task::future(icon_themes::fetch()).map(crate::pages::Message::Appearance),
// Load font families
cosmic::command::future(async move {
cosmic::task::future(async move {
let (mono, interface) = font_config::load_font_families();
Message::FontConfig(font_config::Message::LoadedFonts(mono, interface))
})
@ -1457,7 +1457,7 @@ impl page::Page<crate::pages::Message> for Page {
handle.abort();
}
cosmic::command::message(crate::pages::Message::Appearance(Message::Left))
cosmic::task::message(crate::pages::Message::Appearance(Message::Left))
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
@ -1971,7 +1971,7 @@ pub fn window_management() -> Section<crate::pages::Message> {
settings::section()
.title(&section.title)
.add(settings::item::builder(&descriptions[active_hint]).control(
cosmic::widget::spin_button(
widget::spin_button(
page.theme_builder.active_hint.to_string(),
page.theme_builder.active_hint,
1,
@ -1980,16 +1980,16 @@ pub fn window_management() -> Section<crate::pages::Message> {
Message::WindowHintSize,
),
))
.add(settings::item::builder(&descriptions[gaps]).control(
cosmic::widget::spin_button(
.add(
settings::item::builder(&descriptions[gaps]).control(widget::spin_button(
page.theme_builder.gaps.1.to_string(),
page.theme_builder.gaps.1,
1,
page.theme.active_hint,
500,
Message::GapSize,
),
))
)),
)
.apply(Element::from)
.map(crate::pages::Message::Appearance)
})

View file

@ -442,7 +442,7 @@ impl Page {
}
Message::AddAppletDrawer => {
self.context = Some(ContextDrawer::AddApplet);
return cosmic::command::message(app::Message::OpenContextDrawer(
return cosmic::task::message(app::Message::OpenContextDrawer(
self.entity,
Cow::Owned(fl!("add-applet")),
));

View file

@ -577,7 +577,7 @@ impl Page {
Category::Wallpapers => {
if self.config.current_folder.is_some() {
let _ = self.config.set_current_folder(None);
task = cosmic::command::future(async move {
task = cosmic::task::future(async move {
let folder = change_folder(Config::default_folder().to_owned(), true).await;
Message::ChangeFolder(folder)
});
@ -597,7 +597,7 @@ impl Page {
tracing::error!(?path, ?why, "failed to set current folder");
}
task = cosmic::command::future(async move {
task = cosmic::task::future(async move {
Message::ChangeFolder(change_folder(path, false).await)
});
}
@ -605,7 +605,7 @@ impl Page {
Category::AddFolder => {
#[cfg(feature = "xdg-portal")]
return cosmic::command::future(async {
return cosmic::task::future(async {
let dialog_result = file_chooser::open::Dialog::new()
.title(fl!("wallpaper", "folder-dialog"))
.accept_label(fl!("dialog-add"))
@ -751,7 +751,7 @@ impl Page {
Message::ColorAddContext => {
self.context_view = Some(ContextView::AddColor);
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
return cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
fl!("color-picker").into(),
));
@ -972,20 +972,20 @@ impl Page {
}
// Load preview images concurrently for each custom image stored in the on-disk config.
return cosmic::command::batch(
return cosmic::task::batch(
self.config
.custom_images()
.iter()
.cloned()
.map(|path| {
cosmic::command::future(async move {
cosmic::task::future(async move {
let result = wallpaper::load_image_with_thumbnail(path);
Message::ImageAdd(result.map(Arc::new))
})
})
// Cache wallpaper preview early to prevent blank previews on reload
.chain(std::iter::once(cosmic::command::message::<
.chain(std::iter::once(cosmic::task::message::<
_,
crate::app::Message,
>(

View file

@ -277,7 +277,7 @@ impl page::Page<crate::pages::Message> for Page {
}));
}
cosmic::command::future(on_enter())
cosmic::task::future(on_enter())
}
fn on_leave(&mut self) -> Task<crate::pages::Message> {
@ -293,7 +293,7 @@ impl page::Page<crate::pages::Message> for Page {
&mut self,
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> Task<crate::pages::Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
let mut randr = List::default();
let test_mode = randr.modes.insert(cosmic_randr_shell::Mode {
@ -380,7 +380,7 @@ impl Page {
tracing::error!(?why, "cosmic-randr error");
} else {
// Reload display info
return cosmic::command::future(async move {
return cosmic::task::future(async move {
crate::Message::PageMessage(on_enter().await)
});
}
@ -406,11 +406,11 @@ impl Page {
Message::DialogCountdown => {
if self.dialog_countdown == 0 {
if self.dialog.is_some() {
return cosmic::command::message(app::Message::from(Message::DialogCancel));
return cosmic::task::message(app::Message::from(Message::DialogCancel));
}
} else {
self.dialog_countdown -= 1;
return cosmic::command::future(async move {
return cosmic::task::future(async move {
tokio::time::sleep(time::Duration::from_secs(1)).await;
Message::DialogCountdown
});
@ -449,7 +449,7 @@ impl Page {
//
// Message::NightLightContext => {
// self.context = Some(ContextDrawer::NightLight);
// return cosmic::command::message(app::Message::OpenContextDrawer(
// return cosmic::task::message(app::Message::OpenContextDrawer(
// text::NIGHT_LIGHT.clone().into(),
// ));
// }
@ -473,7 +473,7 @@ impl Page {
Message::Position(display, x, y) => return self.set_position(display, x, y),
Message::Refresh => {
return cosmic::command::future(async move {
return cosmic::task::future(async move {
crate::Message::PageMessage(on_enter().await)
});
}
@ -583,7 +583,7 @@ impl Page {
}
self.dialog = Some(revert_request);
self.dialog_countdown = 10;
cosmic::command::future(async {
cosmic::task::future(async {
tokio::time::sleep(time::Duration::from_secs(1)).await;
app::Message::from(Message::DialogCountdown)
})
@ -872,7 +872,7 @@ impl Page {
// Removes the dialog if no change is being made
if Some(request) == self.dialog {
tasks.push(cosmic::command::message(app::Message::from(
tasks.push(cosmic::task::message(app::Message::from(
Message::DialogComplete,
)));
}
@ -970,7 +970,7 @@ impl Page {
}
}
tasks.push(cosmic::command::future(async move {
tasks.push(cosmic::task::future(async move {
tracing::debug!(?task, "executing");
app::Message::from(Message::RandrResult(Arc::new(task.status().await)))
}));

View file

@ -460,7 +460,7 @@ impl Page {
Message::ShowInputSourcesContext => {
self.context = Some(Context::ShowInputSourcesContext);
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
return cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
fl!("keyboard-sources", "add").into(),
));
@ -472,7 +472,7 @@ impl Page {
Message::OpenSpecialCharacterContext(key) => {
self.context = Some(Context::SpecialCharacter(key));
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
return cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
key.title().into(),
));

View file

@ -393,7 +393,7 @@ impl Model {
self.shortcut_context = Some(id);
self.replace_dialog = None;
let mut tasks = vec![cosmic::command::message(
let mut tasks = vec![cosmic::task::message(
crate::app::Message::OpenContextDrawer(self.entity, description.into()),
)];

View file

@ -212,7 +212,7 @@ impl Page {
Message::ShortcutContext => {
self.add_shortcut.enable();
return Task::batch(vec![
cosmic::command::message(crate::app::Message::OpenContextDrawer(
cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
fl!("custom-shortcuts", "context").into(),
)),

View file

@ -221,28 +221,28 @@ impl Page {
match message {
Message::Category(category) => match category {
Category::Custom => {
cosmic::command::message(crate::app::Message::Page(self.sub_pages.custom))
cosmic::task::message(crate::app::Message::Page(self.sub_pages.custom))
}
Category::ManageWindow => cosmic::command::message(crate::app::Message::Page(
self.sub_pages.manage_window,
)),
Category::ManageWindow => {
cosmic::task::message(crate::app::Message::Page(self.sub_pages.manage_window))
}
Category::MoveWindow => {
cosmic::command::message(crate::app::Message::Page(self.sub_pages.move_window))
cosmic::task::message(crate::app::Message::Page(self.sub_pages.move_window))
}
Category::Nav => {
cosmic::command::message(crate::app::Message::Page(self.sub_pages.nav))
cosmic::task::message(crate::app::Message::Page(self.sub_pages.nav))
}
Category::System => {
cosmic::command::message(crate::app::Message::Page(self.sub_pages.system))
cosmic::task::message(crate::app::Message::Page(self.sub_pages.system))
}
Category::WindowTiling => cosmic::command::message(crate::app::Message::Page(
self.sub_pages.window_tiling,
)),
Category::WindowTiling => {
cosmic::task::message(crate::app::Message::Page(self.sub_pages.window_tiling))
}
},
Message::Search(input) => {

View file

@ -29,6 +29,8 @@ pub enum Message {
CustomShortcuts(input::keyboard::shortcuts::custom::Message),
#[cfg(feature = "page-date")]
DateAndTime(time::date::Message),
#[cfg(feature = "page-default-apps")]
DefaultApps(system::default_apps::Message),
Desktop(desktop::Message),
DesktopWallpaper(desktop::wallpaper::Message),
#[cfg(feature = "page-workspaces")]

View file

@ -289,10 +289,10 @@ impl Page {
Message::OpenPage { page, device } => {
let mut tasks = Vec::<Task<crate::app::Message>>::new();
tasks.push(cosmic::command::message(crate::app::Message::Page(page)));
tasks.push(cosmic::task::message(crate::app::Message::Page(page)));
if let Some(device) = device {
tasks.push(cosmic::command::message(crate::app::Message::PageMessage(
tasks.push(cosmic::task::message(crate::app::Message::PageMessage(
match device {
DeviceVariant::WiFi(device) => {
crate::pages::Message::WiFi(wifi::Message::SelectDevice(device))

View file

@ -339,7 +339,7 @@ impl page::Page<crate::pages::Message> for Page {
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> cosmic::Task<crate::pages::Message> {
if self.nm_task.is_none() {
return cosmic::command::future(async move {
return cosmic::task::future(async move {
zbus::Connection::system()
.await
.context("failed to create system dbus connection")
@ -455,7 +455,7 @@ impl Page {
Message::WireGuardConfig => {
if let Some(VpnDialog::WireGuardName(device, filename, path)) = self.dialog.take() {
return cosmic::command::future(async move {
return cosmic::task::future(async move {
let new_path = path.replace(&filename, &device);
_ = std::fs::rename(&path, &new_path);
match super::nm_add_vpn_file("wireguard", new_path).await {
@ -474,7 +474,7 @@ impl Page {
ConnectionSettings::Vpn(ref settings) => settings,
ConnectionSettings::Wireguard { id } => {
let connection_name = id.clone();
return cosmic::command::future(async move {
return cosmic::task::future(async move {
if let Err(why) = nmcli::connect(&connection_name).await {
return Message::Error(
ErrorKind::Connect,
@ -501,7 +501,7 @@ impl Page {
_ => {
let connection_name = settings.id.clone();
return cosmic::command::future(async move {
return cosmic::task::future(async move {
if let Err(why) = nmcli::connect(&connection_name).await {
return Message::Error(
ErrorKind::Connect,
@ -546,7 +546,7 @@ impl Page {
Message::Settings(uuid) => {
self.close_popup_and_apply_updates();
return cosmic::command::future(async move {
return cosmic::task::future(async move {
super::nm_edit_connection(uuid.as_ref())
.then(|res| async move {
match res {
@ -639,7 +639,7 @@ impl Page {
username: String,
password: SecureString,
) -> Task<Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
if let Err(why) = nmcli::set_username(&connection_name, &username).await {
return Message::Error(ErrorKind::WithPassword("username"), why.to_string());
}
@ -866,7 +866,7 @@ fn popup_button(message: Message, text: &str) -> Element<'_, Message> {
}
fn update_state(conn: zbus::Connection) -> Task<crate::app::Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
match NetworkManagerState::new(&conn).await {
Ok(state) => Message::UpdateState(state),
Err(why) => Message::Error(ErrorKind::UpdatingState, why.to_string()),
@ -875,7 +875,7 @@ fn update_state(conn: zbus::Connection) -> Task<crate::app::Message> {
}
fn update_devices(conn: zbus::Connection) -> Task<crate::app::Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
let filter =
|device_type| matches!(device_type, network_manager::devices::DeviceType::WireGuard);
@ -938,7 +938,7 @@ fn add_network() -> Task<crate::app::Message> {
}
}
})
.apply(cosmic::command::future)
.apply(cosmic::task::future)
}
fn connection_settings(conn: zbus::Connection) -> Task<crate::app::Message> {
@ -1040,7 +1040,7 @@ fn connection_settings(conn: zbus::Connection) -> Task<crate::app::Message> {
Ok::<_, zbus::Error>(settings)
};
cosmic::command::future(async move {
cosmic::task::future(async move {
settings.await.map_or_else(
|why| Message::Error(ErrorKind::ConnectionSettings, why.to_string()),
Message::KnownConnections,

View file

@ -776,7 +776,7 @@ fn connection_settings(conn: zbus::Connection) -> Task<crate::app::Message> {
Ok::<_, zbus::Error>(settings)
};
cosmic::command::future(async move {
cosmic::task::future(async move {
settings
.await
.context("failed to get connection settings")
@ -789,7 +789,7 @@ fn connection_settings(conn: zbus::Connection) -> Task<crate::app::Message> {
}
pub fn update_state(conn: zbus::Connection) -> Task<crate::app::Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
match NetworkManagerState::new(&conn).await {
Ok(state) => Message::UpdateState(state),
Err(why) => Message::Error(why.to_string()),
@ -798,7 +798,7 @@ pub fn update_state(conn: zbus::Connection) -> Task<crate::app::Message> {
}
pub fn update_devices(conn: zbus::Connection) -> Task<crate::app::Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
let filter =
|device_type| matches!(device_type, network_manager::devices::DeviceType::Wifi);
match network_manager::devices::list(&conn, filter).await {

View file

@ -161,7 +161,7 @@ impl page::Page<crate::pages::Message> for Page {
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> cosmic::Task<crate::pages::Message> {
if self.nm_task.is_none() {
return cosmic::command::future(async move {
return cosmic::task::future(async move {
zbus::Connection::system()
.await
.context("failed to create system dbus connection")
@ -265,7 +265,7 @@ impl Page {
Message::NetworkManager(_event) => (),
Message::AddNetwork => {
return cosmic::command::future(async move {
return cosmic::task::future(async move {
_ = super::nm_add_wired().await;
// TODO: Update when iced is rebased to use then method.
Message::Refresh
@ -332,7 +332,7 @@ impl Page {
Message::Settings(uuid) => {
self.close_popup_and_apply_updates();
return cosmic::command::future(async move {
return cosmic::task::future(async move {
_ = super::nm_edit_connection(uuid.as_ref()).await;
// TODO: Update when iced is rebased to use then method.
Message::Refresh
@ -618,7 +618,7 @@ fn popup_button(message: Message, text: &str) -> Element<'_, Message> {
}
fn update_state(conn: zbus::Connection) -> Task<crate::app::Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
match NetworkManagerState::new(&conn).await {
Ok(state) => Message::UpdateState(state),
Err(why) => Message::Error(why.to_string()),
@ -627,7 +627,7 @@ fn update_state(conn: zbus::Connection) -> Task<crate::app::Message> {
}
fn update_devices(conn: zbus::Connection) -> Task<crate::app::Message> {
cosmic::command::future(async move {
cosmic::task::future(async move {
let filter =
|device_type| matches!(device_type, network_manager::devices::DeviceType::Ethernet);

View file

@ -308,7 +308,7 @@ impl Page {
let mut command = None;
if let Some(&node_id) = self.source_ids.get(self.active_source.unwrap_or(0)) {
command = Some(cosmic::command::future(async move {
command = Some(cosmic::task::future(async move {
tokio::time::sleep(Duration::from_millis(64)).await;
crate::pages::Message::Sound(Message::SourceVolumeApply(node_id))
}));
@ -338,7 +338,7 @@ impl Page {
let mut command = None;
if let Some(&node_id) = self.sink_ids.get(self.active_sink.unwrap_or(0)) {
command = Some(cosmic::command::future(async move {
command = Some(cosmic::task::future(async move {
tokio::time::sleep(Duration::from_millis(64)).await;
crate::pages::Message::Sound(Message::SinkVolumeApply(node_id))
}));
@ -542,7 +542,7 @@ impl Page {
.insert(device_id.clone(), Some(profile.clone()));
self.changing_sink_profile = true;
return cosmic::command::future(async move {
return cosmic::task::future(async move {
pactl_set_card_profile(name, profile).await;
Message::SinkProfileSelect(device_id)
})
@ -574,7 +574,7 @@ impl Page {
.insert(device_id.clone(), Some(profile.clone()));
self.changing_source_profile = true;
return cosmic::command::future(async move {
return cosmic::task::future(async move {
pactl_set_card_profile(name, profile).await;
Message::SourceProfileSelect(device_id)
})

View file

@ -0,0 +1,414 @@
// Copyright 2024 System76 <info@system76.com>
// Copyright 2024 bbb651 <bar.ye651@gmail.com>
// SPDX-License-Identifier: GPL-3.0-only
use std::{
collections::{BTreeMap, BTreeSet},
path::{Path, PathBuf},
sync::Arc,
};
use cosmic::{
widget::{self, dropdown, icon, settings},
Apply, Element, Task,
};
use cosmic_settings_page::{self as page, section, Section};
use mime_apps::App;
use slotmap::SlotMap;
use tokio::sync::mpsc;
const DROPDOWN_WEB_BROWSER: usize = 0;
const DROPDOWN_FILE_MANAGER: usize = 1;
const DROPDOWN_MAIL: usize = 2;
const DROPDOWN_MUSIC: usize = 3;
const DROPDOWN_VIDEO: usize = 4;
const DROPDOWN_PHOTO: usize = 5;
const DROPDOWN_CALENDAR: usize = 6;
// const DROPDOWN_TERMINAL: usize = 7;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum Category {
Audio,
Calendar,
FileManager,
Image,
Mail,
Mime(&'static str),
// Terminal,
Video,
WebBrowser,
}
#[derive(Clone, Debug)]
pub enum Message {
SetDefault(Category, usize),
Update(CachedMimeApps),
}
impl From<Message> for crate::app::Message {
fn from(message: Message) -> Self {
crate::pages::Message::DefaultApps(message).into()
}
}
impl From<Message> for crate::pages::Message {
fn from(message: Message) -> Self {
crate::pages::Message::DefaultApps(message)
}
}
#[derive(Clone, Debug)]
pub struct CachedMimeApps {
pub list: mime_apps::List,
pub local_list: mime_apps::List,
pub apps: Vec<AppMeta>,
pub known_mimes: BTreeSet<mime::Mime>,
pub config_path: Box<Path>,
}
#[derive(Clone, Debug)]
pub struct AppMeta {
selected: Option<usize>,
app_ids: Vec<String>,
apps: Vec<String>,
icons: Vec<icon::Handle>,
}
#[derive(Clone, Debug, Default)]
pub struct Page {
on_enter_handle: Option<cosmic::iced::task::Handle>,
mime_apps: Option<CachedMimeApps>,
}
impl page::AutoBind<crate::pages::Message> for Page {}
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<cosmic_settings_page::Content> {
Some(vec![sections.insert(apps())])
}
fn info(&self) -> page::Info {
page::Info::new("default-apps", "application-default-symbolic")
.title(fl!("default-apps"))
.description(fl!("default-apps", "desc"))
}
fn on_enter(
&mut self,
_sender: mpsc::Sender<crate::pages::Message>,
) -> Task<crate::pages::Message> {
let (task, on_enter_handle) = Task::future(async move {
let mut list = mime_apps::List::default();
list.load_from_paths(&mime_apps::list_paths());
let mut local_list = mime_apps::List::default();
if let Some(path) = mime_apps::local_list_path() {
if let Ok(buffer) = std::fs::read_to_string(&path) {
local_list.load_from(&buffer);
}
}
let assocs = mime_apps::associations::by_app();
let apps = vec![
load_defaults(&assocs, "x-scheme-handler/http").await,
load_defaults(&assocs, "inode/directory").await,
load_defaults(&assocs, "x-scheme-handler/mailto").await,
load_defaults(&assocs, "audio/mp3").await,
load_defaults(&assocs, "video/mp4").await,
load_defaults(&assocs, "image/png").await,
load_defaults(&assocs, "text/calendar").await,
AppMeta {
selected: None,
app_ids: Vec::new(),
apps: Vec::new(),
icons: Vec::new(),
},
];
Message::Update(CachedMimeApps {
apps,
list,
local_list,
known_mimes: mime_apps::mime_info::mime_types(),
config_path: dirs::config_dir()
.expect("config dir not found")
.join("mimeapps.list")
.into(),
})
.into()
})
.abortable();
self.on_enter_handle = Some(on_enter_handle);
task
}
fn on_leave(&mut self) -> Task<crate::pages::Message> {
if let Some(handle) = self.on_enter_handle.take() {
handle.abort();
}
self.mime_apps = None;
Task::none()
}
}
impl Page {
pub fn update(&mut self, message: Message) -> Task<crate::Message> {
match message {
Message::SetDefault(category, id) => {
let Some(mime_apps) = self.mime_apps.as_mut() else {
return Task::none();
};
let mime_types: Vec<&str>;
let (category_id, mime_types): (usize, &[&str]) = match category {
Category::Audio => (DROPDOWN_MUSIC, {
mime_types = mime_apps
.known_mimes
.iter()
.map(|m| m.essence_str())
.filter(|m| m.starts_with("audio"))
.chain(
[
"application/ogg",
"application/x-cue",
"application/x-ogg",
"x-content/audio-cdda",
]
.into_iter(),
)
.collect();
&mime_types
}),
Category::Calendar => (DROPDOWN_CALENDAR, &["text/calendar"]),
Category::FileManager => (DROPDOWN_FILE_MANAGER, &["inode/directory"]),
Category::Image => (DROPDOWN_PHOTO, {
mime_types = mime_apps
.known_mimes
.iter()
.map(|m| m.essence_str())
.filter(|m| m.starts_with("image"))
.collect();
&mime_types
}),
Category::Mail => (DROPDOWN_MAIL, &["x-scheme-handler/mailto"]),
// Category::Terminal => (DROPDOWN_TERMINAL, &[]),
Category::Video => (DROPDOWN_VIDEO, {
mime_types = mime_apps
.known_mimes
.iter()
.map(|m| m.essence_str())
.filter(|m| m.starts_with("video"))
.collect();
&mime_types
}),
Category::WebBrowser => (
DROPDOWN_WEB_BROWSER,
&[
"text/html",
"application/xhtml+xml",
"x-scheme-handler/chrome",
"x-scheme-handler/http",
"x-scheme-handler/https",
],
),
Category::Mime(_mime_type) => return Task::none(),
};
let meta = &mut mime_apps.apps[category_id];
if meta.selected != Some(id) {
meta.selected = Some(id);
let appid = &meta.app_ids[id];
for mime in mime_types {
if let Ok(mime) = mime.parse() {
mime_apps
.local_list
.set_default_app(mime, [appid, ".desktop"].concat());
};
}
let mut buffer = mime_apps.local_list.to_string();
buffer.push('\n');
_ = std::fs::write(&mime_apps.config_path, buffer);
_ = std::process::Command::new("update-desktop-database").status();
}
}
Message::Update(mime_apps) => {
self.mime_apps = Some(mime_apps);
}
}
Task::none()
}
}
fn apps() -> Section<crate::pages::Message> {
Section::default().view::<Page>(move |_binder, page, section| {
let Some(mime_apps) = page.mime_apps.as_ref() else {
return widget::row().into();
};
settings::section()
.title(&section.title)
.add({
let meta = &mime_apps.apps[DROPDOWN_WEB_BROWSER];
settings::flex_item(
fl!("default-apps", "web-browser"),
dropdown(&meta.apps, meta.selected, |id| {
Message::SetDefault(Category::WebBrowser, id)
})
.icons(&meta.icons),
)
.min_item_width(300.0)
})
.add({
let meta = &mime_apps.apps[DROPDOWN_FILE_MANAGER];
settings::flex_item(
fl!("default-apps", "file-manager"),
dropdown(&meta.apps, meta.selected, |id| {
Message::SetDefault(Category::FileManager, id)
})
.icons(&meta.icons),
)
})
.add({
let meta = &mime_apps.apps[DROPDOWN_MAIL];
settings::flex_item(
fl!("default-apps", "mail-client"),
dropdown(&meta.apps, meta.selected, |id| {
Message::SetDefault(Category::Mail, id)
})
.icons(&meta.icons),
)
})
.add({
let meta = &mime_apps.apps[DROPDOWN_MUSIC];
settings::flex_item(
fl!("default-apps", "music"),
dropdown(&meta.apps, meta.selected, |id| {
Message::SetDefault(Category::Audio, id)
})
.icons(&meta.icons),
)
})
.add({
let meta = &mime_apps.apps[DROPDOWN_VIDEO];
settings::flex_item(
fl!("default-apps", "video"),
dropdown(&meta.apps, meta.selected, |id| {
Message::SetDefault(Category::Video, id)
})
.icons(&meta.icons),
)
})
.add({
let meta = &mime_apps.apps[DROPDOWN_PHOTO];
settings::flex_item(
fl!("default-apps", "photos"),
dropdown(&meta.apps, meta.selected, |id| {
Message::SetDefault(Category::Image, id)
})
.icons(&meta.icons),
)
})
.add({
let meta = &mime_apps.apps[DROPDOWN_CALENDAR];
settings::flex_item(
fl!("default-apps", "calendar"),
dropdown(&meta.apps, meta.selected, |id| {
Message::SetDefault(Category::Calendar, id)
})
.icons(&meta.icons),
)
})
// TODO: Decide on a mechanism for getting and setting the default terminal.
// .add({
// let meta = &mime_apps.apps[DROPDOWN_TERMINAL];
// settings::flex_item(
// fl!("default-apps", "terminal"),
// dropdown(&meta.apps, meta.selected, |id| {
// Message::SetDefault(Category::Terminal, id)
// })
// .icons(&meta.icons),
// )
// })
.apply(Element::from)
.map(crate::pages::Message::DefaultApps)
})
}
async fn load_defaults(assocs: &BTreeMap<Arc<str>, Arc<App>>, for_mime: &str) -> AppMeta {
let Ok(mime) = for_mime.parse() else {
return AppMeta {
selected: None,
app_ids: Vec::new(),
apps: Vec::new(),
icons: Vec::new(),
};
};
let current_app_entry = xdg_mime_query_default(for_mime).await;
let current_appid = current_app_entry
.as_ref()
.and_then(|entry| entry.strip_suffix(".desktop"));
let current_app = current_appid.and_then(|appid| assocs.get(appid));
let mut unsorted = mime_apps::apps_for_mime(&mime, assocs).collect::<Vec<_>>();
unsorted.sort_unstable_by_key(|(_, app)| &app.name);
let mut selected = None;
let mut app_ids = Vec::new();
let mut apps = Vec::new();
let mut icons = Vec::new();
for (id, (appid, app)) in unsorted.iter().enumerate() {
if let Some(current_app) = current_app {
if app.name.as_ref() == current_app.name.as_ref() {
selected = Some(id);
}
}
app_ids.push(appid.as_ref().into());
apps.push(app.name.as_ref().into());
icons.push(if app.icon.starts_with('/') {
icon::from_path(PathBuf::from(app.icon.as_ref()))
} else {
icon::from_name(app.icon.as_ref()).size(20).handle()
});
}
AppMeta {
selected,
app_ids,
apps,
icons,
}
}
async fn xdg_mime_query_default(mime_type: &str) -> Option<String> {
let output = tokio::process::Command::new("xdg-mime")
.args(&["query", "default", mime_type])
.output()
.await
.ok()?;
if !output.status.success() {
return None;
}
String::from_utf8(output.stdout)
.ok()
.map(|string| string.trim().to_owned())
}

View file

@ -3,6 +3,8 @@
#[cfg(feature = "page-about")]
pub mod about;
#[cfg(feature = "page-default-apps")]
pub mod default_apps;
pub mod firmware;
pub mod users;
@ -33,6 +35,10 @@ impl page::AutoBind<crate::pages::Message> for Page {
page = page.sub_page::<about::Page>();
}
page = page.sub_page::<firmware::Page>();
#[cfg(feature = "page-default-apps")]
{
page = page.sub_page::<default_apps::Page>();
}
page
}
}

View file

@ -183,7 +183,7 @@ impl Page {
Message::TimezoneContext => {
self.timezone_search.clear();
self.timezone_context = true;
return cosmic::command::message(crate::app::Message::OpenContextDrawer(
return cosmic::task::message(crate::app::Message::OpenContextDrawer(
self.entity,
fl!("time-zone").into(),
));
@ -262,14 +262,14 @@ impl Page {
Message::Error(why) => {
tracing::error!(why, "failed to set timezone");
self.timezone_context = false;
return cosmic::command::message(crate::Message::CloseContextDrawer);
return cosmic::task::message(crate::Message::CloseContextDrawer);
}
Message::UpdateTime => {
self.set_ntp(true);
self.update_local_time();
self.timezone_context = false;
return cosmic::command::message(crate::Message::CloseContextDrawer);
return cosmic::task::message(crate::Message::CloseContextDrawer);
}
Message::Refresh(info) => {

View file

@ -139,7 +139,7 @@ impl page::Page<crate::pages::Message> for Page {
&mut self,
_sender: mpsc::Sender<crate::pages::Message>,
) -> cosmic::Task<crate::pages::Message> {
cosmic::command::future(async move { Message::Refresh(Arc::new(page_reload().await)) })
cosmic::task::future(async move { Message::Refresh(Arc::new(page_reload().await)) })
}
fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
@ -175,7 +175,7 @@ impl Page {
let lang = language.lang_code.clone();
let region = region.lang_code.clone();
commands.push(cosmic::command::future(async move {
commands.push(cosmic::task::future(async move {
_ = set_locale(lang, region).await;
Message::Refresh(Arc::new(page_reload().await))
}));
@ -206,7 +206,7 @@ impl Page {
}
Message::InstallAdditionalLanguages => {
return cosmic::command::future(async move {
return cosmic::task::future(async move {
_ = tokio::process::Command::new("gnome-language-selector")
.status()
.await;

View file

@ -767,3 +767,17 @@ firmware = Firmware
users = Users
.desc = Authentication and user accounts.
## System: Default Applications
default-apps = Default Applications
.desc = Default applications and file associations.
.web-browser = Web browser
.file-manager = File manager
.mail-client = Mail client
.music = Music
.video = Video
.photos = Photos
.calendar = Calendar
.terminal = Terminal
.other-associations = Other Associations