feat: add edit profile panel
This commit is contained in:
153
Cargo.lock
generated
153
Cargo.lock
generated
@@ -163,7 +163,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -338,7 +338,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -373,7 +373,7 @@ checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -504,7 +504,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash 1.1.0",
|
||||
"shlex",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -632,7 +632,7 @@ source = "git+https://github.com/kvark/blade?rev=b16f5c7bd873c7126f48c82c39e7ae6
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -731,7 +731,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -800,7 +800,7 @@ dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"tempfile",
|
||||
"toml",
|
||||
]
|
||||
@@ -957,7 +957,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1039,7 +1039,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collections"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"rustc-hash 2.1.0",
|
||||
@@ -1314,7 +1314,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1339,13 +1339,13 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1412,7 +1412,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1516,7 +1516,7 @@ checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1765,7 +1765,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1888,7 +1888,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2058,7 +2058,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"as-raw-xcb-connection",
|
||||
@@ -2092,8 +2092,8 @@ dependencies = [
|
||||
"gpui_macros",
|
||||
"http_client",
|
||||
"image",
|
||||
"inventory",
|
||||
"itertools 0.14.0",
|
||||
"linkme",
|
||||
"log",
|
||||
"lyon",
|
||||
"media",
|
||||
@@ -2145,7 +2145,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2155,7 +2155,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_tokio"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"gpui",
|
||||
"tokio",
|
||||
@@ -2360,7 +2360,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "http_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -2575,7 +2575,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2685,7 +2685,16 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54b12ebb6799019b044deaf431eadfe23245b259bba5a2c0796acec3943a3cdb"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2860,26 +2869,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linkme"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "566336154b9e58a4f055f6dd4cbab62c7dc0826ce3c0a04e63b2d2ecd784cdae"
|
||||
dependencies = [
|
||||
"linkme-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linkme-impl"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edbe595006d355eaf9ae11db92707d4338cd2384d16866131cc1afdbdd35d8d9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.15"
|
||||
@@ -3022,7 +3011,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "media"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bindgen",
|
||||
@@ -3346,7 +3335,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3830,7 +3819,7 @@ dependencies = [
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3865,7 +3854,7 @@ checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3975,7 +3964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4012,7 +4001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4274,7 +4263,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"derive_refineable",
|
||||
]
|
||||
@@ -4403,7 +4392,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "reqwest_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -4480,7 +4469,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
@@ -4668,7 +4657,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4753,7 +4742,7 @@ checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe"
|
||||
[[package]]
|
||||
name = "semantic_version"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -4782,7 +4771,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4793,7 +4782,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4826,7 +4815,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5066,7 +5055,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5078,7 +5067,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
[[package]]
|
||||
name = "sum_tree"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"log",
|
||||
@@ -5203,9 +5192,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.97"
|
||||
version = "2.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dabd04e3b9a8c3c03d5e743f5ef5e1207befc9de704d477f7198cc28049763e"
|
||||
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5238,7 +5227,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5369,7 +5358,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5380,7 +5369,7 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5501,7 +5490,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5635,7 +5624,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5900,7 +5889,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
[[package]]
|
||||
name = "util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#2f8237492641b4c97f61977a39f8a10225578a6d"
|
||||
source = "git+https://github.com/zed-industries/zed#1dd2bbe2bae4e7340ffceb6a9be4742f571e9b1d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-fs",
|
||||
@@ -6081,7 +6070,7 @@ dependencies = [
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -6116,7 +6105,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -6334,7 +6323,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6345,7 +6334,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6718,7 +6707,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -6805,7 +6794,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"zvariant_utils 2.1.0",
|
||||
]
|
||||
|
||||
@@ -6818,7 +6807,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"zbus_names 4.1.1",
|
||||
"zvariant 5.2.0",
|
||||
"zvariant_utils 3.1.0",
|
||||
@@ -6871,7 +6860,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6891,7 +6880,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -6912,7 +6901,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6934,7 +6923,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6999,7 +6988,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"zvariant_utils 2.1.0",
|
||||
]
|
||||
|
||||
@@ -7012,7 +7001,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"zvariant_utils 3.1.0",
|
||||
]
|
||||
|
||||
@@ -7024,7 +7013,7 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7037,6 +7026,6 @@ dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"syn 2.0.97",
|
||||
"syn 2.0.98",
|
||||
"winnow 0.6.26",
|
||||
]
|
||||
|
||||
@@ -9,8 +9,8 @@ use common::{
|
||||
profile::NostrProfile,
|
||||
};
|
||||
use gpui::{
|
||||
actions, point, px, size, App, AppContext, Application, BorrowAppContext, Bounds, SharedString,
|
||||
TitlebarOptions, WindowBounds, WindowKind, WindowOptions,
|
||||
actions, point, px, size, App, AppContext, Application, BorrowAppContext, Bounds, Menu,
|
||||
MenuItem, SharedString, TitlebarOptions, WindowBounds, WindowKind, WindowOptions,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
use gpui::{WindowBackgroundAppearance, WindowDecorations};
|
||||
@@ -223,8 +223,12 @@ fn main() {
|
||||
// Initialize components
|
||||
ui::init(cx);
|
||||
|
||||
// Set quit action
|
||||
cx.activate(true);
|
||||
cx.on_action(quit);
|
||||
cx.set_menus(vec![Menu {
|
||||
name: "Coop".into(),
|
||||
items: vec![MenuItem::action("Quit", Quit)],
|
||||
}]);
|
||||
|
||||
let opts = WindowOptions {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
@@ -248,7 +252,6 @@ fn main() {
|
||||
|
||||
let window = cx
|
||||
.open_window(opts, |window, cx| {
|
||||
cx.activate(true);
|
||||
window.set_window_title(APP_NAME);
|
||||
window.set_app_id(APP_ID);
|
||||
|
||||
@@ -363,5 +366,5 @@ fn main() {
|
||||
}
|
||||
|
||||
fn quit(_: &Quit, cx: &mut App) {
|
||||
cx.shutdown();
|
||||
cx.quit();
|
||||
}
|
||||
|
||||
@@ -133,11 +133,13 @@ impl AppView {
|
||||
}
|
||||
}
|
||||
PanelKind::Profile => {
|
||||
let panel = Arc::new(profile::init(window, cx));
|
||||
if let Some(profile) = cx.global::<AppRegistry>().user() {
|
||||
let panel = Arc::new(profile::init(profile, window, cx));
|
||||
|
||||
self.dock.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel(panel, action.position, window, cx);
|
||||
});
|
||||
self.dock.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel(panel, action.position, window, cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
PanelKind::Contacts => {
|
||||
let panel = Arc::new(contacts::init(window, cx));
|
||||
|
||||
@@ -370,8 +370,7 @@ impl Chat {
|
||||
});
|
||||
|
||||
// Show loading spinner
|
||||
self.is_uploading = true;
|
||||
cx.notify();
|
||||
self.set_loading(true, cx);
|
||||
|
||||
// TODO: support multiple upload
|
||||
cx.spawn(move |this, mut async_cx| async move {
|
||||
@@ -394,8 +393,7 @@ impl Chat {
|
||||
// Stop loading spinner
|
||||
if let Some(view) = this.upgrade() {
|
||||
_ = async_cx.update_entity(&view, |this, cx| {
|
||||
this.is_uploading = false;
|
||||
cx.notify();
|
||||
this.set_loading(false, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -427,6 +425,11 @@ impl Chat {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn set_loading(&mut self, status: bool, cx: &mut Context<Self>) {
|
||||
self.is_uploading = status;
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
impl Panel for Chat {
|
||||
|
||||
@@ -1,18 +1,37 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use async_utility::task::spawn;
|
||||
use common::{constants::IMAGE_SERVICE, profile::NostrProfile, utils::nip96_upload};
|
||||
use gpui::{
|
||||
div, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
IntoElement, ParentElement, Render, SharedString, Styled, Window,
|
||||
div, img, AnyElement, App, AppContext, Context, Entity, EventEmitter, Flatten, FocusHandle,
|
||||
Focusable, IntoElement, ParentElement, PathPromptOptions, Render, SharedString, Styled, Window,
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use smol::fs;
|
||||
use state::get_client;
|
||||
use tokio::sync::oneshot;
|
||||
use ui::{
|
||||
button::Button,
|
||||
button::{Button, ButtonVariants},
|
||||
dock_area::panel::{Panel, PanelEvent},
|
||||
input::TextInput,
|
||||
popup_menu::PopupMenu,
|
||||
ContextModal, Disableable, Sizable, Size,
|
||||
};
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Profile> {
|
||||
Profile::new(window, cx)
|
||||
pub fn init(profile: NostrProfile, window: &mut Window, cx: &mut App) -> Entity<Profile> {
|
||||
Profile::new(profile, window, cx)
|
||||
}
|
||||
|
||||
pub struct Profile {
|
||||
profile: NostrProfile,
|
||||
// Form
|
||||
name_input: Entity<TextInput>,
|
||||
avatar_input: Entity<TextInput>,
|
||||
bio_input: Entity<TextInput>,
|
||||
website_input: Entity<TextInput>,
|
||||
is_loading: bool,
|
||||
is_submitting: bool,
|
||||
// Panel
|
||||
name: SharedString,
|
||||
closable: bool,
|
||||
zoomable: bool,
|
||||
@@ -20,14 +39,177 @@ pub struct Profile {
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
pub fn new(_window: &mut Window, cx: &mut App) -> Entity<Self> {
|
||||
pub fn new(mut profile: NostrProfile, window: &mut Window, cx: &mut App) -> Entity<Self> {
|
||||
let name_input = cx.new(|cx| {
|
||||
let mut input = TextInput::new(window, cx).text_size(Size::XSmall);
|
||||
if let Some(name) = profile.metadata().display_name.as_ref() {
|
||||
input.set_text(name, window, cx);
|
||||
}
|
||||
input
|
||||
});
|
||||
let avatar_input = cx.new(|cx| {
|
||||
let mut input = TextInput::new(window, cx).text_size(Size::XSmall).small();
|
||||
if let Some(picture) = profile.metadata().picture.as_ref() {
|
||||
input.set_text(picture, window, cx);
|
||||
}
|
||||
input
|
||||
});
|
||||
let bio_input = cx.new(|cx| {
|
||||
let mut input = TextInput::new(window, cx)
|
||||
.text_size(Size::XSmall)
|
||||
.multi_line();
|
||||
if let Some(about) = profile.metadata().about.as_ref() {
|
||||
input.set_text(about, window, cx);
|
||||
} else {
|
||||
input.set_placeholder("A short introduce about you.");
|
||||
}
|
||||
input
|
||||
});
|
||||
let website_input = cx.new(|cx| {
|
||||
let mut input = TextInput::new(window, cx).text_size(Size::XSmall);
|
||||
if let Some(website) = profile.metadata().website.as_ref() {
|
||||
input.set_text(website, window, cx);
|
||||
} else {
|
||||
input.set_placeholder("https://your-website.com");
|
||||
}
|
||||
input
|
||||
});
|
||||
|
||||
cx.new(|cx| Self {
|
||||
profile,
|
||||
name_input,
|
||||
avatar_input,
|
||||
bio_input,
|
||||
website_input,
|
||||
is_loading: false,
|
||||
is_submitting: false,
|
||||
name: "Profile".into(),
|
||||
closable: true,
|
||||
zoomable: true,
|
||||
focus_handle: cx.focus_handle(),
|
||||
})
|
||||
}
|
||||
|
||||
fn upload(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let avatar_input = self.avatar_input.downgrade();
|
||||
let window_handle = window.window_handle();
|
||||
let paths = cx.prompt_for_paths(PathPromptOptions {
|
||||
files: true,
|
||||
directories: false,
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
// Show loading spinner
|
||||
self.set_loading(true, cx);
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
match Flatten::flatten(paths.await.map_err(|e| e.into())) {
|
||||
Ok(Some(mut paths)) => {
|
||||
let path = paths.pop().unwrap();
|
||||
|
||||
if let Ok(file_data) = fs::read(path).await {
|
||||
let (tx, rx) = oneshot::channel::<Url>();
|
||||
|
||||
spawn(async move {
|
||||
let client = get_client();
|
||||
|
||||
if let Ok(url) = nip96_upload(client, file_data).await {
|
||||
_ = tx.send(url);
|
||||
}
|
||||
});
|
||||
|
||||
if let Ok(url) = rx.await {
|
||||
// Stop loading spinner
|
||||
if let Some(view) = this.upgrade() {
|
||||
cx.update_entity(&view, |this, cx| {
|
||||
this.set_loading(false, cx);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Update avatar input
|
||||
if let Some(input) = avatar_input.upgrade() {
|
||||
cx.update_window(window_handle, |_, window, cx| {
|
||||
cx.update_entity(&input, |this, cx| {
|
||||
this.set_text(url.to_string(), window, cx);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(_) => {}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn set_loading(&mut self, status: bool, cx: &mut Context<Self>) {
|
||||
self.is_loading = status;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn submit(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
// Show loading spinner
|
||||
self.set_submitting(true, cx);
|
||||
|
||||
let avatar = self.avatar_input.read(cx).text().to_string();
|
||||
let name = self.name_input.read(cx).text().to_string();
|
||||
let bio = self.bio_input.read(cx).text().to_string();
|
||||
let website = self.website_input.read(cx).text().to_string();
|
||||
|
||||
let mut new_metadata = self
|
||||
.profile
|
||||
.metadata()
|
||||
.to_owned()
|
||||
.display_name(name)
|
||||
.about(bio);
|
||||
|
||||
if let Ok(url) = Url::from_str(&avatar) {
|
||||
new_metadata = new_metadata.picture(url);
|
||||
};
|
||||
|
||||
if let Ok(url) = Url::from_str(&website) {
|
||||
new_metadata = new_metadata.website(url);
|
||||
}
|
||||
|
||||
let window_handle = window.window_handle();
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let client = get_client();
|
||||
let (tx, rx) = oneshot::channel::<EventId>();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
if let Ok(output) = client.set_metadata(&new_metadata).await {
|
||||
_ = tx.send(output.val);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
if rx.await.is_ok() {
|
||||
if let Some(profile) = this.upgrade() {
|
||||
cx.update_window(window_handle, |_, window, cx| {
|
||||
cx.update_entity(&profile, |this, cx| {
|
||||
this.set_submitting(false, cx);
|
||||
window.push_notification(
|
||||
"Your profile has been updated successfully",
|
||||
cx,
|
||||
);
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn set_submitting(&mut self, status: bool, cx: &mut Context<Self>) {
|
||||
self.is_submitting = status;
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
impl Panel for Profile {
|
||||
@@ -65,12 +247,91 @@ impl Focusable for Profile {
|
||||
}
|
||||
|
||||
impl Render for Profile {
|
||||
fn render(&mut self, _window: &mut gpui::Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.size_full()
|
||||
.px_2()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.child("Profile")
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.items_center()
|
||||
.justify_end()
|
||||
.gap_2()
|
||||
.w_full()
|
||||
.h_24()
|
||||
.child(
|
||||
img(format!(
|
||||
"{}/?url={}&w=100&h=100&fit=cover&mask=circle&n=-1",
|
||||
IMAGE_SERVICE,
|
||||
self.avatar_input.read(cx).text()
|
||||
))
|
||||
.size_10()
|
||||
.rounded_full()
|
||||
.flex_shrink_0(),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.w_full()
|
||||
.child(self.avatar_input.clone())
|
||||
.child(
|
||||
Button::new("upload")
|
||||
.label("Upload")
|
||||
.ghost()
|
||||
.small()
|
||||
.disabled(self.is_submitting)
|
||||
.loading(self.is_loading)
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
this.upload(window, cx);
|
||||
})),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.text_xs()
|
||||
.child("Name:")
|
||||
.child(self.name_input.clone()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.text_xs()
|
||||
.child("Bio:")
|
||||
.child(self.bio_input.clone()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.text_xs()
|
||||
.child("Website:")
|
||||
.child(self.website_input.clone()),
|
||||
)
|
||||
.child(
|
||||
div().flex().items_center().justify_end().child(
|
||||
Button::new("submit")
|
||||
.label("Update")
|
||||
.primary()
|
||||
.small()
|
||||
.disabled(self.is_loading)
|
||||
.loading(self.is_submitting)
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
this.submit(window, cx);
|
||||
})),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,12 +79,12 @@ impl Room {
|
||||
/// Set contact's metadata by public key
|
||||
pub fn set_metadata(&mut self, public_key: PublicKey, metadata: Metadata) {
|
||||
if self.owner.public_key() == public_key {
|
||||
self.owner.metadata(&metadata);
|
||||
self.owner.set_metadata(&metadata);
|
||||
}
|
||||
|
||||
for member in self.members.iter_mut() {
|
||||
if member.public_key() == public_key {
|
||||
member.metadata(&metadata);
|
||||
member.set_metadata(&metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,6 @@ impl NostrProfile {
|
||||
self.public_key
|
||||
}
|
||||
|
||||
/// Set contact's metadata
|
||||
pub fn metadata(&mut self, metadata: &Metadata) {
|
||||
self.metadata = metadata.clone()
|
||||
}
|
||||
|
||||
/// Get contact's avatar
|
||||
pub fn avatar(&self) -> String {
|
||||
if let Some(picture) = &self.metadata.picture {
|
||||
@@ -59,4 +54,14 @@ impl NostrProfile {
|
||||
|
||||
shorted_public_key(self.public_key)
|
||||
}
|
||||
|
||||
/// Get contact's metadata
|
||||
pub fn metadata(&mut self) -> &Metadata {
|
||||
&self.metadata
|
||||
}
|
||||
|
||||
/// Set contact's metadata
|
||||
pub fn set_metadata(&mut self, metadata: &Metadata) {
|
||||
self.metadata = metadata.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ impl Dock {
|
||||
) -> Self {
|
||||
let panel = cx.new(|cx| {
|
||||
let mut tab = TabPanel::new(None, dock_area.clone(), window, cx);
|
||||
tab.closeable = false;
|
||||
tab.closable = true;
|
||||
tab
|
||||
});
|
||||
|
||||
@@ -250,7 +250,7 @@ impl Dock {
|
||||
.when(self.placement.is_right(), |this| {
|
||||
this.cursor_col_resize()
|
||||
.top_0()
|
||||
.left(px(1.))
|
||||
.left(px(-0.5))
|
||||
.h_full()
|
||||
.w(HANDLE_SIZE)
|
||||
.pt_12()
|
||||
|
||||
@@ -21,7 +21,7 @@ use std::sync::Arc;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct TabState {
|
||||
closeable: bool,
|
||||
closable: bool,
|
||||
zoomable: bool,
|
||||
draggable: bool,
|
||||
droppable: bool,
|
||||
@@ -70,7 +70,7 @@ pub struct TabPanel {
|
||||
pub(crate) active_ix: usize,
|
||||
/// If this is true, the Panel closeable will follow the active panel's closeable,
|
||||
/// otherwise this TabPanel will not able to close
|
||||
pub(crate) closeable: bool,
|
||||
pub(crate) closable: bool,
|
||||
tab_bar_scroll_handle: ScrollHandle,
|
||||
is_zoomed: bool,
|
||||
is_collapsed: bool,
|
||||
@@ -90,7 +90,7 @@ impl Panel for TabPanel {
|
||||
}
|
||||
|
||||
fn closable(&self, cx: &App) -> bool {
|
||||
if !self.closeable {
|
||||
if !self.closable {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ impl TabPanel {
|
||||
will_split_placement: None,
|
||||
is_zoomed: false,
|
||||
is_collapsed: false,
|
||||
closeable: true,
|
||||
closable: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,8 +356,6 @@ impl TabPanel {
|
||||
let view = cx.entity().clone();
|
||||
let build_popup_menu = move |this, cx: &App| view.read(cx).popup_menu(this, cx);
|
||||
|
||||
// TODO: Do not show MenuButton if there is no menu items
|
||||
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.occlude()
|
||||
@@ -390,7 +388,7 @@ impl TabPanel {
|
||||
let name = if is_zoomed { "Zoom Out" } else { "Zoom In" };
|
||||
this.separator().menu(name, Box::new(ToggleZoom))
|
||||
})
|
||||
.when(state.closeable, |this| {
|
||||
.when(state.closable, |this| {
|
||||
this.separator().menu("Close", Box::new(ClosePanel))
|
||||
})
|
||||
})
|
||||
@@ -1015,14 +1013,14 @@ impl Render for TabPanel {
|
||||
let focus_handle = self.focus_handle(cx);
|
||||
|
||||
let mut state = TabState {
|
||||
closeable: self.closable(cx),
|
||||
closable: self.closable(cx),
|
||||
draggable: self.draggable(cx),
|
||||
droppable: self.droppable(cx),
|
||||
zoomable: self.zoomable(cx),
|
||||
};
|
||||
|
||||
if !state.draggable {
|
||||
state.closeable = false;
|
||||
state.closable = false;
|
||||
}
|
||||
|
||||
v_flex()
|
||||
|
||||
@@ -495,7 +495,7 @@ impl Element for TextElement {
|
||||
|
||||
// Paint selections
|
||||
if let Some(path) = prepaint.selection_path.take() {
|
||||
window.paint_path(path, cx.theme().accent.step(cx, ColorScaleStep::FIVE));
|
||||
window.paint_path(path, cx.theme().accent.step(cx, ColorScaleStep::FOUR));
|
||||
}
|
||||
|
||||
// Paint multi line text
|
||||
@@ -515,7 +515,7 @@ impl Element for TextElement {
|
||||
|
||||
for line in prepaint.lines.iter() {
|
||||
let p = point(origin.x, origin.y + offset_y);
|
||||
_ = line.paint(p, line_height, window, cx);
|
||||
_ = line.paint(p, line_height, gpui::TextAlign::Left, window, cx);
|
||||
offset_y += line.size(line_height).height;
|
||||
}
|
||||
|
||||
|
||||
@@ -237,16 +237,16 @@ impl Render for Notification {
|
||||
.shadow_md()
|
||||
.p_2()
|
||||
.gap_3()
|
||||
.child(div().absolute().top_3().left_2().child(icon))
|
||||
.child(div().absolute().top_2p5().left_2().child(icon))
|
||||
.child(
|
||||
v_flex()
|
||||
.pl_6()
|
||||
.gap_1()
|
||||
.when_some(self.title.clone(), |this, title| {
|
||||
this.child(div().text_sm().font_semibold().child(title))
|
||||
this.child(div().text_xs().font_semibold().child(title))
|
||||
})
|
||||
.overflow_hidden()
|
||||
.child(div().text_sm().child(self.message.clone())),
|
||||
.child(div().text_xs().child(self.message.clone())),
|
||||
)
|
||||
.when_some(self.on_click.clone(), |this, on_click| {
|
||||
this.cursor_pointer()
|
||||
@@ -370,16 +370,16 @@ impl Render for NotificationList {
|
||||
.child(
|
||||
v_flex()
|
||||
.id("notification-list")
|
||||
.gap_3()
|
||||
.absolute()
|
||||
.relative()
|
||||
.right_0()
|
||||
.h(size.height - px(8.))
|
||||
.children(items)
|
||||
.on_hover(cx.listener(|view, hovered, _window, cx| {
|
||||
view.expanded = *hovered;
|
||||
cx.notify();
|
||||
}))
|
||||
.gap_3()
|
||||
.children(items),
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user