diff --git a/Cargo.lock b/Cargo.lock index 2a2e53a..775b5e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -138,20 +138,20 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -230,9 +230,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake3" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888" +checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" dependencies = [ "arrayref", "arrayvec", @@ -402,9 +402,9 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "constant_time_eq" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "core-foundation" @@ -424,9 +424,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -538,7 +538,7 @@ checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "strsim", "syn 1.0.109", @@ -593,7 +593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" dependencies = [ "darling", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "syn 1.0.109", ] @@ -640,9 +640,9 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -699,7 +699,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -839,9 +839,9 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -987,18 +987,9 @@ checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hkdf" @@ -1191,9 +1182,9 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1213,9 +1204,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "js-sys" @@ -1495,9 +1486,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -1511,7 +1502,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1543,19 +1534,19 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] [[package]] name = "object" -version = "0.30.4" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -1593,9 +1584,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -1695,29 +1686,29 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -1779,9 +1770,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" dependencies = [ "unicode-ident", ] @@ -1813,7 +1804,7 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "syn 1.0.109", ] @@ -1833,7 +1824,7 @@ version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", ] [[package]] @@ -2042,9 +2033,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" dependencies = [ "aho-corasick", "memchr", @@ -2053,9 +2056,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" [[package]] name = "reqwest" @@ -2185,7 +2188,7 @@ checksum = "0f82e91eb61cd86d9287303133ee55b54618eccb75a522cc22a42c15f5bda340" dependencies = [ "once_cell", "proc-macro-crate", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "ruma-identifiers-validation", "serde", @@ -2201,31 +2204,31 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.37.20" +version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2259,38 +2262,38 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.164" +version = "1.0.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "bd51c3db8f9500d531e6c12dd0fd4ad13d133e9117f5aebac3cdbb8b6d9824b0" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +checksum = "5a16be4fe5320ade08736447e3198294a5ea9a6d44dde6f35f0a5e06859c427a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "27738cfea0d944ab72c3ed01f3d5f23ec4322af8a1431e40ce630e4c01ea74fd" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" dependencies = [ "itoa", "ryu", @@ -2396,9 +2399,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" @@ -2448,18 +2451,18 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.22" +version = "2.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "36ccaf716a23c35ff908f91c971a86a9a71af5998c1d8f10e828d9f55f68ac00" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "unicode-ident", ] @@ -2475,27 +2478,27 @@ dependencies = [ "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -2526,9 +2529,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374442f06ee49c3a28a8fc9f01a2596fed7559c6b99b31279c3261778e77d84f" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg 1.1.0", "backtrace", @@ -2539,7 +2542,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2548,9 +2551,9 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -2594,9 +2597,9 @@ checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ "indexmap 2.0.0", "toml_datetime", @@ -2627,9 +2630,9 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -2648,7 +2651,7 @@ dependencies = [ "anyhow", "cli-log", "crossterm", - "indexmap 1.9.3", + "indexmap 2.0.0", "matrix-sdk", "serde", "tokio", @@ -2700,9 +2703,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "unicode-normalization" @@ -2865,9 +2868,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", "wasm-bindgen-shared", ] @@ -2899,9 +2902,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2974,21 +2977,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -3004,93 +2992,51 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -3099,9 +3045,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" dependencies = [ "memchr", ] @@ -3142,7 +3088,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] diff --git a/Cargo.toml b/Cargo.toml index b5f63dd..92db0f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ license = "MIT" [dependencies] tui = "0.19" -tui-textarea = { version = "*" } -crossterm = "*" +tui-textarea = { version = "0.2", features = ["crossterm"] } +crossterm = "0.25" matrix-sdk = "0.6" anyhow = "1.0" -tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.29", features = ["macros", "rt-multi-thread"] } tokio-util = "0.7" serde = "1.0" cli-log = "2.0" -indexmap = "*" \ No newline at end of file +indexmap = "2.0.0" diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index 2e2fc08..f273104 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -1,13 +1,13 @@ use std::fs; -use matrix_sdk::{Client, - config::SyncSettings, - ruma::{user_id, - events::room::message::SyncRoomMessageEvent, - exports::serde_json}, - Session}; + use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; +use matrix_sdk::{ + config::SyncSettings, + ruma::{events::room::message::SyncRoomMessageEvent, exports::serde_json, user_id}, + Client, Session, +}; use serde::{Deserialize, Serialize}; -use cli_log::{error, warn, info}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Account { @@ -33,7 +33,7 @@ pub struct AccountsManager { } impl Account { - pub fn name (&self) -> &String { + pub fn name(&self) -> &String { &self.name } @@ -43,11 +43,12 @@ impl Account { } impl AccountsManager { - pub fn new(config:Option) -> Self { + pub fn new(config: Option) -> Self { return match config { Some(s) => { info!("Loading serialized AccountsManager"); - let accounts_data:AccountsData = serde_json::from_str(&s).expect("failed to deserialize json"); + let accounts_data: AccountsData = + serde_json::from_str(&s).expect("failed to deserialize json"); let mut clients = Vec::new(); clients.resize(accounts_data.accounts.len(), None); Self { @@ -56,7 +57,7 @@ impl AccountsManager { accounts: accounts_data.accounts, clients, } - }, + } None => { info!("Creating empty AccountsManager"); Self { @@ -66,7 +67,7 @@ impl AccountsManager { clients: Vec::new(), } } - } + }; } pub async fn restore(&mut self) -> Result<()> { @@ -74,7 +75,12 @@ impl AccountsManager { Ok(()) } - pub async fn add(&mut self, homeserver: &String, username: &String, password: &String) -> Result { + pub async fn add( + &mut self, + homeserver: &String, + username: &String, + password: &String, + ) -> Result { let id = self.num_accounts; self.num_accounts += 1; @@ -84,7 +90,8 @@ impl AccountsManager { .build() .await?; - client.login_username(username, password) + client + .login_username(username, password) .initial_device_display_name("Trinitrix") .send() .await?; @@ -94,9 +101,13 @@ impl AccountsManager { let account = Account { homeserver: homeserver.to_string(), id, - name: client.account().get_display_name().await?.expect("failed to fetch display name"), + name: client + .account() + .get_display_name() + .await? + .expect("failed to fetch display name"), session: session.clone(), - sync_token: None + sync_token: None, }; self.logout().await?; @@ -105,12 +116,16 @@ impl AccountsManager { self.clients.push(Some(client)); self.save()?; - info!("Logged in as '{}' device ID: {}", session.user_id.to_string(), session.device_id.to_string()); + info!( + "Logged in as '{}' device ID: {}", + session.user_id.to_string(), + session.device_id.to_string() + ); Ok(id) } - pub async fn login(&mut self, account_id:u32) -> Result<()> { + pub async fn login(&mut self, account_id: u32) -> Result<()> { self.logout().await?; // log out the current account let account = if account_id >= self.num_accounts { @@ -120,17 +135,28 @@ impl AccountsManager { self.get(account_id).expect("Account lookup failed") }; - if self.clients.get(account_id as usize).expect("client lookup failed").is_none() { - info!("No client cached for account: '{}' -> requesting a new one", &account.session.user_id); + if self + .clients + .get(account_id as usize) + .expect("client lookup failed") + .is_none() + { + info!( + "No client cached for account: '{}' -> requesting a new one", + &account.session.user_id + ); let client = Client::builder() .homeserver_url(&account.homeserver) - .sled_store(format!("userdata/{account_id}"), Some("supersecure")) ? + .sled_store(format!("userdata/{account_id}"), Some("supersecure"))? .build() .await?; client.restore_login(account.session.clone()).await?; self.clients.insert(account_id as usize, Some(client)); } else { - info!("Using cached client for account: '{}'", &account.session.user_id); + info!( + "Using cached client for account: '{}'", + &account.session.user_id + ); }; info!("Restored account"); @@ -156,7 +182,7 @@ impl AccountsManager { Ok(()) } - pub fn save(&self) -> Result<()>{ + pub fn save(&self) -> Result<()> { let accounts_data = AccountsData { current_account: self.current_account, accounts: self.accounts.clone(), @@ -188,5 +214,7 @@ impl AccountsManager { } } - pub fn num_accounts(&self) -> u32 { self.num_accounts } -} \ No newline at end of file + pub fn num_accounts(&self) -> u32 { + self.num_accounts + } +} diff --git a/src/app/event.rs b/src/app/event.rs index 02226f1..9d0c8bc 100644 --- a/src/app/event.rs +++ b/src/app/event.rs @@ -1,14 +1,27 @@ -use crate::app::{App, status::{Status, State}}; -use crate::ui; -use tokio::time::Duration; -use tokio::sync::{mpsc, broadcast}; +use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; +use matrix_sdk::{ + config::SyncSettings, + room::Room, + ruma::events::room::{ + member::StrippedRoomMemberEvent, + message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, + }, + Client, LoopCtrl, +}; +use tokio::{ + sync::{broadcast, mpsc}, + time::Duration, +}; use tokio_util::sync::CancellationToken; -use anyhow::{Result, Error}; -use matrix_sdk::{Client, room::{Room}, config::SyncSettings, ruma::events::room::{ - member::StrippedRoomMemberEvent, - message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, -}, LoopCtrl}; -use cli_log::{error, warn, info}; + +use crate::{ + app::{ + status::{State, Status}, + App, + }, + ui, +}; #[derive(Debug)] pub enum EventStatus { @@ -20,7 +33,7 @@ pub enum EventStatus { #[derive(Debug)] pub struct Event { input_event: Option, - matrix_event: Option + matrix_event: Option, } pub struct EventBuilder { @@ -42,7 +55,6 @@ impl Default for EventBuilder { event: Event::default(), } } - } impl EventBuilder { @@ -51,7 +63,10 @@ impl EventBuilder { self } - fn matrix_event(&mut self, matrix_event: matrix_sdk::deserialized_responses::SyncResponse) -> &Self { + fn matrix_event( + &mut self, + matrix_event: matrix_sdk::deserialized_responses::SyncResponse, + ) -> &Self { self.event.matrix_event = Some(matrix_event); self } @@ -66,7 +81,6 @@ impl EventBuilder { impl Event { pub async fn handle(&self, app: &mut App<'_>) -> Result { - if self.matrix_event.is_some() { return self.handle_matrix(app).await; } @@ -88,7 +102,11 @@ impl Event { None => continue, }; for m_event in m_room.timeline.events.clone() { - let event = m_event.event.deserialize().unwrap().into_full_event(m_room_id.clone()); + let event = m_event + .event + .deserialize() + .unwrap() + .into_full_event(m_room_id.clone()); room.timeline_add(event); } } @@ -99,99 +117,125 @@ impl Event { async fn handle_main(&self, app: &mut App<'_>) -> Result { if self.input_event.is_some() { match tui_textarea::Input::from(self.input_event.clone().unwrap()) { - tui_textarea::Input { key: tui_textarea::Key::Esc, .. } => return Ok(EventStatus::Terminate), + tui_textarea::Input { + key: tui_textarea::Key::Esc, + .. + } => return Ok(EventStatus::Terminate), tui_textarea::Input { key: tui_textarea::Key::Tab, .. } => { app.ui.cycle_main_input_position(); } - input => { - match app.ui.input_position() { - ui::MainInputPosition::MessageCompose => { - match input { - tui_textarea::Input {key: tui_textarea::Key::Enter, alt: true, ..} => { - match app.status.room_mut() { - Some(room) => { - room.send(app.ui.message_compose.lines().join("\n")).await?; - app.ui.message_compose_clear(); - }, - None => () - }; - } - _ => { app.ui.message_compose.input(input); } - }; - }, - ui::MainInputPosition::Rooms => { - match input { - tui_textarea::Input {key: tui_textarea::Key::Up, ..} => { - let i = match app.ui.rooms_state.selected() { - Some(i) => { - if i > 0 { i - 1 } - else { i } - }, - None => 0, - }; - app.ui.rooms_state.select(Some(i)); - app.status.set_room_by_index(i)?; - }, - tui_textarea::Input {key: tui_textarea::Key::Down, ..} => { - let i = match app.ui.rooms_state.selected() { - Some(i) => { - if i < app.status.rooms().len() { i + 1 } - else { i } - }, - None => 0, - }; - app.ui.rooms_state.select(Some(i)); - app.status.set_room_by_index(i)?; - }, - _ => () - }; - }, - ui::MainInputPosition::Messages => { - match input { - tui_textarea::Input {key: tui_textarea::Key::Up, ..} => { - match app.status.room_mut(){ - Some(room) => { - let len = room.timeline().len(); - let i = match room.view_scroll() { - Some(i) => i+1, - None => 0, - }; - if i < len { - room.set_view_scroll(Some(i)) - } - if i <= len - 5 { - room.poll_old_timeline().await?; - } - }, - None => (), - }; - }, - tui_textarea::Input {key: tui_textarea::Key::Down, ..} => { - match app.status.room_mut(){ - Some(room) => { - match room.view_scroll() { - Some(i) => { - if i == 0 { - room.set_view_scroll(None); - } else { - room.set_view_scroll(Some(i - 1)); - } - } - None => (), - }; - }, - None => (), - }; - }, - _ => () - }; - }, - _ => (), + input => match app.ui.input_position() { + ui::MainInputPosition::MessageCompose => { + match input { + tui_textarea::Input { + key: tui_textarea::Key::Enter, + alt: true, + .. + } => { + match app.status.room_mut() { + Some(room) => { + room.send(app.ui.message_compose.lines().join("\n")) + .await?; + app.ui.message_compose_clear(); + } + None => (), + }; + } + _ => { + app.ui.message_compose.input(input); + } + }; } - } + ui::MainInputPosition::Rooms => { + match input { + tui_textarea::Input { + key: tui_textarea::Key::Up, + .. + } => { + let i = match app.ui.rooms_state.selected() { + Some(i) => { + if i > 0 { + i - 1 + } else { + i + } + } + None => 0, + }; + app.ui.rooms_state.select(Some(i)); + app.status.set_room_by_index(i)?; + } + tui_textarea::Input { + key: tui_textarea::Key::Down, + .. + } => { + let i = match app.ui.rooms_state.selected() { + Some(i) => { + if i < app.status.rooms().len() { + i + 1 + } else { + i + } + } + None => 0, + }; + app.ui.rooms_state.select(Some(i)); + app.status.set_room_by_index(i)?; + } + _ => (), + }; + } + ui::MainInputPosition::Messages => { + match input { + tui_textarea::Input { + key: tui_textarea::Key::Up, + .. + } => { + match app.status.room_mut() { + Some(room) => { + let len = room.timeline().len(); + let i = match room.view_scroll() { + Some(i) => i + 1, + None => 0, + }; + if i < len { + room.set_view_scroll(Some(i)) + } + if i <= len - 5 { + room.poll_old_timeline().await?; + } + } + None => (), + }; + } + tui_textarea::Input { + key: tui_textarea::Key::Down, + .. + } => { + match app.status.room_mut() { + Some(room) => { + match room.view_scroll() { + Some(i) => { + if i == 0 { + room.set_view_scroll(None); + } else { + room.set_view_scroll(Some(i - 1)); + } + } + None => (), + }; + } + None => (), + }; + } + _ => (), + }; + } + _ => (), + }, }; } Ok(EventStatus::Ok) @@ -200,18 +244,21 @@ impl Event { async fn handle_setup(&self, app: &mut App<'_>) -> Result { let ui = match &mut app.ui.setup_ui { Some(ui) => ui, - None => return Err(Error::msg("SetupUI instance not found")) + None => return Err(Error::msg("SetupUI instance not found")), }; if self.input_event.is_some() { match tui_textarea::Input::from(self.input_event.clone().unwrap()) { - tui_textarea::Input { key: tui_textarea::Key::Esc, .. } => return Ok(EventStatus::Terminate), + tui_textarea::Input { + key: tui_textarea::Key::Esc, + .. + } => return Ok(EventStatus::Terminate), tui_textarea::Input { key: tui_textarea::Key::Tab, .. } => { ui.cycle_input_position(); - }, + } tui_textarea::Input { key: tui_textarea::Key::Enter, .. @@ -225,33 +272,40 @@ impl Event { if login.is_ok() { return Ok(EventStatus::Finished); } - }, + } _ => ui.cycle_input_position(), }; - }, - input => { - match ui.input_position() { - ui::SetupInputPosition::Homeserver => { ui.homeserver.input(input); }, - ui::SetupInputPosition::Username => { ui.username.input(input); }, - ui::SetupInputPosition::Password => { - ui.password_data.input(input.clone()); - match input.key { - tui_textarea::Key::Char(_) => { - ui.password.input(tui_textarea::Input { key: tui_textarea::Key::Char('*'), ctrl: false, alt: false }); - }, - _ => { ui.password.input(input); }, - } - }, - _ => (), - } } + input => match ui.input_position() { + ui::SetupInputPosition::Homeserver => { + ui.homeserver.input(input); + } + ui::SetupInputPosition::Username => { + ui.username.input(input); + } + ui::SetupInputPosition::Password => { + ui.password_data.input(input.clone()); + match input.key { + tui_textarea::Key::Char(_) => { + ui.password.input(tui_textarea::Input { + key: tui_textarea::Key::Char('*'), + ctrl: false, + alt: false, + }); + } + _ => { + ui.password.input(input); + } + } + } + _ => (), + }, }; } Ok(EventStatus::Ok) } } - async fn poll_input_events_stage_2(channel: mpsc::Sender) -> Result<()> { loop { if crossterm::event::poll(Duration::from_millis(100))? { @@ -266,7 +320,10 @@ async fn poll_input_events_stage_2(channel: mpsc::Sender) -> Result<()> { } } -pub async fn poll_input_events(channel: mpsc::Sender, kill: CancellationToken) -> Result<()> { +pub async fn poll_input_events( + channel: mpsc::Sender, + kill: CancellationToken, +) -> Result<()> { tokio::select! { output = poll_input_events_stage_2(channel) => output, _ = kill.cancelled() => Err(Error::msg("received kill signal")) @@ -275,28 +332,32 @@ pub async fn poll_input_events(channel: mpsc::Sender, kill: CancellationT async fn poll_matrix_events_stage_2(channel: mpsc::Sender, client: Client) -> Result<()> { let sync_settings = SyncSettings::default(); - // .token(sync_token) - // .timeout(Duration::from_secs(30)); + // .token(sync_token) + // .timeout(Duration::from_secs(30)); let tx = &channel; - client.sync_with_callback(sync_settings, |response| async move { - let event = EventBuilder::default() - .matrix_event(response) - .build(); + client + .sync_with_callback(sync_settings, |response| async move { + let event = EventBuilder::default().matrix_event(response).build(); - match tx.send(event).await { - Ok(_) => LoopCtrl::Continue, - Err(_) => LoopCtrl::Break, - } - }).await?; + match tx.send(event).await { + Ok(_) => LoopCtrl::Continue, + Err(_) => LoopCtrl::Break, + } + }) + .await?; Ok(()) } -pub async fn poll_matrix_events(channel: mpsc::Sender, kill: CancellationToken, client: Client) -> Result<()> { +pub async fn poll_matrix_events( + channel: mpsc::Sender, + kill: CancellationToken, + client: Client, +) -> Result<()> { tokio::select! { output = poll_matrix_events_stage_2(channel, client) => output, _ = kill.cancelled() => Err(Error::msg("received kill signal")), } -} \ No newline at end of file +} diff --git a/src/app/mod.rs b/src/app/mod.rs index 09931fd..6b14863 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,27 +1,29 @@ pub mod event; pub mod status; -use crate::accounts; -use crate::ui; - use std::path::Path; -use matrix_sdk::{Client, - room::{Room}, - config::SyncSettings, - ruma::events::room::{ - member::StrippedRoomMemberEvent, - message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, - }, - event_handler::Ctx -}; -use accounts::Account; -use accounts::AccountsManager; -use anyhow::{Result, Error}; -use cli_log::{error, warn, info}; -use tokio::{time::{sleep, Duration}, sync::{mpsc, broadcast}}; -use tokio_util::sync::CancellationToken; -use status::{Status, State}; +use accounts::{Account, AccountsManager}; +use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; +use matrix_sdk::{ + config::SyncSettings, + event_handler::Ctx, + room::Room, + ruma::events::room::{ + member::StrippedRoomMemberEvent, + message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, + }, + Client, +}; +use status::{State, Status}; +use tokio::{ + sync::{broadcast, mpsc}, + time::{sleep, Duration}, +}; +use tokio_util::sync::CancellationToken; + +use crate::{accounts, ui}; pub struct App<'a> { ui: ui::UI<'a>, @@ -35,14 +37,12 @@ pub struct App<'a> { } impl Drop for App<'_> { - fn drop(&mut self) { - - } + fn drop(&mut self) {} } impl App<'_> { pub fn new() -> Self { - let path:&std::path::Path = Path::new("userdata/accounts.json"); + let path: &std::path::Path = Path::new("userdata/accounts.json"); let config = if path.exists() { info!("Reading account config (userdata/accounts.json)"); Some(std::fs::read_to_string(path).expect("failed to read accounts config")) @@ -65,9 +65,11 @@ impl App<'_> { } pub async fn run(&mut self) -> Result<()> { - // Spawn input event listener - tokio::task::spawn(event::poll_input_events(self.channel_tx.clone(), self.input_listener_killer.clone())); + tokio::task::spawn(event::poll_input_events( + self.channel_tx.clone(), + self.input_listener_killer.clone(), + )); if self.account().is_err() { info!("No saved sessions found -> jumping into setup"); @@ -77,14 +79,13 @@ impl App<'_> { self.init_account().await?; } - loop { self.status.set_state(State::Main); self.ui.update(&self.status).await?; let event: event::Event = match self.channel_rx.recv().await { Some(e) => e, - None => return Err(Error::msg("Event channel has no senders")) + None => return Err(Error::msg("Event channel has no senders")), }; match event.handle(self).await? { @@ -107,7 +108,7 @@ impl App<'_> { let event: event::Event = match self.channel_rx.recv().await { Some(e) => e, - None => return Err(Error::msg("Event channel has no senders")) + None => return Err(Error::msg("Event channel has no senders")), }; match event.handle(self).await? { @@ -121,14 +122,19 @@ impl App<'_> { pub async fn init_account(&mut self) -> Result<()> { let client = match self.client() { Some(c) => c, - None => return Err(Error::msg("failed to get current client")) - }.clone(); + None => return Err(Error::msg("failed to get current client")), + } + .clone(); self.matrix_listener_killer.cancel(); self.matrix_listener_killer = CancellationToken::new(); // Spawn Matrix Event Listener - tokio::task::spawn(event::poll_matrix_events(self.channel_tx.clone(), self.matrix_listener_killer.clone(), client.clone())); + tokio::task::spawn(event::poll_matrix_events( + self.channel_tx.clone(), + self.matrix_listener_killer.clone(), + client.clone(), + )); // Reset Status self.status = Status::new(Some(client)); @@ -139,10 +145,11 @@ impl App<'_> { self.status.set_account_name(name); self.status.set_account_user_id(user_id); - for (_, room) in self.status.rooms_mut() { room.update_name().await?; - for _ in 0..3 { room.poll_old_timeline().await?; } + for _ in 0..3 { + room.poll_old_timeline().await?; + } } info!("Initializing client for the current account"); @@ -151,12 +158,18 @@ impl App<'_> { } pub async fn switch_account(&mut self, account_id: u32) -> Result<()> { - Ok(()) } - pub async fn login(&mut self, homeserver: &String, username: &String, password: &String) -> Result<()> { - self.accounts_manager.add(homeserver, username, password).await?; + pub async fn login( + &mut self, + homeserver: &String, + username: &String, + password: &String, + ) -> Result<()> { + self.accounts_manager + .add(homeserver, username, password) + .await?; self.init_account().await?; Ok(()) } @@ -165,11 +178,11 @@ impl App<'_> { let account = self.accounts_manager.current(); match account { None => Err(Error::msg("failed to resolve current account")), - Some(a) => Ok(a) + Some(a) => Ok(a), } } - + pub fn client(&self) -> Option<&Client> { self.accounts_manager.client() } -} \ No newline at end of file +} diff --git a/src/app/status.rs b/src/app/status.rs index 6110cfd..6b2d3fc 100644 --- a/src/app/status.rs +++ b/src/app/status.rs @@ -1,14 +1,16 @@ use std::any::Any; + +use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; use indexmap::IndexMap; -use matrix_sdk::{Client, - ruma::{events::{AnyTimelineEvent, - room::message::RoomMessageEventContent, - StateEventType}, - RoomId, - TransactionId}, - room::MessagesOptions}; -use anyhow::{Result, Error}; -use cli_log::{error, warn, info}; +use matrix_sdk::{ + room::MessagesOptions, + ruma::{ + events::{room::message::RoomMessageEventContent, AnyTimelineEvent, StateEventType}, + RoomId, TransactionId, + }, + Client, +}; pub enum State { None, @@ -36,7 +38,7 @@ pub struct Status { } impl Room { - pub fn new (matrix_room: matrix_sdk::room::Joined) -> Self { + pub fn new(matrix_room: matrix_sdk::room::Joined) -> Self { Self { matrix_room, name: "".to_string(), @@ -50,26 +52,29 @@ impl Room { pub async fn poll_old_timeline(&mut self) -> Result<()> { if let Some(AnyTimelineEvent::State(event)) = &self.timeline.get(0) { if event.event_type() == StateEventType::RoomCreate { - return Ok(()) + return Ok(()); } } let mut messages_options = MessagesOptions::backward(); messages_options = match &self.timeline_end { Some(end) => messages_options.from(end.as_str()), - None => messages_options + None => messages_options, }; let events = self.matrix_room.messages(messages_options).await?; self.timeline_end = events.end; for event in events.chunk.iter() { - self.timeline.insert(0, match event.event.deserialize() { - Ok(ev) => ev, - Err(err) => { - warn!("Failed to deserialize timeline event - {err}"); - continue; - } - }); + self.timeline.insert( + 0, + match event.event.deserialize() { + Ok(ev) => ev, + Err(err) => { + warn!("Failed to deserialize timeline event - {err}"); + continue; + } + }, + ); } Ok(()) } @@ -87,7 +92,9 @@ impl Room { self.timeline.push(event); } - pub fn timeline(&self) -> &Vec { &self.timeline } + pub fn timeline(&self) -> &Vec { + &self.timeline + } pub async fn send(&mut self, message: String) -> Result<()> { let content = RoomMessageEventContent::text_plain(message); @@ -114,9 +121,7 @@ impl Status { let mut rooms = IndexMap::new(); if let Some(c) = &client { for r in c.joined_rooms() { - rooms.insert( - r.room_id().to_string(), - Room::new(r.clone())); + rooms.insert(r.room_id().to_string(), Room::new(r.clone())); } }; @@ -167,7 +172,10 @@ impl Status { self.current_room_id = room_id.to_string(); Ok(()) } else { - Err(Error::msg(format!("failed to set room -> invalid room id {}", room_id.to_string()))) + Err(Error::msg(format!( + "failed to set room -> invalid room id {}", + room_id.to_string() + ))) } } @@ -176,7 +184,10 @@ impl Status { self.current_room_id = room_id.clone(); Ok(()) } else { - Err(Error::msg(format!("failed to set room -> invalid room index {}", room_index))) + Err(Error::msg(format!( + "failed to set room -> invalid room index {}", + room_index + ))) } } @@ -187,12 +198,12 @@ impl Status { pub fn get_room_mut(&mut self, room_id: &RoomId) -> Option<&mut Room> { self.rooms.get_mut(room_id.as_str()) } - + pub fn state(&self) -> &State { &self.state } - + pub fn set_state(&mut self, state: State) { self.state = state; } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 24ccbfc..aa926e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ -mod ui; mod accounts; mod app; +mod ui; -use cli_log::{error, warn, info}; +use cli_log::{error, info, warn}; #[tokio::main] async fn main() -> anyhow::Result<()> { diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 18280f6..f5b8a2a 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,30 +1,35 @@ -use crate::app::status::Status; +use std::{cmp, io, io::Stdout}; -use std::cmp; -use crossterm::{ - event::{self, DisableMouseCapture, EnableMouseCapture, Event, read}, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, - style::{style}, -}; use anyhow::{Error, Result}; -use std::io::Stdout; -use std::io; -use tui::{backend::CrosstermBackend, layout::{Constraint, Direction, Layout}, widgets::{Block, Borders, Widget}, Terminal, Frame}; -use tui::layout::{Alignment, Corner}; -use tui::style::{Color, Modifier, Style}; -use tui::text::{Spans, Span, Text}; -use tui::widgets::{List, ListItem, ListState, Paragraph, Wrap}; +use cli_log::{error, info, warn}; +use crossterm::{ + event::{self, read, DisableMouseCapture, EnableMouseCapture, Event}, + execute, + style::style, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, +}; +use matrix_sdk::{ + room::MessagesOptions, + ruma::events::{AnyMessageLikeEvent, AnyTimelineEvent}, +}; +use tui::{ + backend::CrosstermBackend, + layout::{Alignment, Constraint, Corner, Direction, Layout}, + style::{Color, Modifier, Style}, + text::{Span, Spans, Text}, + widgets::{Block, Borders, List, ListItem, ListState, Paragraph, Widget, Wrap}, + Frame, Terminal, +}; use tui_textarea::{Input, Key, TextArea}; -use cli_log::{error, warn, info}; -use matrix_sdk::{room::MessagesOptions, ruma::events::{AnyTimelineEvent, AnyMessageLikeEvent}}; + +use crate::app::status::Status; #[derive(Clone, Copy)] pub enum SetupInputPosition { Homeserver, Username, Password, - Ok + Ok, } #[derive(Clone, Copy)] @@ -33,7 +38,7 @@ pub enum MainInputPosition { Rooms, Messages, MessageCompose, - RoomInfo + RoomInfo, } pub struct SetupUI<'a> { @@ -54,7 +59,6 @@ pub struct UI<'a> { pub setup_ui: Option>, } - fn terminal_prepare() -> Result { enable_raw_mode()?; let mut stdout = io::stdout(); @@ -80,9 +84,7 @@ pub fn textarea_inactivate(textarea: &mut TextArea) { .block() .cloned() .unwrap_or_else(|| Block::default().borders(Borders::ALL)); - textarea.set_block( - b.style(Style::default().fg(Color::DarkGray)) - ); + textarea.set_block(b.style(Style::default().fg(Color::DarkGray))); } impl Drop for UI<'_> { @@ -94,7 +96,9 @@ impl Drop for UI<'_> { LeaveAlternateScreen, DisableMouseCapture ).expect("While destructing UI -> Failed execute backend commands (LeaveAlternateScreen and DisableMouseCapture)"); - self.terminal.show_cursor().expect("While destructing UI -> Failed to re-enable cursor"); + self.terminal + .show_cursor() + .expect("While destructing UI -> Failed to re-enable cursor"); } } @@ -105,18 +109,9 @@ impl SetupUI<'_> { let mut password = TextArea::default(); let mut password_data = TextArea::default(); - homeserver.set_block( - Block::default() - .title("Homeserver") - .borders(Borders::ALL)); - username.set_block( - Block::default() - .title("Username") - .borders(Borders::ALL)); - password.set_block( - Block::default() - .title("Password") - .borders(Borders::ALL)); + homeserver.set_block(Block::default().title("Homeserver").borders(Borders::ALL)); + username.set_block(Block::default().title("Username").borders(Borders::ALL)); + password.set_block(Block::default().title("Password").borders(Borders::ALL)); textarea_activate(&mut homeserver); textarea_inactivate(&mut username); @@ -138,68 +133,74 @@ impl SetupUI<'_> { textarea_activate(&mut self.username); textarea_inactivate(&mut self.password); SetupInputPosition::Username - }, + } SetupInputPosition::Username => { textarea_inactivate(&mut self.homeserver); textarea_inactivate(&mut self.username); textarea_activate(&mut self.password); SetupInputPosition::Password - }, + } SetupInputPosition::Password => { textarea_inactivate(&mut self.homeserver); textarea_inactivate(&mut self.username); textarea_inactivate(&mut self.password); SetupInputPosition::Ok - }, + } SetupInputPosition::Ok => { textarea_activate(&mut self.homeserver); textarea_inactivate(&mut self.username); textarea_inactivate(&mut self.password); SetupInputPosition::Homeserver - }, + } }; } - pub fn input_position(&self) -> &SetupInputPosition { &self.input_position } + pub fn input_position(&self) -> &SetupInputPosition { + &self.input_position + } - pub async fn update(&'_ mut self, terminal: &mut Terminal>) -> Result<()> { + pub async fn update( + &'_ mut self, + terminal: &mut Terminal>, + ) -> Result<()> { let mut strings: Vec = Vec::new(); strings.resize(3, "".to_string()); - let content_ok = match self.input_position { - SetupInputPosition:: Ok => Span::styled("OK", Style::default().add_modifier(Modifier::UNDERLINED)), + let content_ok = match self.input_position { + SetupInputPosition::Ok => { + Span::styled("OK", Style::default().add_modifier(Modifier::UNDERLINED)) + } _ => Span::styled("OK", Style::default().fg(Color::DarkGray)), }; - let block = Block::default() - .title("Login") - .borders(Borders::ALL); - - let mut ok = Paragraph::new(content_ok) - .alignment(Alignment::Center); + let block = Block::default().title("Login").borders(Borders::ALL); + let mut ok = Paragraph::new(content_ok).alignment(Alignment::Center); // define a 32 * 6 chunk in the middle of the screen let mut chunk = terminal.size()?; - chunk.x = (chunk.width / 2) - 16; - chunk.y = (chunk.height / 2) - 5; + chunk.x = (chunk.width / 2) - 16; + chunk.y = (chunk.height / 2) - 5; chunk.height = 12; - chunk.width = 32; + chunk.width = 32; let mut split_chunk = chunk.clone(); - split_chunk.x += 1; - split_chunk.y += 1; + split_chunk.x += 1; + split_chunk.y += 1; split_chunk.height -= 1; - split_chunk.width -= 2; + split_chunk.width -= 2; let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([ - Constraint::Length(3), // 0. Homserver: - Constraint::Length(3), // 1. Username: - Constraint::Length(3), // 2. Password: - Constraint::Length(1) // 3. OK - ].as_ref()) + .constraints( + [ + Constraint::Length(3), // 0. Homserver: + Constraint::Length(3), // 1. Username: + Constraint::Length(3), // 2. Password: + Constraint::Length(1), // 3. OK + ] + .as_ref(), + ) .split(split_chunk); terminal.draw(|frame| { @@ -226,7 +227,8 @@ impl UI<'_> { message_compose.set_block( Block::default() .title("Message Compose (send: +)") - .borders(Borders::ALL)); + .borders(Borders::ALL), + ); info!("Initialized UI"); @@ -235,7 +237,7 @@ impl UI<'_> { input_position: MainInputPosition::Rooms, rooms_state: ListState::default(), message_compose, - setup_ui: None + setup_ui: None, } } @@ -249,14 +251,17 @@ impl UI<'_> { }; } - pub fn input_position(&self) -> &MainInputPosition { &self.input_position } + pub fn input_position(&self) -> &MainInputPosition { + &self.input_position + } pub fn message_compose_clear(&mut self) { self.message_compose = TextArea::default(); self.message_compose.set_block( Block::default() .title("Message Compose (send: +)") - .borders(Borders::ALL)); + .borders(Borders::ALL), + ); } pub async fn update(&mut self, status: &Status) -> Result<()> { @@ -264,7 +269,14 @@ impl UI<'_> { let main_chunks = Layout::default() .direction(Direction::Horizontal) - .constraints([Constraint::Length(32), Constraint::Min(16), Constraint::Length(32)].as_ref()) + .constraints( + [ + Constraint::Length(32), + Constraint::Min(16), + Constraint::Length(32), + ] + .as_ref(), + ) .split(chunk); let left_chunks = Layout::default() @@ -274,7 +286,13 @@ impl UI<'_> { let middle_chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Min(4), Constraint::Length(cmp::min(2 + self.message_compose.lines().len() as u16, 8))].as_ref()) + .constraints( + [ + Constraint::Min(4), + Constraint::Length(cmp::min(2 + self.message_compose.lines().len() as u16, 8)), + ] + .as_ref(), + ) .split(main_chunks[1]); let right_chunks = Layout::default() @@ -282,15 +300,22 @@ impl UI<'_> { .constraints([Constraint::Min(4)].as_ref()) .split(main_chunks[2]); - let mut status_content = Text::styled(status.account_name(), Style::default().add_modifier(Modifier::BOLD)); + let mut status_content = Text::styled( + status.account_name(), + Style::default().add_modifier(Modifier::BOLD), + ); status_content.extend(Text::styled(status.account_user_id(), Style::default())); - status_content.extend(Text::styled("settings", Style::default().fg(Color::LightMagenta).add_modifier(Modifier::ITALIC | Modifier::UNDERLINED))); + status_content.extend(Text::styled( + "settings", + Style::default() + .fg(Color::LightMagenta) + .add_modifier(Modifier::ITALIC | Modifier::UNDERLINED), + )); - let rooms_content = status.rooms() + let rooms_content = status + .rooms() .iter() - .map(|(_, room)| { - ListItem::new(Span::styled(room.name(), Style::default())) - }) + .map(|(_, room)| ListItem::new(Span::styled(room.name(), Style::default()))) .collect::>(); let messages_content = match status.room() { @@ -300,7 +325,6 @@ impl UI<'_> { .rev() .map(|event| { match event { - // Message Like Events AnyTimelineEvent::MessageLike(message_like_event) => { let (content, color) = match &message_like_event { @@ -312,30 +336,48 @@ impl UI<'_> { .body(); (message_content.to_string(), Color::White) - }, - _ => ("~~~ not supported message like event ~~~".to_string(), Color::Red) + } + _ => ( + "~~~ not supported message like event ~~~".to_string(), + Color::Red, + ), }; - let mut text = Text::styled(message_like_event.sender().to_string(), - Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)); - text.extend(Text::styled(content.to_string(), - Style::default().fg(color))); + let mut text = Text::styled( + message_like_event.sender().to_string(), + Style::default() + .fg(Color::Cyan) + .add_modifier(Modifier::BOLD), + ); + text.extend(Text::styled( + content.to_string(), + Style::default().fg(color), + )); ListItem::new(text) - }, + } // State Events AnyTimelineEvent::State(state) => { ListItem::new(vec![Spans::from(vec![ - Span::styled(state.sender().to_string(), Style::default().fg(Color::DarkGray)), + Span::styled( + state.sender().to_string(), + Style::default().fg(Color::DarkGray), + ), Span::styled(": ", Style::default().fg(Color::DarkGray)), - Span::styled(state.event_type().to_string(), Style::default().fg(Color::DarkGray)) + Span::styled( + state.event_type().to_string(), + Style::default().fg(Color::DarkGray), + ), ])]) } } }) .collect::>() - }, + } None => { - vec![ListItem::new(Text::styled("No room selected!", Style::default().fg(Color::Red)))] + vec![ListItem::new(Text::styled( + "No room selected!", + Style::default().fg(Color::Red), + ))] } }; @@ -347,78 +389,129 @@ impl UI<'_> { room_info_content.extend(Text::styled(room.name(), Style::default().fg(Color::Cyan))); if room.encrypted() { - room_info_content.extend(Text::styled("Encrypted", Style::default().fg(Color::Green))); + room_info_content + .extend(Text::styled("Encrypted", Style::default().fg(Color::Green))); } else { - room_info_content.extend(Text::styled("Not Encrypted!", Style::default().fg(Color::Red))); + room_info_content.extend(Text::styled( + "Not Encrypted!", + Style::default().fg(Color::Red), + )); } } else { - room_info_content.extend(Text::styled("No room selected!", Style::default().fg(Color::Red))); + room_info_content.extend(Text::styled( + "No room selected!", + Style::default().fg(Color::Red), + )); } - // calculate to widgets colors, based of which widget is currently selected let colors = match self.input_position { MainInputPosition::Status => { textarea_inactivate(&mut self.message_compose); - vec![Color::White, Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::White, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::Rooms => { textarea_inactivate(&mut self.message_compose); - vec![Color::DarkGray, Color::White, Color::DarkGray, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::DarkGray, + Color::White, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::Messages => { textarea_inactivate(&mut self.message_compose); - vec![Color::DarkGray, Color::DarkGray, Color::White, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::DarkGray, + Color::DarkGray, + Color::White, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::MessageCompose => { textarea_activate(&mut self.message_compose); - vec![Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::RoomInfo => { textarea_inactivate(&mut self.message_compose); - vec![Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::White] - }, + vec![ + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::White, + ] + } }; // initiate the widgets let status_panel = Paragraph::new(status_content) - .block(Block::default() - .title("Status") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::Status as usize]))) + .block( + Block::default() + .title("Status") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::Status as usize])), + ) .alignment(Alignment::Left); let rooms_panel = List::new(rooms_content) - .block(Block::default() - .title("Rooms (navigate: arrow keys)") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::Rooms as usize]))) + .block( + Block::default() + .title("Rooms (navigate: arrow keys)") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::Rooms as usize])), + ) .style(Style::default().fg(Color::DarkGray)) - .highlight_style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)) + .highlight_style( + Style::default() + .fg(Color::Cyan) + .add_modifier(Modifier::BOLD), + ) .highlight_symbol(">"); let messages_panel = List::new(messages_content) - .block(Block::default() - .title("Messages") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::Messages as usize]))) + .block( + Block::default() + .title("Messages") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::Messages as usize])), + ) .start_corner(Corner::BottomLeft) .highlight_symbol(">") - .highlight_style(Style::default().fg(Color::LightMagenta).add_modifier(Modifier::BOLD)); + .highlight_style( + Style::default() + .fg(Color::LightMagenta) + .add_modifier(Modifier::BOLD), + ); let room_info_panel = Paragraph::new(room_info_content) - .block(Block::default() - .title("Room Info") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::RoomInfo as usize]))) + .block( + Block::default() + .title("Room Info") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::RoomInfo as usize])), + ) .alignment(Alignment::Center); - // render the widgets self.terminal.draw(|frame| { frame.render_widget(status_panel, left_chunks[0]); frame.render_stateful_widget(rooms_panel, left_chunks[1], &mut self.rooms_state); - frame.render_stateful_widget(messages_panel, middle_chunks[0], & mut messages_state); + frame.render_stateful_widget(messages_panel, middle_chunks[0], &mut messages_state); frame.render_widget(self.message_compose.widget(), middle_chunks[1]); frame.render_widget(room_info_panel, right_chunks[0]); })?;