add: community settings ui
TODO: add community read/write access settings TODO: add profile settings TODO: profile following in ui TODO: community joining and membership management in ui
This commit is contained in:
parent
eecf357325
commit
6413ed09fb
20 changed files with 855 additions and 46 deletions
489
Cargo.lock
generated
489
Cargo.lock
generated
|
@ -32,6 +32,19 @@ version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
|
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ammonia"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
|
||||||
|
dependencies = [
|
||||||
|
"html5ever",
|
||||||
|
"maplit",
|
||||||
|
"once_cell",
|
||||||
|
"tendril",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -47,6 +60,56 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"once_cell",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.97"
|
version = "1.0.97"
|
||||||
|
@ -261,6 +324,30 @@ dependencies = [
|
||||||
"tokio-postgres",
|
"tokio-postgres",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bincode"
|
||||||
|
version = "1.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit-set"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
||||||
|
dependencies = [
|
||||||
|
"bit-vec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit-vec"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
|
@ -294,6 +381,31 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bon"
|
||||||
|
version = "3.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65268237be94042665b92034f979c42d431d2fd998b49809543afe3e66abad1c"
|
||||||
|
dependencies = [
|
||||||
|
"bon-macros",
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bon-macros"
|
||||||
|
version = "3.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "803c95b2ecf650eb10b5f87dda6b9f6a1b758cee53245e2b7b825c9b3803a443"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"ident_case",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "1.11.3"
|
version = "1.11.3"
|
||||||
|
@ -340,6 +452,15 @@ version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "caseless"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-normalization",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.16"
|
version = "1.2.16"
|
||||||
|
@ -403,12 +524,59 @@ dependencies = [
|
||||||
"phf_codegen",
|
"phf_codegen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
"terminal_size",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "combine"
|
name = "combine"
|
||||||
version = "4.6.7"
|
version = "4.6.7"
|
||||||
|
@ -419,6 +587,25 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "comrak"
|
||||||
|
version = "0.36.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5afa2702ef2fecc5bd7ca605f37e875a6be3fc8138c4633e711a945b70351550"
|
||||||
|
dependencies = [
|
||||||
|
"bon",
|
||||||
|
"caseless",
|
||||||
|
"clap",
|
||||||
|
"entities",
|
||||||
|
"memchr",
|
||||||
|
"shell-words",
|
||||||
|
"slug",
|
||||||
|
"syntect",
|
||||||
|
"typed-arena",
|
||||||
|
"unicode_categories",
|
||||||
|
"xdg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cookie"
|
name = "cookie"
|
||||||
version = "0.18.1"
|
version = "0.18.1"
|
||||||
|
@ -505,6 +692,41 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -557,6 +779,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "entities"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
@ -606,6 +834,16 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fancy-regex"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2"
|
||||||
|
dependencies = [
|
||||||
|
"bit-set",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
|
@ -667,6 +905,16 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futf"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
|
||||||
|
dependencies = [
|
||||||
|
"mac",
|
||||||
|
"new_debug_unreachable",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
@ -862,6 +1110,20 @@ dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "html5ever"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"mac",
|
||||||
|
"markup5ever",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
|
@ -1137,6 +1399,12 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
@ -1240,6 +1508,12 @@ version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -1324,6 +1598,12 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
|
@ -1361,6 +1641,32 @@ dependencies = [
|
||||||
"imgref",
|
"imgref",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mac"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maplit"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markup5ever"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"phf",
|
||||||
|
"phf_codegen",
|
||||||
|
"string_cache",
|
||||||
|
"string_cache_codegen",
|
||||||
|
"tendril",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchers"
|
name = "matchers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1582,6 +1888,28 @@ version = "1.21.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "onig"
|
||||||
|
version = "6.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"onig_sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "onig_sys"
|
||||||
|
version = "69.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.71"
|
version = "0.10.71"
|
||||||
|
@ -1786,6 +2114,19 @@ version = "0.3.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plist"
|
||||||
|
version = "1.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"indexmap",
|
||||||
|
"quick-xml",
|
||||||
|
"serde",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.16"
|
version = "0.17.16"
|
||||||
|
@ -1843,6 +2184,22 @@ dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "precomputed-hash"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.2.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.94"
|
version = "1.0.94"
|
||||||
|
@ -1886,6 +2243,15 @@ version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-xml"
|
||||||
|
version = "0.32.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
|
@ -2385,6 +2751,12 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shell-words"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -2459,6 +2831,31 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "string_cache"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
|
||||||
|
dependencies = [
|
||||||
|
"new_debug_unreachable",
|
||||||
|
"parking_lot",
|
||||||
|
"phf_shared",
|
||||||
|
"precomputed-hash",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "string_cache_codegen"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
|
||||||
|
dependencies = [
|
||||||
|
"phf_generator",
|
||||||
|
"phf_shared",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stringprep"
|
name = "stringprep"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
@ -2470,6 +2867,12 @@ dependencies = [
|
||||||
"unicode-properties",
|
"unicode-properties",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
@ -2507,6 +2910,29 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syntect"
|
||||||
|
version = "5.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
|
||||||
|
dependencies = [
|
||||||
|
"bincode",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"fancy-regex",
|
||||||
|
"flate2",
|
||||||
|
"fnv",
|
||||||
|
"once_cell",
|
||||||
|
"onig",
|
||||||
|
"plist",
|
||||||
|
"regex-syntax 0.8.5",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"walkdir",
|
||||||
|
"yaml-rust",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -2560,6 +2986,17 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tendril"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0"
|
||||||
|
dependencies = [
|
||||||
|
"futf",
|
||||||
|
"mac",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tera"
|
name = "tera"
|
||||||
version = "1.20.0"
|
version = "1.20.0"
|
||||||
|
@ -2582,6 +3019,16 @@ dependencies = [
|
||||||
"unic-segment",
|
"unic-segment",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "terminal_size"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
|
||||||
|
dependencies = [
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tetratto"
|
name = "tetratto"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -2593,6 +3040,7 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"tera",
|
"tera",
|
||||||
"tetratto-core",
|
"tetratto-core",
|
||||||
"tetratto-l10n",
|
"tetratto-l10n",
|
||||||
|
@ -2633,7 +3081,9 @@ dependencies = [
|
||||||
name = "tetratto-shared"
|
name = "tetratto-shared"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ammonia",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"comrak",
|
||||||
"hex_fmt",
|
"hex_fmt",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"rand 0.9.0",
|
"rand 0.9.0",
|
||||||
|
@ -3001,6 +3451,12 @@ version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-arena"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
|
@ -3096,6 +3552,12 @@ version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
|
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode_categories"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "untrusted"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -3113,6 +3575,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf16_iter"
|
name = "utf16_iter"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
|
@ -3125,6 +3593,12 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
|
@ -3558,6 +4032,21 @@ version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xdg"
|
||||||
|
version = "2.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaml-rust"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yoke"
|
name = "yoke"
|
||||||
version = "0.7.5"
|
version = "0.7.5"
|
||||||
|
|
|
@ -25,3 +25,4 @@ tetratto-l10n = { path = "../l10n" }
|
||||||
image = "0.25.5"
|
image = "0.25.5"
|
||||||
reqwest = "0.12.15"
|
reqwest = "0.12.15"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
|
serde_json = "1.0.140"
|
||||||
|
|
|
@ -11,6 +11,7 @@ version = "1.0.0"
|
||||||
"dialog:action.cancel" = "Cancel"
|
"dialog:action.cancel" = "Cancel"
|
||||||
"dialog:action.yes" = "Yes"
|
"dialog:action.yes" = "Yes"
|
||||||
"dialog:action.no" = "No"
|
"dialog:action.no" = "No"
|
||||||
|
"dialog:action.save_and_close" = "Save and close"
|
||||||
|
|
||||||
"auth:action.login" = "Login"
|
"auth:action.login" = "Login"
|
||||||
"auth:action.register" = "Register"
|
"auth:action.register" = "Register"
|
||||||
|
|
|
@ -7,15 +7,19 @@ use assets::{init_dirs, write_assets};
|
||||||
pub use tetratto_core::*;
|
pub use tetratto_core::*;
|
||||||
|
|
||||||
use axum::{Extension, Router};
|
use axum::{Extension, Router};
|
||||||
use tera::Tera;
|
use tera::{Tera, Value};
|
||||||
use tower_http::trace::{self, TraceLayer};
|
use tower_http::trace::{self, TraceLayer};
|
||||||
use tracing::{Level, info};
|
use tracing::{Level, info};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
pub(crate) type State = Arc<RwLock<(DataManager, Tera)>>;
|
pub(crate) type State = Arc<RwLock<(DataManager, Tera)>>;
|
||||||
|
|
||||||
|
fn render_markdown(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> {
|
||||||
|
Ok(tetratto_shared::markdown::render_markdown(&value.as_str().unwrap()).into())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
|
@ -33,12 +37,12 @@ async fn main() {
|
||||||
let database = DataManager::new(config.clone()).await.unwrap();
|
let database = DataManager::new(config.clone()).await.unwrap();
|
||||||
database.init().await.unwrap();
|
database.init().await.unwrap();
|
||||||
|
|
||||||
|
let mut tera = Tera::new(&format!("{html_path}/**/*")).unwrap();
|
||||||
|
tera.register_filter("markdown", render_markdown);
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.merge(routes::routes(&config))
|
.merge(routes::routes(&config))
|
||||||
.layer(Extension(Arc::new(RwLock::new((
|
.layer(Extension(Arc::new(RwLock::new((database, tera)))))
|
||||||
database,
|
|
||||||
Tera::new(&format!("{html_path}/**/*")).unwrap(),
|
|
||||||
)))))
|
|
||||||
.layer(
|
.layer(
|
||||||
TraceLayer::new_for_http()
|
TraceLayer::new_for_http()
|
||||||
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
|
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
|
||||||
|
|
|
@ -152,7 +152,14 @@ button svg {
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border-top: 1px var(--color-super-lowered);
|
border-top: solid 1px var(--color-super-lowered) !important;
|
||||||
|
border-left: 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr.margin {
|
||||||
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p,
|
p,
|
||||||
|
|
|
@ -25,6 +25,18 @@
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<span class="fade">{{ community.title }}</span>
|
<span class="fade">{{ community.title }}</span>
|
||||||
|
|
||||||
|
{% if user %}
|
||||||
|
<div
|
||||||
|
class="flex gap-1 reactions_box"
|
||||||
|
hook="check_reactions"
|
||||||
|
hook-arg:id="{{ community.id }}"
|
||||||
|
>
|
||||||
|
{{ components::likes(id=community.id,
|
||||||
|
asset_type="Community", likes=community.likes,
|
||||||
|
dislikes=community.dislikes) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -41,15 +53,86 @@
|
||||||
<span>{{ text "communities:action.leave" }}</span>
|
<span>{{ text "communities:action.leave" }}</span>
|
||||||
</button>
|
</button>
|
||||||
{% endif %} {% else %}
|
{% endif %} {% else %}
|
||||||
<a
|
<button
|
||||||
href="/community/{{ community.title }}/manage"
|
href="/community/{{ community.title }}"
|
||||||
class="button primary"
|
class="button primary"
|
||||||
|
onclick="document.getElementById('manage').showModal()"
|
||||||
>
|
>
|
||||||
{{ icon "settings" }}
|
{{ icon "settings" }}
|
||||||
<span
|
<span
|
||||||
>{{ text "communities:action.configure" }}</span
|
>{{ text "communities:action.configure" }}</span
|
||||||
>
|
>
|
||||||
</a>
|
</button>
|
||||||
|
|
||||||
|
<dialog id="manage">
|
||||||
|
<div class="inner">
|
||||||
|
<div
|
||||||
|
id="manage_fields"
|
||||||
|
class="flex flex-col gap-2"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<hr class="margin" />
|
||||||
|
|
||||||
|
<button
|
||||||
|
onclick="document.getElementById('manage').close(); save_context()"
|
||||||
|
>
|
||||||
|
{{ icon "check" }}
|
||||||
|
<span
|
||||||
|
>{{ text "dialog:action.save_and_close"
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
setTimeout(() => {
|
||||||
|
const ui = ns("ui");
|
||||||
|
const settings = JSON.parse(
|
||||||
|
"{{ community_context_serde|safe }}",
|
||||||
|
);
|
||||||
|
|
||||||
|
ui.generate_settings_ui(
|
||||||
|
document.getElementById("manage_fields"),
|
||||||
|
[
|
||||||
|
[
|
||||||
|
["display_name", "Title"],
|
||||||
|
"{{ community.context.display_name }}",
|
||||||
|
"input",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
["description", "Description"],
|
||||||
|
"{{ community.context.description }}",
|
||||||
|
"textarea",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
settings,
|
||||||
|
);
|
||||||
|
|
||||||
|
window.save_context = () => {
|
||||||
|
fetch(
|
||||||
|
`/api/v1/communities/{{ community.id }}/context`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type":
|
||||||
|
"application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
context: settings,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => {
|
||||||
|
trigger("atto::toast", [
|
||||||
|
res.ok ? "success" : "error",
|
||||||
|
res.message,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, 250);
|
||||||
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -57,7 +140,7 @@
|
||||||
|
|
||||||
<div class="card-nest flex flex-col">
|
<div class="card-nest flex flex-col">
|
||||||
<div id="bio" class="card small">
|
<div id="bio" class="card small">
|
||||||
{{ community.context.description }}
|
{{ community.context.description|markdown|safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card flex flex-col gap-2">
|
<div class="card flex flex-col gap-2">
|
||||||
|
|
|
@ -38,6 +38,28 @@
|
||||||
{% if user.settings.display_name %} {{ user.settings.display_name }} {% else
|
{% if user.settings.display_name %} {{ user.settings.display_name }} {% else
|
||||||
%} {{ user.username }} {% endif %}
|
%} {{ user.username }} {% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{%- endmacro %} {% macro likes(id, asset_type, likes=0, dislikes=0) -%}
|
||||||
|
<button
|
||||||
|
title="Like"
|
||||||
|
class="camo small"
|
||||||
|
hook_element="reaction.like"
|
||||||
|
onclick="trigger('me::react', [event.target, '{{ id }}', '{{ asset_type }}', true])"
|
||||||
|
>
|
||||||
|
{{ icon "heart" }} {% if likes > 0 %}
|
||||||
|
<span>{{ likes }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
title="Dislike"
|
||||||
|
class="camo small"
|
||||||
|
hook_element="reaction.dislike"
|
||||||
|
onclick="trigger('me::react', [event.target, '{{ id }}', '{{ asset_type }}', false])"
|
||||||
|
>
|
||||||
|
{{ icon "heart-crack" }} {% if dislikes > 0 %}
|
||||||
|
<span>{{ dislikes }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
{%- endmacro %} {% macro post(post, owner, secondary=false, community=false,
|
{%- endmacro %} {% macro post(post, owner, secondary=false, community=false,
|
||||||
show_community=true) -%}
|
show_community=true) -%}
|
||||||
<div class="card flex flex-col gap-2 {% if secondary %}secondary{% endif %}">
|
<div class="card flex flex-col gap-2 {% if secondary %}secondary{% endif %}">
|
||||||
|
@ -68,21 +90,23 @@ show_community=true) -%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span id="post-content:{{ post.id }}">{{ post.content }}</span>
|
<span id="post-content:{{ post.id }}"
|
||||||
|
>{{ post.content|markdown|safe }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-between items-center gap-2 w-full">
|
<div class="flex justify-between items-center gap-2 w-full">
|
||||||
<div class="flex gap-1 reactions_box">
|
|
||||||
{% if user %}
|
{% if user %}
|
||||||
<button title="Like" class="primary small">
|
<div
|
||||||
{{ icon "heart" }}
|
class="flex gap-1 reactions_box"
|
||||||
</button>
|
hook="check_reactions"
|
||||||
<button title="Dislike" class="secondary small">
|
hook-arg:id="{{ post.id }}"
|
||||||
{{ icon "heart-crack" }}
|
>
|
||||||
</button>
|
{{ components::likes(id=post.id, asset_type="Post",
|
||||||
{% endif %}
|
likes=post.likes, dislikes=post.dislikes) }}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="flex gap-1 buttons_box">
|
<div class="flex gap-1 buttons_box">
|
||||||
<a href="/post/{{ post.id }}" class="button camo small">
|
<a href="/post/{{ post.id }}" class="button camo small">
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
|
|
||||||
<div class="card-nest flex flex-col">
|
<div class="card-nest flex flex-col">
|
||||||
<div id="bio" class="card small">
|
<div id="bio" class="card small">
|
||||||
{{ profile.settings.biography }}
|
{{ profile.settings.biography|markdown|safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card flex flex-col gap-2">
|
<div class="card flex flex-col gap-2">
|
||||||
|
|
|
@ -455,21 +455,33 @@ media_theme_pref();
|
||||||
self.define("hooks::check_reactions", async ({ $ }) => {
|
self.define("hooks::check_reactions", async ({ $ }) => {
|
||||||
const observer = $.offload_work_to_client_when_in_view(
|
const observer = $.offload_work_to_client_when_in_view(
|
||||||
async (element) => {
|
async (element) => {
|
||||||
|
const like = element.querySelector(
|
||||||
|
'[hook_element="reaction.like"]',
|
||||||
|
);
|
||||||
|
|
||||||
|
const dislike = element.querySelector(
|
||||||
|
'[hook_element="reaction.dislike"]',
|
||||||
|
);
|
||||||
|
|
||||||
const reaction = await (
|
const reaction = await (
|
||||||
await fetch(
|
await fetch(
|
||||||
`/api/v1/reactions/${element.getAttribute("hook-arg:id")}`,
|
`/api/v1/reactions/${element.getAttribute("hook-arg:id")}`,
|
||||||
)
|
)
|
||||||
).json();
|
).json();
|
||||||
|
|
||||||
if (reaction.success) {
|
if (reaction.ok) {
|
||||||
element.classList.add("green");
|
if (reaction.payload.is_like) {
|
||||||
element.querySelector("svg").classList.add("filled");
|
like.classList.add("green");
|
||||||
|
like.querySelector("svg").classList.add("filled");
|
||||||
|
} else {
|
||||||
|
dislike.classList.add("red");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const element of Array.from(
|
for (const element of Array.from(
|
||||||
document.querySelectorAll("[hook=check_reaction]") || [],
|
document.querySelectorAll("[hook=check_reactions]") || [],
|
||||||
)) {
|
)) {
|
||||||
observer.observe(element);
|
observer.observe(element);
|
||||||
}
|
}
|
||||||
|
@ -619,3 +631,44 @@ media_theme_pref();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// ui ns
|
||||||
|
(() => {
|
||||||
|
const self = reg_ns("ui");
|
||||||
|
|
||||||
|
self.define("render_settings_ui_field", (_, into_element, option) => {
|
||||||
|
into_element.innerHTML += `<div class="card-nest">
|
||||||
|
<div class="card small">
|
||||||
|
<b>${option.label.replaceAll("_", " ")}</b>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<${option.input_element_type || "input"}
|
||||||
|
type="text"
|
||||||
|
onchange="window.set_setting_field('${option.key}', event.target.value)"
|
||||||
|
placeholder="${option.key}"
|
||||||
|
${option.input_element_type === "input" ? `value="${option.value}"/>` : ">"}
|
||||||
|
${option.input_element_type === "textarea" ? `${option.value}</textarea>` : ""}
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
self.define(
|
||||||
|
"generate_settings_ui",
|
||||||
|
({ $ }, into_element, options, settings_ref) => {
|
||||||
|
for (const option of options) {
|
||||||
|
$.render_settings_ui_field(into_element, {
|
||||||
|
key: Array.isArray(option[0]) ? option[0][0] : option[0],
|
||||||
|
label: Array.isArray(option[0]) ? option[0][1] : option[0],
|
||||||
|
value: option[1],
|
||||||
|
input_element_type: option[2],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.set_setting_field = (key, value) => {
|
||||||
|
settings_ref[key] = value;
|
||||||
|
console.log("update", key);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})();
|
||||||
|
|
|
@ -48,4 +48,47 @@
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.define("react", async (_, element, asset, asset_type, is_like) => {
|
||||||
|
fetch("/api/v1/reactions", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
asset,
|
||||||
|
asset_type,
|
||||||
|
is_like,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => {
|
||||||
|
trigger("atto::toast", [
|
||||||
|
res.ok ? "success" : "error",
|
||||||
|
res.message,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
const like = element.parentElement.querySelector(
|
||||||
|
'[hook_element="reaction.like"]',
|
||||||
|
);
|
||||||
|
|
||||||
|
const dislike = element.parentElement.querySelector(
|
||||||
|
'[hook_element="reaction.dislike"]',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (is_like) {
|
||||||
|
like.classList.add("green");
|
||||||
|
like.querySelector("svg").classList.add("filled");
|
||||||
|
|
||||||
|
dislike.classList.remove("red");
|
||||||
|
} else {
|
||||||
|
dislike.classList.add("red");
|
||||||
|
|
||||||
|
like.classList.remove("green");
|
||||||
|
like.querySelector("svg").classList.remove("filled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -173,7 +173,7 @@ pub struct UpdatePostContext {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CreateReaction {
|
pub struct CreateReaction {
|
||||||
pub asset: usize,
|
pub asset: String,
|
||||||
pub asset_type: AssetType,
|
pub asset_type: AssetType,
|
||||||
pub is_like: bool,
|
pub is_like: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,34 @@ pub async fn create_request(
|
||||||
None => return Json(Error::NotAllowed.into()),
|
None => return Json(Error::NotAllowed.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let asset_id = match req.asset.parse::<usize>() {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => return Json(Error::MiscError(e.to_string()).into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// check for existing reaction
|
||||||
|
if let Ok(r) = data.get_reaction_by_owner_asset(user.id, asset_id).await {
|
||||||
|
match data.delete_reaction(r.id, &user).await {
|
||||||
|
Ok(_) => {
|
||||||
|
// if we're trying to create a reaction of a DIFFERENT TYPE, then
|
||||||
|
// we don't need to return here
|
||||||
|
if r.is_like == req.is_like {
|
||||||
|
return Json(ApiReturn {
|
||||||
|
ok: true,
|
||||||
|
message: "Reaction removed".to_string(),
|
||||||
|
payload: (),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => return Json(e.into()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// create reaction
|
||||||
match data
|
match data
|
||||||
.create_reaction(Reaction::new(
|
.create_reaction(Reaction::new(
|
||||||
user.id,
|
user.id,
|
||||||
req.asset,
|
asset_id,
|
||||||
req.asset_type,
|
req.asset_type,
|
||||||
req.is_like,
|
req.is_like,
|
||||||
))
|
))
|
||||||
|
@ -50,7 +74,7 @@ pub async fn create_request(
|
||||||
message: "Reaction created".to_string(),
|
message: "Reaction created".to_string(),
|
||||||
payload: (),
|
payload: (),
|
||||||
}),
|
}),
|
||||||
Err(e) => return Json(e.into()),
|
Err(e) => Json(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +94,7 @@ pub async fn delete_request(
|
||||||
Err(e) => return Json(e.into()),
|
Err(e) => return Json(e.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
match data.delete_reaction(reaction.id, user).await {
|
match data.delete_reaction(reaction.id, &user).await {
|
||||||
Ok(_) => Json(ApiReturn {
|
Ok(_) => Json(ApiReturn {
|
||||||
ok: true,
|
ok: true,
|
||||||
message: "Reaction deleted".to_string(),
|
message: "Reaction deleted".to_string(),
|
||||||
|
|
|
@ -80,6 +80,15 @@ pub fn community_context(
|
||||||
context.insert("community", &community);
|
context.insert("community", &community);
|
||||||
context.insert("is_owner", &is_owner);
|
context.insert("is_owner", &is_owner);
|
||||||
context.insert("is_joined", &is_joined);
|
context.insert("is_joined", &is_joined);
|
||||||
|
|
||||||
|
if is_owner {
|
||||||
|
context.insert(
|
||||||
|
"community_context_serde",
|
||||||
|
&serde_json::to_string(&community.context)
|
||||||
|
.unwrap()
|
||||||
|
.replace("\"", "\\\""),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `/community/{title}`
|
/// `/community/{title}`
|
||||||
|
|
|
@ -116,14 +116,14 @@ impl DataManager {
|
||||||
|
|
||||||
auto_method!(delete_community()@get_community_by_id:MANAGE_COMMUNITIES -> "DELETE communities pages WHERE id = $1" --cache-key-tmpl=cache_clear_community);
|
auto_method!(delete_community()@get_community_by_id:MANAGE_COMMUNITIES -> "DELETE communities pages WHERE id = $1" --cache-key-tmpl=cache_clear_community);
|
||||||
auto_method!(update_community_title(String)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET title = $1 WHERE id = $2" --cache-key-tmpl=cache_clear_community);
|
auto_method!(update_community_title(String)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET title = $1 WHERE id = $2" --cache-key-tmpl=cache_clear_community);
|
||||||
auto_method!(update_community_context(CommunityContext)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET prompt = $1 WHERE id = $2" --serde --cache-key-tmpl=cache_clear_community);
|
auto_method!(update_community_context(CommunityContext)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET context = $1 WHERE id = $2" --serde --cache-key-tmpl=cache_clear_community);
|
||||||
auto_method!(update_community_read_access(CommunityReadAccess)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET read_access = $1 WHERE id = $2" --serde --cache-key-tmpl=cache_clear_community);
|
auto_method!(update_community_read_access(CommunityReadAccess)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET read_access = $1 WHERE id = $2" --serde --cache-key-tmpl=cache_clear_community);
|
||||||
auto_method!(update_community_write_access(CommunityWriteAccess)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET write_access = $1 WHERE id = $2" --serde --cache-key-tmpl=cache_clear_community);
|
auto_method!(update_community_write_access(CommunityWriteAccess)@get_community_by_id:MANAGE_COMMUNITIES -> "UPDATE communities SET write_access = $1 WHERE id = $2" --serde --cache-key-tmpl=cache_clear_community);
|
||||||
|
|
||||||
auto_method!(incr_community_likes()@get_community_by_id -> "UPDATE communities SET likes = likes + 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --incr);
|
auto_method!(incr_community_likes()@get_community_by_id -> "UPDATE communities SET likes = likes + 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --incr);
|
||||||
auto_method!(incr_community_dislikes()@get_community_by_id -> "UPDATE communities SET likes = dislikes + 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --incr);
|
auto_method!(incr_community_dislikes()@get_community_by_id -> "UPDATE communities SET dislikes = dislikes + 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --incr);
|
||||||
auto_method!(decr_community_likes()@get_community_by_id -> "UPDATE communities SET likes = likes - 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --decr);
|
auto_method!(decr_community_likes()@get_community_by_id -> "UPDATE communities SET likes = likes - 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --decr);
|
||||||
auto_method!(decr_community_dislikes()@get_community_by_id -> "UPDATE communities SET likes = dislikes - 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --decr);
|
auto_method!(decr_community_dislikes()@get_community_by_id -> "UPDATE communities SET dislikes = dislikes - 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --decr);
|
||||||
|
|
||||||
auto_method!(incr_community_member_count()@get_community_by_id -> "UPDATE communities SET member_count = member_count + 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --incr);
|
auto_method!(incr_community_member_count()@get_community_by_id -> "UPDATE communities SET member_count = member_count + 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --incr);
|
||||||
auto_method!(decr_community_member_count()@get_community_by_id -> "UPDATE communities SET member_count = member_count - 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --decr);
|
auto_method!(decr_community_member_count()@get_community_by_id -> "UPDATE communities SET member_count = member_count - 1 WHERE id = $1" --cache-key-tmpl=cache_clear_community --decr);
|
||||||
|
|
|
@ -287,9 +287,9 @@ impl DataManager {
|
||||||
auto_method!(update_post_context(PostContext)@get_post_by_id:MANAGE_POSTS -> "UPDATE posts SET context = $1 WHERE id = $2" --serde --cache-key-tmpl="atto.post:{}");
|
auto_method!(update_post_context(PostContext)@get_post_by_id:MANAGE_POSTS -> "UPDATE posts SET context = $1 WHERE id = $2" --serde --cache-key-tmpl="atto.post:{}");
|
||||||
|
|
||||||
auto_method!(incr_post_likes() -> "UPDATE posts SET likes = likes + 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --incr);
|
auto_method!(incr_post_likes() -> "UPDATE posts SET likes = likes + 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --incr);
|
||||||
auto_method!(incr_post_dislikes() -> "UPDATE posts SET likes = dislikes + 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --incr);
|
auto_method!(incr_post_dislikes() -> "UPDATE posts SET dislikes = dislikes + 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --incr);
|
||||||
auto_method!(decr_post_likes() -> "UPDATE posts SET likes = likes - 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --decr);
|
auto_method!(decr_post_likes() -> "UPDATE posts SET likes = likes - 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --decr);
|
||||||
auto_method!(decr_post_dislikes() -> "UPDATE posts SET likes = dislikes - 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --decr);
|
auto_method!(decr_post_dislikes() -> "UPDATE posts SET dislikes = dislikes - 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --decr);
|
||||||
|
|
||||||
auto_method!(incr_post_comments() -> "UPDATE posts SET comment_count = comment_count + 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --incr);
|
auto_method!(incr_post_comments() -> "UPDATE posts SET comment_count = comment_count + 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --incr);
|
||||||
auto_method!(decr_post_comments() -> "UPDATE posts SET comment_count = comment_count - 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --decr);
|
auto_method!(decr_post_comments() -> "UPDATE posts SET comment_count = comment_count - 1 WHERE id = $1" --cache-key-tmpl="atto.post:{}" --decr);
|
||||||
|
|
|
@ -86,13 +86,25 @@ impl DataManager {
|
||||||
|
|
||||||
// incr corresponding
|
// incr corresponding
|
||||||
match data.asset_type {
|
match data.asset_type {
|
||||||
AssetType::Journal => {
|
AssetType::Community => {
|
||||||
if let Err(e) = self.incr_community_likes(data.id).await {
|
if let Err(e) = {
|
||||||
|
if data.is_like {
|
||||||
|
self.incr_community_likes(data.asset).await
|
||||||
|
} else {
|
||||||
|
self.incr_community_dislikes(data.asset).await
|
||||||
|
}
|
||||||
|
} {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssetType::JournalEntry => {
|
AssetType::Post => {
|
||||||
if let Err(e) = self.incr_post_likes(data.id).await {
|
if let Err(e) = {
|
||||||
|
if data.is_like {
|
||||||
|
self.incr_post_likes(data.asset).await
|
||||||
|
} else {
|
||||||
|
self.incr_post_dislikes(data.asset).await
|
||||||
|
}
|
||||||
|
} {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +114,7 @@ impl DataManager {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_reaction(&self, id: usize, user: User) -> Result<()> {
|
pub async fn delete_reaction(&self, id: usize, user: &User) -> Result<()> {
|
||||||
let reaction = self.get_reaction_by_id(id).await?;
|
let reaction = self.get_reaction_by_id(id).await?;
|
||||||
|
|
||||||
if user.id != reaction.owner {
|
if user.id != reaction.owner {
|
||||||
|
@ -130,13 +142,25 @@ impl DataManager {
|
||||||
|
|
||||||
// decr corresponding
|
// decr corresponding
|
||||||
match reaction.asset_type {
|
match reaction.asset_type {
|
||||||
AssetType::Journal => {
|
AssetType::Community => {
|
||||||
if let Err(e) = self.decr_community_likes(reaction.asset).await {
|
if let Err(e) = {
|
||||||
|
if reaction.is_like {
|
||||||
|
self.decr_community_likes(reaction.asset).await
|
||||||
|
} else {
|
||||||
|
self.decr_community_dislikes(reaction.asset).await
|
||||||
|
}
|
||||||
|
} {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssetType::JournalEntry => {
|
AssetType::Post => {
|
||||||
if let Err(e) = self.decr_post_likes(reaction.asset).await {
|
if let Err(e) = {
|
||||||
|
if reaction.is_like {
|
||||||
|
self.decr_post_likes(reaction.asset).await
|
||||||
|
} else {
|
||||||
|
self.decr_post_dislikes(reaction.asset).await
|
||||||
|
}
|
||||||
|
} {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ use tetratto_shared::{snow::AlmostSnowflake, unix_epoch_timestamp};
|
||||||
/// All of the items which support reactions.
|
/// All of the items which support reactions.
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub enum AssetType {
|
pub enum AssetType {
|
||||||
Journal,
|
Community,
|
||||||
JournalEntry,
|
Post,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
|
|
@ -7,7 +7,9 @@ repository.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ammonia = "4.0.0"
|
||||||
chrono = "0.4.40"
|
chrono = "0.4.40"
|
||||||
|
comrak = "0.36.0"
|
||||||
hex_fmt = "0.3.0"
|
hex_fmt = "0.3.0"
|
||||||
num-bigint = "0.4.6"
|
num-bigint = "0.4.6"
|
||||||
rand = "0.9.0"
|
rand = "0.9.0"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
|
pub mod markdown;
|
||||||
pub mod snow;
|
pub mod snow;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
|
||||||
|
|
44
crates/shared/src/markdown.rs
Normal file
44
crates/shared/src/markdown.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
use ammonia::Builder;
|
||||||
|
use comrak::{Options, markdown_to_html};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
/// Render markdown input into HTML
|
||||||
|
pub fn render_markdown(input: &str) -> String {
|
||||||
|
let mut options = Options::default();
|
||||||
|
|
||||||
|
options.extension.table = true;
|
||||||
|
options.extension.superscript = true;
|
||||||
|
options.extension.strikethrough = true;
|
||||||
|
options.extension.autolink = true;
|
||||||
|
options.extension.header_ids = Option::Some(String::new());
|
||||||
|
options.extension.tagfilter = true;
|
||||||
|
options.render.unsafe_ = true;
|
||||||
|
// options.render.escape = true;
|
||||||
|
options.parse.smart = false;
|
||||||
|
|
||||||
|
let html = markdown_to_html(input, &options);
|
||||||
|
|
||||||
|
let mut allowed_attributes = HashSet::new();
|
||||||
|
allowed_attributes.insert("id");
|
||||||
|
allowed_attributes.insert("class");
|
||||||
|
allowed_attributes.insert("ref");
|
||||||
|
allowed_attributes.insert("aria-label");
|
||||||
|
allowed_attributes.insert("lang");
|
||||||
|
allowed_attributes.insert("title");
|
||||||
|
allowed_attributes.insert("align");
|
||||||
|
|
||||||
|
allowed_attributes.insert("data-color");
|
||||||
|
allowed_attributes.insert("data-font-family");
|
||||||
|
|
||||||
|
Builder::default()
|
||||||
|
.generic_attributes(allowed_attributes)
|
||||||
|
.clean(&html)
|
||||||
|
.to_string()
|
||||||
|
.replace(
|
||||||
|
"src=\"",
|
||||||
|
"loading=\"lazy\" src=\"/api/v1/util/ext/image?img=",
|
||||||
|
)
|
||||||
|
.replace("-->", "<align class=\"right\">")
|
||||||
|
.replace("->", "<align class=\"center\">")
|
||||||
|
.replace("<-", "</align>")
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue