Compare commits
82 Commits
7989d86af1
...
renovate/v
Author | SHA1 | Date | |
---|---|---|---|
8dfc4f2694 | |||
b2da9b5dc5 | |||
ff578ab849
|
|||
0cffafcd77 | |||
e88ad47af9 | |||
bf6c3d5cb0
|
|||
2f101bedc3 | |||
30b118a621 | |||
cf359b4950
|
|||
c101fba07c | |||
01778866e0 | |||
2bfa5161ee | |||
ae57282dda | |||
0e022fabef | |||
b0623a3f1b | |||
56afe2688d | |||
66179ba858 | |||
63f82eab07
|
|||
f00adf9276
|
|||
216b4cee80
|
|||
cdc02a601d
|
|||
8bcb479b57
|
|||
b9d5c25137 | |||
e9fb20ad6e
|
|||
d98222cd4a | |||
c6effdfa15
|
|||
f17986fa16 | |||
cc65e7d5ff
|
|||
1f42eaa37c | |||
acbe15ed69
|
|||
4671a5ee51
|
|||
9e7ba84576
|
|||
a8a7b16e9f
|
|||
8684086c74
|
|||
cd0a763c0a
|
|||
4d6d6d3515
|
|||
2bdd0b6a6d
|
|||
a9996d448c
|
|||
d5e92f282a
|
|||
285d4ba590
|
|||
6b8cef176f
|
|||
60756b7e72
|
|||
18ee33d512
|
|||
e2c20e4c64
|
|||
28aa250f58
|
|||
d29a3a0821
|
|||
570c792bf4
|
|||
fb37125740 | |||
6ce395cf7c | |||
a4eae624d3
|
|||
f53e4fbadf
|
|||
b4bc48d576
|
|||
b435bc73a7
|
|||
a741c6ea8e
|
|||
c761b203cc
|
|||
d85a2a97b7
|
|||
403d238463
|
|||
581a3d159a
|
|||
4bbe863a56
|
|||
722d98f5d1
|
|||
219fac87b1
|
|||
c9deeea36f
|
|||
d19a8a7f7d
|
|||
5bc8ac409e
|
|||
6586edf287
|
|||
a533f1869d
|
|||
6b9ef5dc90
|
|||
93b6027c73
|
|||
8026b6fa32
|
|||
8652d56f51
|
|||
c5045c328c | |||
ba96ad77d3
|
|||
5ff06c93f4 | |||
831085e8b6
|
|||
691dc7572a
|
|||
b728f6efcd
|
|||
d8e3d49d95
|
|||
9b2ab337b2
|
|||
deb3e273f4
|
|||
abea905feb
|
|||
c7955d5571
|
|||
f99296bdce
|
18
.woodpecker/.audit.yaml
Normal file
18
.woodpecker/.audit.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
variables:
|
||||
- shared-config: &shared-config
|
||||
image: rg.fr-par.scw.cloud/asr-projects/beau-gosse-du-92/ci-lint-audit:latest
|
||||
pull: true
|
||||
|
||||
steps:
|
||||
- name: dependencies
|
||||
<<: *shared-config
|
||||
commands: |
|
||||
cargo deny check
|
||||
# Not ready to block PR on fail
|
||||
failure: ignore
|
||||
|
||||
when:
|
||||
- event: pull_request
|
||||
|
||||
depends_on:
|
||||
- lint
|
18
.woodpecker/.dependencies.yaml
Normal file
18
.woodpecker/.dependencies.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
steps:
|
||||
- name: renovate
|
||||
image: renovate/renovate
|
||||
pull: true
|
||||
commands:
|
||||
- renovate $${CI_REPO}
|
||||
environment:
|
||||
RENOVATE_PLATFORM: gitea
|
||||
RENOVATE_ENDPOINT: https://git.adrien.run
|
||||
RENOVATE_GIT_AUTHOR: renovate-bot <renovate-bot@adrien.run>
|
||||
RENOVATE_TOKEN:
|
||||
from_secret: renovate-bot-mr-token
|
||||
LOG_LEVEL: debug
|
||||
|
||||
when:
|
||||
- event: cron
|
||||
cron: renovate
|
||||
- event: manual
|
@@ -16,10 +16,6 @@ steps:
|
||||
repo: rg.fr-par.scw.cloud/asr-projects/beau-gosse-du-92-web
|
||||
container: beau-gosse-du-92-web
|
||||
tag: ${CI_COMMIT_SHA}
|
||||
secrets:
|
||||
- kubernetes_cert
|
||||
- kubernetes_server
|
||||
- kubernetes_token
|
||||
|
||||
when:
|
||||
- event: push
|
||||
|
@@ -6,6 +6,7 @@ steps:
|
||||
repo: asr-projects/beau-gosse-du-92-web
|
||||
tags: ${CI_COMMIT_SHA}
|
||||
auto_tag: true
|
||||
cache: false
|
||||
username: nologin
|
||||
password:
|
||||
from_secret: registry-password
|
||||
@@ -13,3 +14,6 @@ steps:
|
||||
when:
|
||||
- event: push
|
||||
branch: ${CI_REPO_DEFAULT_BRANCH}
|
||||
|
||||
# depends_on:
|
||||
# - validate
|
||||
|
17
.woodpecker/.lint-audit-image.yaml
Normal file
17
.woodpecker/.lint-audit-image.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
steps:
|
||||
dockerize:
|
||||
image: woodpeckerci/plugin-kaniko
|
||||
settings:
|
||||
registry: rg.fr-par.scw.cloud
|
||||
repo: asr-projects/beau-gosse-du-92/ci-lint-audit
|
||||
dockerfile: ./docker/Dockerfile.ci-lint-audit
|
||||
tags: latest
|
||||
auto_tag: false
|
||||
cache: false
|
||||
username: nologin
|
||||
password:
|
||||
from_secret: registry-password
|
||||
|
||||
when:
|
||||
- event: push
|
||||
path: ./docker/Dockerfile.ci-lint-audit
|
45
.woodpecker/.lint.yaml
Normal file
45
.woodpecker/.lint.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
variables:
|
||||
- shared-config: &shared-config
|
||||
image: rg.fr-par.scw.cloud/asr-projects/beau-gosse-du-92/ci-lint-audit:latest
|
||||
pull: true
|
||||
|
||||
steps:
|
||||
- name: format
|
||||
<<: *shared-config
|
||||
commands: |
|
||||
cargo fmt --all --check
|
||||
|
||||
- name: sort derives
|
||||
<<: *shared-config
|
||||
commands: |
|
||||
cargo sort-derives --check
|
||||
|
||||
- name: clippy
|
||||
<<: *shared-config
|
||||
commands: |
|
||||
cargo clippy --all --all-features -- -D warnings
|
||||
# Not ready to block PR on fail
|
||||
failure: ignore
|
||||
|
||||
- name: spellcheck
|
||||
<<: *shared-config
|
||||
commands: |
|
||||
cargo spellcheck
|
||||
|
||||
- name: dependencies
|
||||
<<: *shared-config
|
||||
commands: |
|
||||
cargo udeps
|
||||
|
||||
- name: dockerizable (web)
|
||||
image: woodpeckerci/plugin-kaniko
|
||||
settings:
|
||||
registry: rg.fr-par.scw.cloud
|
||||
repo: asr-projects/beau-gosse-du-92-web
|
||||
username: nologin
|
||||
password:
|
||||
from_secret: registry-password
|
||||
dry-run: true
|
||||
|
||||
when:
|
||||
- event: pull_request
|
51
Cargo.toml
51
Cargo.toml
@@ -2,14 +2,18 @@
|
||||
name = "beau-gosse-du-92"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
[package.metadata.spellcheck]
|
||||
config = "./spellcheck.toml"
|
||||
|
||||
[dependencies]
|
||||
# Errors
|
||||
anyhow = "1.0.75"
|
||||
thiserror = "1.0.50"
|
||||
thiserror = "2.0.0"
|
||||
|
||||
# Async
|
||||
async-std = "1.12.0"
|
||||
@@ -22,12 +26,12 @@ tokio-stream = "0.1.15"
|
||||
# Utils
|
||||
base64 = "0.22.0"
|
||||
const_format = "0.2.32"
|
||||
rand = "0.8.5"
|
||||
validator = { version = "0.17.0", features = ["derive"] }
|
||||
rand = "0.9.1"
|
||||
validator = { version = "0.20.0", features = ["derive"] }
|
||||
# Http client
|
||||
reqwest = "0.11.24"
|
||||
reqwest = "0.12.0"
|
||||
# Password strength estimation
|
||||
zxcvbn = "2.2.2"
|
||||
zxcvbn = { version = "3.0.0", features = ["ser"] }
|
||||
# Image processing/conversion
|
||||
image = "0.25.1"
|
||||
# Get the application version
|
||||
@@ -40,44 +44,59 @@ tracing = "0.1.40"
|
||||
tracing-forest = "0.1.6"
|
||||
|
||||
# SCSS -> CSS + usage in rust code
|
||||
turf = "0.9.3"
|
||||
turf = "0.10.0"
|
||||
|
||||
# Dioxus
|
||||
# dioxus-free-icons = { version = "0.8", features = ["ionicons", "font-awesome-solid"] }
|
||||
dioxus-free-icons = { git = "https://github.com/ASR-ASU/dioxus-free-icons.git", branch = "asr/dioxus-0.6", features = ["ionicons", "font-awesome-solid"] }
|
||||
modx = "0.1.2"
|
||||
|
||||
# Matrix rich text editor
|
||||
wysiwyg = { path = "../matrix.org/matrix-rich-text-editor/crates/wysiwyg/" }
|
||||
dioxus-free-icons = { version = "0.9", features = ["ionicons", "font-awesome-solid"] }
|
||||
modx = "0.1.4"
|
||||
|
||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||
# Utils
|
||||
getrandom = { version = "0.3.2", features = ["wasm_js"] }
|
||||
|
||||
# Logging/tracing
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
tracing-web = "0.1.3"
|
||||
|
||||
# Dioxus
|
||||
dioxus = { git = "https://github.com/DioxusLabs/dioxus.git", branch = "main", features = ["web"] }
|
||||
dioxus = { version = "0.6.3", features = ["web"] }
|
||||
web-sys = "0.3.69"
|
||||
|
||||
# Matrix
|
||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", default-features = false, features = ["rustls-tls", "js"] }
|
||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", rev = "fa6066b8", default-features = false, features = ["rustls-tls", "js"] }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
# Utils
|
||||
time = "0.3.36"
|
||||
getrandom = { version = "0.3.2" }
|
||||
|
||||
# Logging/tracing
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "time"] }
|
||||
|
||||
# Dioxus
|
||||
dioxus = { git = "https://github.com/DioxusLabs/dioxus.git", branch = "main", features = ["desktop"] }
|
||||
dioxus = { version = "0.6.3", features = ["desktop"] }
|
||||
|
||||
# Matrix
|
||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", default-features = false, features = ["rustls-tls"] }
|
||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", rev = "fa6066b8", default-features = false, features = ["rustls-tls"] }
|
||||
|
||||
[target.wasm32-unknown-unknown]
|
||||
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']
|
||||
|
||||
[build-dependencies]
|
||||
regex = "1.10.3"
|
||||
|
||||
[profile]
|
||||
|
||||
[profile.wasm-dev]
|
||||
inherits = "dev"
|
||||
opt-level = 1
|
||||
|
||||
[profile.server-dev]
|
||||
inherits = "dev"
|
||||
|
||||
[profile.android-dev]
|
||||
inherits = "dev"
|
||||
|
||||
[package.metadata.turf]
|
||||
minify = true
|
||||
|
||||
|
@@ -7,14 +7,7 @@ title = "BG92"
|
||||
|
||||
[web.watcher]
|
||||
reload_html = true
|
||||
watch_path = ["public/index.html", "public/assets/index.css", "src"]
|
||||
|
||||
[web.resource]
|
||||
style = ["assets/index.css"]
|
||||
|
||||
[web.resource.dev]
|
||||
style = []
|
||||
script = []
|
||||
watch_path = ["Dioxus.toml", "public/index.html", "src"]
|
||||
|
||||
[[web.proxy]]
|
||||
backend = "http://localhost:8000/api/"
|
||||
|
15
Dockerfile
15
Dockerfile
@@ -1,7 +1,4 @@
|
||||
FROM rust:latest AS builder
|
||||
|
||||
# Homemade docker image providing the dioxus-cli
|
||||
COPY --from=rg.fr-par.scw.cloud/asr-projects/dioxus-cli:asr-0.5.2 /usr/local/bin/dx /usr/local/bin/dx
|
||||
FROM rg.fr-par.scw.cloud/asr-projects/dioxus-cli-0.6.3:latest AS builder
|
||||
|
||||
ARG JOBS_NB=${JOBS_NB:-default}
|
||||
# Disable incremental compilation
|
||||
@@ -10,16 +7,20 @@ ARG CARGO_INCREMENTAL=0
|
||||
|
||||
WORKDIR /usr/src/beau-gosse-du-92
|
||||
|
||||
# git is required by the git-version crate
|
||||
RUN apt update \
|
||||
&& apt install -y git-lfs
|
||||
&& apt install -y --no-install-recommends git git-lfs \
|
||||
&& apt clean
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN /usr/local/bin/dx build -r --platform web -- -j ${JOBS_NB}
|
||||
# Workaround waiting for the dioxus 0.7 release (cf. https://github.com/DioxusLabs/dioxus/issues/4238)
|
||||
ENV RUSTFLAGS="--cfg getrandom_backend=\"wasm_js\""
|
||||
RUN dx build -r --platform web -- -j ${JOBS_NB}
|
||||
|
||||
|
||||
FROM nginx:mainline-alpine-slim
|
||||
|
||||
WORKDIR /usr/share/nginx/html
|
||||
|
||||
COPY --from=builder /usr/src/beau-gosse-du-92/dist .
|
||||
COPY --from=builder /usr/src/beau-gosse-du-92/target/dx/beau-gosse-du-92/release/web/public .
|
||||
|
12
README.md
12
README.md
@@ -14,8 +14,8 @@ reinvent the wheel. This solution provides:
|
||||
- [Open-source protocol](https://spec.matrix.org/v1.9/).
|
||||
- Features expected for a messaging solution in 2024 (multi-devices management, emojis, integrations, redaction,
|
||||
spaces, ...).
|
||||
- Multi-platforms clients (Android, iOS and Webclient).
|
||||
- SDK available for each platform and a new Rust sdk supporting all the previously listed platforms.
|
||||
- Multi-platforms clients (Android, iOS and web-client).
|
||||
- SDK available for each platform and a new Rust SDK supporting all the previously listed platforms.
|
||||
- Conference stack ([Element Call](https://github.com/element-hq/element-call)).
|
||||
- End-to-end encryption.
|
||||
- Federation management.
|
||||
@@ -28,16 +28,16 @@ API)](https://spec.matrix.org/v1.9/client-server-api/) protocol.
|
||||
|
||||
Even if the Rust SDK is still in beta, it seems to be the future one (cf. [Element X - experience the future of
|
||||
Element!](https://element.io/blog/element-x-experience-the-future-of-element/)) and a good choice for someone starting a
|
||||
new client... from my point of vue.
|
||||
new client... from my point of view.
|
||||
|
||||
The SDK choosen, a Rust (to avoid to use the bindings provided by the matrix-rust-sdk and mostly because I want to
|
||||
The SDK chosen, a Rust (to avoid to use the bindings provided by the matrix-rust-sdk and mostly because I want to
|
||||
learn Rust) graphical library should be selected. The [Dioxus](https://dioxuslabs.com/) one seems to do the job:
|
||||
|
||||
- React-inspired library for Rust.
|
||||
- Multi-platforms (use of Webview or WGPU-enabled renderers).
|
||||
- Multi-platforms (use of Web-view or WGPU-enabled renderers).
|
||||
|
||||
# TODO
|
||||
|
||||
- [ ] Test dioxus-radio.
|
||||
- [ ] Design system ?
|
||||
- [ ] Implement MSN messenger features using Matrix.org sdk...
|
||||
- [ ] Implement MSN messenger features using Matrix.org SDK...
|
||||
|
49
build.rs
49
build.rs
@@ -15,26 +15,27 @@ fn main() {
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
// Global tokens
|
||||
tasks.push(Task::new(
|
||||
PathBuf::from("src/ui/_base.scss"),
|
||||
Path::new(&out_dir).join("style_tokens.rs"),
|
||||
"style".to_string(),
|
||||
));
|
||||
// variables defined by the Panel component
|
||||
tasks.push(Task::new(
|
||||
PathBuf::from("src/ui/components/_panel.scss"),
|
||||
Path::new(&out_dir).join("style_component_panel.rs"),
|
||||
"panel".to_string(),
|
||||
));
|
||||
// Variables set by the Conversations layout
|
||||
tasks.push(Task::new(
|
||||
PathBuf::from("src/ui/layouts/conversations.scss"),
|
||||
Path::new(&out_dir).join("style_layout_conversations.rs"),
|
||||
"conversations".to_string(),
|
||||
));
|
||||
// let mut tasks = Vec::new();
|
||||
let tasks = vec![
|
||||
// Global tokens
|
||||
Task::new(
|
||||
PathBuf::from("src/ui/_base.scss"),
|
||||
Path::new(&out_dir).join("style_tokens.rs"),
|
||||
"style".to_string(),
|
||||
),
|
||||
// variables defined by the Panel component
|
||||
Task::new(
|
||||
PathBuf::from("src/ui/components/_panel.scss"),
|
||||
Path::new(&out_dir).join("style_component_panel.rs"),
|
||||
"panel".to_string(),
|
||||
),
|
||||
// Variables set by the Conversations layout
|
||||
Task::new(
|
||||
PathBuf::from("src/ui/layouts/conversations.scss"),
|
||||
Path::new(&out_dir).join("style_layout_conversations.rs"),
|
||||
"conversations".to_string(),
|
||||
),
|
||||
];
|
||||
|
||||
export_variables(tasks)
|
||||
}
|
||||
@@ -123,7 +124,7 @@ fn export_variables(tasks: Vec<Task>) {
|
||||
"#[allow(dead_code)]\nmod {} {{\n",
|
||||
task.module_name
|
||||
)) {
|
||||
println!("{}", err);
|
||||
println!("{err}");
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -142,14 +143,14 @@ fn export_variables(tasks: Vec<Task>) {
|
||||
}
|
||||
|
||||
for variable in variables {
|
||||
if let Err(err) = dst_file.write_fmt(format_args!(" pub {}\n", variable)) {
|
||||
println!("{}", err);
|
||||
if let Err(err) = dst_file.write_fmt(format_args!(" pub {variable}\n")) {
|
||||
println!("{err}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(err) = dst_file.write(b"}\n") {
|
||||
println!("{}", err);
|
||||
println!("{err}");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
298
deny.toml
Normal file
298
deny.toml
Normal file
@@ -0,0 +1,298 @@
|
||||
# This template contains all of the possible sections and their default values
|
||||
|
||||
# Note that all fields that take a lint level have these possible values:
|
||||
# * deny - An error will be produced and the check will fail
|
||||
# * warn - A warning will be produced, but the check will not fail
|
||||
# * allow - No warning or error will be produced, though in some cases a note
|
||||
# will be
|
||||
|
||||
# The values provided in this template are the default values that will be used
|
||||
# when any section or field is not specified in your own configuration
|
||||
|
||||
# Root options
|
||||
|
||||
# The graph table configures how the dependency graph is constructed and thus
|
||||
# which crates the checks are performed against
|
||||
[graph]
|
||||
# If 1 or more target triples (and optionally, target_features) are specified,
|
||||
# only the specified targets will be checked when running `cargo deny check`.
|
||||
# This means, if a particular package is only ever used as a target specific
|
||||
# dependency, such as, for example, the `nix` crate only being used via the
|
||||
# `target_family = "unix"` configuration, that only having windows targets in
|
||||
# this list would mean the nix crate, as well as any of its exclusive
|
||||
# dependencies not shared by any other crates, would be ignored, as the target
|
||||
# list here is effectively saying which targets you are building for.
|
||||
targets = [
|
||||
# The triple can be any string, but only the target triples built in to
|
||||
# rustc (as of 1.40) can be checked against actual config expressions
|
||||
#"x86_64-unknown-linux-musl",
|
||||
# You can also specify which target_features you promise are enabled for a
|
||||
# particular target. target_features are currently not validated against
|
||||
# the actual valid features supported by the target architecture.
|
||||
#{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
|
||||
]
|
||||
# When creating the dependency graph used as the source of truth when checks are
|
||||
# executed, this field can be used to prune crates from the graph, removing them
|
||||
# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate
|
||||
# is pruned from the graph, all of its dependencies will also be pruned unless
|
||||
# they are connected to another crate in the graph that hasn't been pruned,
|
||||
# so it should be used with care. The identifiers are [Package ID Specifications]
|
||||
# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html)
|
||||
#exclude = []
|
||||
# If true, metadata will be collected with `--all-features`. Note that this can't
|
||||
# be toggled off if true, if you want to conditionally enable `--all-features` it
|
||||
# is recommended to pass `--all-features` on the cmd line instead
|
||||
all-features = false
|
||||
# If true, metadata will be collected with `--no-default-features`. The same
|
||||
# caveat with `all-features` applies
|
||||
no-default-features = false
|
||||
# If set, these feature will be enabled when collecting metadata. If `--features`
|
||||
# is specified on the cmd line they will take precedence over this option.
|
||||
#features = []
|
||||
|
||||
# The output table provides options for how/if diagnostics are outputted
|
||||
[output]
|
||||
# When outputting inclusion graphs in diagnostics that include features, this
|
||||
# option can be used to specify the depth at which feature edges will be added.
|
||||
# This option is included since the graphs can be quite large and the addition
|
||||
# of features from the crate(s) to all of the graph roots can be far too verbose.
|
||||
# This option can be overridden via `--feature-depth` on the cmd line
|
||||
feature-depth = 1
|
||||
|
||||
# This section is considered when running `cargo deny check advisories`
|
||||
# More documentation for the advisories section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
||||
[advisories]
|
||||
# The path where the advisory databases are cloned/fetched into
|
||||
#db-path = "$CARGO_HOME/advisory-dbs"
|
||||
# The url(s) of the advisory databases to use
|
||||
#db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
||||
# output a note when they are encountered.
|
||||
ignore = [
|
||||
#"RUSTSEC-0000-0000",
|
||||
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
||||
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
||||
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
||||
]
|
||||
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
||||
# If this is false, then it uses a built-in git library.
|
||||
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
||||
# See Git Authentication for more information about setting up git authentication.
|
||||
#git-fetch-with-cli = true
|
||||
|
||||
# This section is considered when running `cargo deny check licenses`
|
||||
# More documentation for the licenses section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
||||
[licenses]
|
||||
version = 2
|
||||
# List of explicitly allowed licenses
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||
allow = [
|
||||
# Free software licenses compatible with (A)GPL.
|
||||
# List extracted from: https://www.gnu.org/licenses/license-list.en.html#GPLCompatibleLicenses
|
||||
# "GPL-3.0",
|
||||
# "GPL-2.0",
|
||||
"LGPL-3.0",
|
||||
# "LGPL-2.1",
|
||||
"AGPL-3.0",
|
||||
# "FSFAP",
|
||||
"Apache-2.0",
|
||||
"Apache-2.0 WITH LLVM-exception",
|
||||
# "Artistic-2.0",
|
||||
# "ClArtistic",
|
||||
# "Sleepycat",
|
||||
"BSL-1.0",
|
||||
"BSD-3-Clause",
|
||||
# "CECILL-2.0",
|
||||
# "BSD-3-Clause-Clear",
|
||||
# "ECL-2.0",
|
||||
# "EFL-2.0",
|
||||
# "EUDatagrid",
|
||||
"MIT",
|
||||
"BSD-2-Clause",
|
||||
# "FTL",
|
||||
# "HPND",
|
||||
# "iMatix",
|
||||
# "Imlib2",
|
||||
# "IJG",
|
||||
# "Intel",
|
||||
"ISC",
|
||||
"MPL-2.0",
|
||||
"NCSA",
|
||||
# "OLDAP-2.7",
|
||||
# "NIST-PD",
|
||||
# "CC-PDDC",
|
||||
"CC0-1.0",
|
||||
# "Python-2.0",
|
||||
# "Ruby",
|
||||
# "SGI-B-2.0",
|
||||
# "SMLNJ",
|
||||
# "UPL-1.0",
|
||||
"Unlicense",
|
||||
# "Vim",
|
||||
# "W3C",
|
||||
# "WTFPL",
|
||||
# "X11",
|
||||
# "XFree86-1.1",
|
||||
"Zlib",
|
||||
# "zlib-acknowledgement",
|
||||
# "ZPL-2.0",
|
||||
# "ZPL-2.1",
|
||||
# Not expressely listed as (A)GPL compatible in the page above, but
|
||||
# according to https://opensource.org/licenses/0BSD it is a modification
|
||||
# of the ISC license, which is compatible. Its text is also extremely
|
||||
# simple and allows using the code for any purpose
|
||||
"0BSD",
|
||||
# Permissive license used by the Unicode consortium, similar in spirit
|
||||
# to other permissive licenses:
|
||||
# https://spdx.org/licenses/Unicode-DFS-2016.html
|
||||
"Unicode-DFS-2016",
|
||||
# Permissive license used by the Unicode consortium, similar in spirit
|
||||
# to other permissive licenses:
|
||||
# https://spdx.org/licenses/Unicode-3.0.html
|
||||
"Unicode-3.0",
|
||||
]
|
||||
# The confidence threshold for detecting a license from license text.
|
||||
# The higher the value, the more closely the license text must be to the
|
||||
# canonical license text of a valid SPDX license file.
|
||||
# [possible values: any between 0.0 and 1.0].
|
||||
confidence-threshold = 0.8
|
||||
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
|
||||
# aren't accepted for every possible crate as with the normal allow list
|
||||
exceptions = [
|
||||
# Each entry is the crate and version constraint, and its specific allow
|
||||
# list
|
||||
#{ allow = ["Zlib"], crate = "adler32" },
|
||||
]
|
||||
|
||||
# Some crates don't have (easily) machine readable licensing information,
|
||||
# adding a clarification entry for it allows you to manually specify the
|
||||
# licensing information
|
||||
# [[licenses.clarify]]
|
||||
# The package spec the clarification applies to
|
||||
# crate = "ring"
|
||||
# The SPDX expression for the license requirements of the crate
|
||||
# expression = "MIT AND ISC AND OpenSSL"
|
||||
# One or more files in the crate's source used as the "source of truth" for
|
||||
# the license expression. If the contents match, the clarification will be used
|
||||
# when running the license check, otherwise the clarification will be ignored
|
||||
# and the crate will be checked normally, which may produce warnings or errors
|
||||
# depending on the rest of your configuration
|
||||
# license-files = [
|
||||
#Each entry is a crate relative path, and the (opaque) hash of its contents
|
||||
# { path = "LICENSE", hash = 0xbd0eed23 }
|
||||
# ]
|
||||
|
||||
[licenses.private]
|
||||
# If true, ignores workspace crates that aren't published, or are only
|
||||
# published to private registries.
|
||||
# To see how to mark a crate as unpublished (to the official registry),
|
||||
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
|
||||
ignore = false
|
||||
# One or more private registries that you might publish crates to, if a crate
|
||||
# is only published to private registries, and ignore is true, the crate will
|
||||
# not have its license(s) checked
|
||||
registries = [
|
||||
#"https://sekretz.com/registry
|
||||
]
|
||||
|
||||
# This section is considered when running `cargo deny check bans`.
|
||||
# More documentation about the 'bans' section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
|
||||
[bans]
|
||||
# Lint level for when multiple versions of the same crate are detected
|
||||
multiple-versions = "warn"
|
||||
# Lint level for when a crate version requirement is `*`
|
||||
wildcards = "allow"
|
||||
# The graph highlighting used when creating dotgraphs for crates
|
||||
# with multiple versions
|
||||
# * lowest-version - The path to the lowest versioned duplicate is highlighted
|
||||
# * simplest-path - The path to the version with the fewest edges is highlighted
|
||||
# * all - Both lowest-version and simplest-path are used
|
||||
highlight = "all"
|
||||
# The default lint level for `default` features for crates that are members of
|
||||
# the workspace that is being checked. This can be overridden by allowing/denying
|
||||
# `default` on a crate-by-crate basis if desired.
|
||||
workspace-default-features = "allow"
|
||||
# The default lint level for `default` features for external crates that are not
|
||||
# members of the workspace. This can be overridden by allowing/denying `default`
|
||||
# on a crate-by-crate basis if desired.
|
||||
external-default-features = "allow"
|
||||
# List of crates that are allowed. Use with care!
|
||||
allow = [
|
||||
#"ansi_term@0.11.0",
|
||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" },
|
||||
]
|
||||
# List of crates to deny
|
||||
deny = [
|
||||
#"ansi_term@0.11.0",
|
||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" },
|
||||
# Wrapper crates can optionally be specified to allow the crate when it
|
||||
# is a direct dependency of the otherwise banned crate
|
||||
#{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] },
|
||||
]
|
||||
|
||||
# List of features to allow/deny
|
||||
# Each entry the name of a crate and a version range. If version is
|
||||
# not specified, all versions will be matched.
|
||||
#[[bans.features]]
|
||||
#crate = "reqwest"
|
||||
# Features to not allow
|
||||
#deny = ["json"]
|
||||
# Features to allow
|
||||
#allow = [
|
||||
# "rustls",
|
||||
# "__rustls",
|
||||
# "__tls",
|
||||
# "hyper-rustls",
|
||||
# "rustls",
|
||||
# "rustls-pemfile",
|
||||
# "rustls-tls-webpki-roots",
|
||||
# "tokio-rustls",
|
||||
# "webpki-roots",
|
||||
#]
|
||||
# If true, the allowed features must exactly match the enabled feature set. If
|
||||
# this is set there is no point setting `deny`
|
||||
#exact = true
|
||||
|
||||
# Certain crates/versions that will be skipped when doing duplicate detection.
|
||||
skip = [
|
||||
#"ansi_term@0.11.0",
|
||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" },
|
||||
]
|
||||
# Similarly to `skip` allows you to skip certain crates during duplicate
|
||||
# detection. Unlike skip, it also includes the entire tree of transitive
|
||||
# dependencies starting at the specified crate, up to a certain depth, which is
|
||||
# by default infinite.
|
||||
skip-tree = [
|
||||
#"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies
|
||||
#{ crate = "ansi_term@0.11.0", depth = 20 },
|
||||
]
|
||||
|
||||
# This section is considered when running `cargo deny check sources`.
|
||||
# More documentation about the 'sources' section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
|
||||
[sources]
|
||||
# Lint level for what to happen when a crate from a crate registry that is not
|
||||
# in the allow list is encountered
|
||||
unknown-registry = "warn"
|
||||
# Lint level for what to happen when a crate from a git repository that is not
|
||||
# in the allow list is encountered
|
||||
unknown-git = "warn"
|
||||
# List of URLs for allowed crate registries. Defaults to the crates.io index
|
||||
# if not specified. If it is specified but empty, no registries are allowed.
|
||||
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||
# List of URLs for allowed Git repositories
|
||||
allow-git = [
|
||||
"https://github.com/matrix-org/matrix-rust-sdk.git"
|
||||
]
|
||||
|
||||
[sources.allow-org]
|
||||
# github.com organizations to allow git sources for
|
||||
github = []
|
||||
# gitlab.com organizations to allow git sources for
|
||||
gitlab = []
|
||||
# bitbucket.org organizations to allow git sources for
|
||||
bitbucket = []
|
26
docker/Dockerfile.ci-lint-audit
Normal file
26
docker/Dockerfile.ci-lint-audit
Normal file
@@ -0,0 +1,26 @@
|
||||
FROM rust:1.88 AS builder
|
||||
|
||||
RUN apt update \
|
||||
&& apt install -y --no-install-recommends libclang-dev hunspell \
|
||||
&& apt clean
|
||||
|
||||
RUN rustup default nightly \
|
||||
&& rustup component add rustfmt clippy
|
||||
|
||||
RUN cargo install cargo-binstall
|
||||
|
||||
RUN cargo binstall cargo-sort-derives cargo-spellcheck cargo-udeps cargo-deny
|
||||
|
||||
|
||||
FROM debian:trixie-slim
|
||||
|
||||
RUN apt update \
|
||||
&& apt install -y --no-install-recommends ca-certificates git rustup build-essential \
|
||||
libssl-dev pkg-config libglib2.0-0 libpango-1.0-0 libatk1.0-dev libgdk-pixbuf-2.0-dev \
|
||||
libcairo2-dev libgtk-3-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev \
|
||||
&& apt clean
|
||||
|
||||
COPY --from=builder /usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/ /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/
|
||||
COPY --from=builder /usr/local/cargo/bin /root/.cargo/bin/
|
||||
|
||||
RUN rustup default nightly
|
@@ -1,207 +0,0 @@
|
||||
|
||||
@font-face {
|
||||
src: url("../fonts/Geist/Geist-Medium.woff2") format("woff2");
|
||||
font-family: "Geist";
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
src: url("../fonts/Geist/Geist-Bold.woff2") format("woff2");
|
||||
font-family: "Geist";
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
|
||||
font-family: "Geist";
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#main {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@keyframes multicolor {
|
||||
0% { fill: #1DB2CF; /* color-primary-100 */ }
|
||||
33% { fill: #7E6BB6; /* color-secondary-100 */ }
|
||||
66% { fill: #D53583; /* color-ternary-100 */ }
|
||||
}
|
||||
|
||||
:root {
|
||||
--wallpaper-pattern-height: 128px;
|
||||
--spinner-height: 5%;
|
||||
--window-center-pos: calc(50% + (var(--wallpaper-pattern-height) / 2) - (var(--spinner-height) / 2));
|
||||
}
|
||||
|
||||
/* @media (0px < height <= calc(var(--wallpaper-pattern-height) * 5)) { */
|
||||
@media (min-height: 0px) and (max-height: 640px) {
|
||||
:root {
|
||||
--spinner-top: var(--window-center-pos);
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 5) < height <= calc($wallpaper-pattern-height * 6)) { */
|
||||
@media (min-height: 641px) and (max-height: 768px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 2));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 6) < height <= calc($wallpaper-pattern-height * 8)) { */
|
||||
@media (min-height: 769px) and (max-height: 1024px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 2));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 8) < height <= calc($wallpaper-pattern-height * 10)) { */
|
||||
@media (min-height: 1025px) and (max-height: 1280px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 3));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 10) < height <= calc($wallpaper-pattern-height * 12)) { */
|
||||
@media (min-height: 1281px) and (max-height: 1536px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 4));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 12) < height <= calc($wallpaper-pattern-height * 14)) { */
|
||||
@media (min-height: 1537px) and (max-height: 1792px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 5));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 14) < height <= calc($wallpaper-pattern-height * 16)) { */
|
||||
@media (min-height: 1793px) and (max-height: 2048px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 6));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 16) < height <= calc($wallpaper-pattern-height * 18)) { */
|
||||
@media (min-height: 2049px) and (max-height: 2304px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 7));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 18) < height <= calc($wallpaper-pattern-height * 20)) { */
|
||||
@media (min-height: 2305px) and (max-height: 2560px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 8));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 20) < height <= calc($wallpaper-pattern-height * 22)) { */
|
||||
@media (min-height: 2561px) and (max-height: 2816px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 9));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 22) < height <= calc($wallpaper-pattern-height * 24)) { */
|
||||
@media (min-height: 2817px) and (max-height: 3072px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 10));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 24) < height <= calc($wallpaper-pattern-height * 26)) { */
|
||||
@media (min-height: 3073px) and (max-height: 3328px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 11));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 26) < height <= calc($wallpaper-pattern-height * 28)) { */
|
||||
@media (min-height: 3329px) and (max-height: 3584px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 12));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 28) < height <= calc($wallpaper-pattern-height * 30)) { */
|
||||
@media (min-height: 3585px) and (max-height: 3840px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 13));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 30) < height <= calc($wallpaper-pattern-height * 32)) { */
|
||||
@media (min-height: 3841px) and (max-height: 4096px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 14));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 32) < height <= calc($wallpaper-pattern-height * 34)) { */
|
||||
@media (min-height: 4097px) and (max-height: 4352px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 15));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 34) < height <= calc($wallpaper-pattern-height * 36)) { */
|
||||
@media (min-height: 4353px) and (max-height: 4608px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 16));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 36) < height <= calc($wallpaper-pattern-height * 38)) { */
|
||||
@media (min-height: 4609px) and (max-height: 4864px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 17));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 38) < height <= calc($wallpaper-pattern-height * 40)) { */
|
||||
@media (min-height: 4865px) and (max-height: 5120px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 18));
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.wallpaper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: -1;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
.content {
|
||||
background-image: url("../images/wallpaper-pattern.svg");
|
||||
background-position: center;
|
||||
|
||||
width: 150%;
|
||||
height: 150%;
|
||||
}
|
||||
}
|
||||
|
||||
.spinner {
|
||||
height: var(--spinner-height);
|
||||
aspect-ratio: 2;
|
||||
|
||||
position: absolute;
|
||||
|
||||
top: var(--spinner-top);
|
||||
|
||||
svg {
|
||||
--fps: 4;
|
||||
--duration_sec: 3;
|
||||
--steps: calc(var(--duration_sec) * var(--fps));
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
fill: #1DB2CF; /* color-primary-100 */
|
||||
stroke: #1B1B1B; /* greyscale-90 */
|
||||
|
||||
animation: 3s multicolor linear infinite;
|
||||
animation-timing-function: steps(var(--steps), end);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,15 +1,207 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Hack to avoid the addition of the script part by dioxus-cli -->
|
||||
<!-- <title>{base_path}</title> -->
|
||||
<!-- <title>{app_name}</title> -->
|
||||
|
||||
<title></title>
|
||||
<title>{app_name}</title>
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="UTF-8" />
|
||||
{style_include}
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
|
||||
font-family: "Geist";
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#main {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@keyframes multicolor {
|
||||
0% { fill: #1DB2CF; /* color-primary-100 */ }
|
||||
33% { fill: #7E6BB6; /* color-secondary-100 */ }
|
||||
66% { fill: #D53583; /* color-ternary-100 */ }
|
||||
}
|
||||
|
||||
:root {
|
||||
--wallpaper-pattern-height: 128px;
|
||||
--spinner-height: 5%;
|
||||
--window-center-pos: calc(50% + (var(--wallpaper-pattern-height) / 2) - (var(--spinner-height) / 2));
|
||||
}
|
||||
|
||||
/* @media (0px < height <= calc(var(--wallpaper-pattern-height) * 5)) { */
|
||||
@media (min-height: 0px) and (max-height: 640px) {
|
||||
:root {
|
||||
--spinner-top: var(--window-center-pos);
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 5) < height <= calc($wallpaper-pattern-height * 6)) { */
|
||||
@media (min-height: 641px) and (max-height: 768px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 2));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 6) < height <= calc($wallpaper-pattern-height * 8)) { */
|
||||
@media (min-height: 769px) and (max-height: 1024px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 2));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 8) < height <= calc($wallpaper-pattern-height * 10)) { */
|
||||
@media (min-height: 1025px) and (max-height: 1280px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 3));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 10) < height <= calc($wallpaper-pattern-height * 12)) { */
|
||||
@media (min-height: 1281px) and (max-height: 1536px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 4));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 12) < height <= calc($wallpaper-pattern-height * 14)) { */
|
||||
@media (min-height: 1537px) and (max-height: 1792px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 5));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 14) < height <= calc($wallpaper-pattern-height * 16)) { */
|
||||
@media (min-height: 1793px) and (max-height: 2048px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 6));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 16) < height <= calc($wallpaper-pattern-height * 18)) { */
|
||||
@media (min-height: 2049px) and (max-height: 2304px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 7));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 18) < height <= calc($wallpaper-pattern-height * 20)) { */
|
||||
@media (min-height: 2305px) and (max-height: 2560px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 8));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 20) < height <= calc($wallpaper-pattern-height * 22)) { */
|
||||
@media (min-height: 2561px) and (max-height: 2816px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 9));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 22) < height <= calc($wallpaper-pattern-height * 24)) { */
|
||||
@media (min-height: 2817px) and (max-height: 3072px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 10));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 24) < height <= calc($wallpaper-pattern-height * 26)) { */
|
||||
@media (min-height: 3073px) and (max-height: 3328px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 11));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 26) < height <= calc($wallpaper-pattern-height * 28)) { */
|
||||
@media (min-height: 3329px) and (max-height: 3584px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 12));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 28) < height <= calc($wallpaper-pattern-height * 30)) { */
|
||||
@media (min-height: 3585px) and (max-height: 3840px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 13));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 30) < height <= calc($wallpaper-pattern-height * 32)) { */
|
||||
@media (min-height: 3841px) and (max-height: 4096px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 14));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 32) < height <= calc($wallpaper-pattern-height * 34)) { */
|
||||
@media (min-height: 4097px) and (max-height: 4352px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 15));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 34) < height <= calc($wallpaper-pattern-height * 36)) { */
|
||||
@media (min-height: 4353px) and (max-height: 4608px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 16));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 36) < height <= calc($wallpaper-pattern-height * 38)) { */
|
||||
@media (min-height: 4609px) and (max-height: 4864px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 17));
|
||||
}
|
||||
}
|
||||
/* @media (calc($wallpaper-pattern-height * 38) < height <= calc($wallpaper-pattern-height * 40)) { */
|
||||
@media (min-height: 4865px) and (max-height: 5120px) {
|
||||
:root {
|
||||
--spinner-top: calc(var(--window-center-pos) + (var(--wallpaper-pattern-height) * 18));
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.wallpaper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: -1;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
.content {
|
||||
background-image: url("data:image/svg+xml, <svg xmlns='http://www.w3.org/2000/svg' height='128' width='384' viewBox='0 0 384 128'><pattern id='p' width='384' height='128' patternUnits='userSpaceOnUse' stroke='%231B1B1B' stroke-linejoin='round' stroke-width='4'><path fill='%231DB2CF' d='M 9.736 -15 L -30 3.337 l 23.642 -0.088 L -10.212 15 L 30 -3.425 H 6.834 L 9.736 -15 Z'/><path fill='%23D53583' d='M 201.736 -15 L 162 3.337 l 23.642 -0.088 L 181.788 15 L 222 -3.425 H 198.834 L 201.736 -15 Z'/><path fill='%231DB2CF' d='M 393.736 -15 L 354 3.337 l 23.642 -0.088 L 373.788 15 L 414 -3.425 H 390.834 L 393.736 -15 Z'/><path fill='%237E6BB6' d='M 105.736 50 L 66 68.337 l 23.642 -0.088 L 85.788 80 L 126 61.575 H 102.834 L 105.736 50 Z'/><path fill='%237E6BB6' d='M 297.736 50 L 258 68.337 l 23.642 -0.088 L 277.788 80 L 318 61.575 H 294.834 L 297.736 50 Z'/><path fill='%231DB2CF' d='M 9.736 113 L -30 131.337 l 23.642 -0.088 L -10.212 143 L 30 124.575 H 6.834 L 9.736 113 Z'/><path fill='%23D53583' d='M 201.736 113 L 162 131.337 l 23.642 -0.088 L 181.788 143 L 222 124.575 H 198.834 L 201.736 113 Z'/><path fill='%231DB2CF' d='M 393.736 113 L 354 131.337 l 23.642 -0.088 L 373.788 143 L 414 124.575 H 390.834 L 393.736 113 Z'/></pattern><rect fill='url(%23p)' width='100%' height='100%'/></svg>");
|
||||
background-position: center;
|
||||
backgrond-size: var(--wallpaper-pattern-height);
|
||||
|
||||
width: 150%;
|
||||
height: 150%;
|
||||
}
|
||||
}
|
||||
|
||||
.spinner {
|
||||
height: var(--spinner-height);
|
||||
aspect-ratio: 2;
|
||||
|
||||
position: absolute;
|
||||
|
||||
top: var(--spinner-top);
|
||||
|
||||
svg {
|
||||
--fps: 4;
|
||||
--duration_sec: 3;
|
||||
--steps: calc(var(--duration_sec) * var(--fps));
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
fill: #1DB2CF; /* color-primary-100 */
|
||||
stroke: #1B1B1B; /* greyscale-90 */
|
||||
|
||||
animation: 3s multicolor linear infinite;
|
||||
animation-timing-function: steps(var(--steps), end);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
@@ -18,7 +210,7 @@
|
||||
<div class="content"></div>
|
||||
</div>
|
||||
<div class="spinner">
|
||||
<svg viewBox="0 0 184 94" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width='184' height='94' viewBox="0 0 184 94">
|
||||
<path
|
||||
stroke-linejoin="round"
|
||||
stroke-width="6"
|
||||
@@ -28,25 +220,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" async>
|
||||
import init from "{base_path}/assets/dioxus/beau-gosse-du-92.js";
|
||||
|
||||
// Ensure that everything needed to render preloader has been downloaded
|
||||
// before fetching the wasm bundle.
|
||||
window.onload=function() {
|
||||
init("{base_path}/assets/dioxus/beau-gosse-du-92_bg.wasm").then(
|
||||
wasm => {
|
||||
const preloader = document.getElementById("preloader");
|
||||
if (preloader !== undefined) {
|
||||
preloader.style.display = 'none';
|
||||
}
|
||||
|
||||
if (wasm.__wbindgen_start == undefined) {
|
||||
wasm.main();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
3
renovate.json
Normal file
3
renovate.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
||||
}
|
6
spellcheck.dic
Normal file
6
spellcheck.dic
Normal file
@@ -0,0 +1,6 @@
|
||||
5
|
||||
Dioxus
|
||||
MSN
|
||||
renderers
|
||||
SDK
|
||||
TODO
|
10
spellcheck.toml
Normal file
10
spellcheck.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
# Also take into account developer comments
|
||||
dev_comments = false
|
||||
|
||||
# Skip the README.md file as defined in the cargo manifest
|
||||
skip_readme = false
|
||||
|
||||
[Hunspell]
|
||||
lang = "en_US"
|
||||
search_dirs = [ "." ]
|
||||
extra_dictionaries = [ "./spellcheck.dic" ]
|
@@ -21,7 +21,7 @@ use crate::infrastructure::services::mozaik_builder::create_mozaik;
|
||||
|
||||
pub type RoomId = OwnedRoomId;
|
||||
|
||||
#[derive(PartialEq, Clone)]
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Invitation {
|
||||
invitee_id: UserId,
|
||||
sender_id: UserId,
|
||||
|
@@ -39,6 +39,7 @@ pub trait RoomStoreConsumerInterface {
|
||||
pub trait RoomStoreProviderInterface {
|
||||
fn on_new_name(&self, name: Option<String>);
|
||||
fn on_new_avatar(&self, avatar: Option<Avatar>);
|
||||
#[allow(dead_code)]
|
||||
fn on_new_topic(&self, topic: Option<String>);
|
||||
fn on_new_member(&self, member: RoomMember);
|
||||
fn on_invitation(&self, invitation: Invitation);
|
||||
|
@@ -43,7 +43,7 @@ use super::{
|
||||
};
|
||||
use crate::utils::oneshot;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ClientError {
|
||||
#[error("Matrix client error: {0}")]
|
||||
Matrix(#[from] matrix_sdk::Error),
|
||||
|
@@ -3,7 +3,7 @@ use std::future::Future;
|
||||
use std::sync::OnceLock;
|
||||
use std::{collections::HashMap, future::IntoFuture};
|
||||
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
use rand::distr::{Alphanumeric, SampleString};
|
||||
use reqwest::Result as RequestResult;
|
||||
use tracing::error;
|
||||
|
||||
@@ -15,7 +15,7 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash)]
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub enum AvatarFeeling {
|
||||
Ok,
|
||||
Warning,
|
||||
@@ -124,7 +124,7 @@ async fn fetch_dicebear_svg(
|
||||
// TODO: Use configuration file
|
||||
let url = "dicebear.tools.adrien.run";
|
||||
|
||||
let seed = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
|
||||
let seed = Alphanumeric.sample_string(&mut rand::rng(), 16);
|
||||
let type_str = r#type.to_string();
|
||||
let url = format!(
|
||||
"https://{url}/8.x/{type_str}/svg?seed={seed}&randomizeIds=true{}{}",
|
||||
|
20
src/main.rs
20
src/main.rs
@@ -10,6 +10,7 @@ mod utils;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use dioxus::document::{Link, Style};
|
||||
use dioxus::prelude::*;
|
||||
use futures_util::stream::StreamExt;
|
||||
use tracing::{debug, error, warn};
|
||||
@@ -89,13 +90,24 @@ async fn login(mut rx: UnboundedReceiver<bool>, session: &GlobalSignal<Session>)
|
||||
fn app() -> Element {
|
||||
let login_coro = use_coroutine(|rx| login(rx, &SESSION));
|
||||
|
||||
if !SESSION.read().is_logged {
|
||||
let is_logged = SESSION.read().is_logged;
|
||||
|
||||
if !is_logged {
|
||||
login_coro.send(false);
|
||||
rsx! {
|
||||
}
|
||||
|
||||
rsx! {
|
||||
Link {
|
||||
href: asset!("public/fonts/Geist/Geist-Medium.woff2"), as: "font", type: "font/woff2"
|
||||
}
|
||||
Style {
|
||||
id: "style-head", "body {{ font-family: 'Geist'; font-weight: normal; }}"
|
||||
}
|
||||
|
||||
if !is_logged {
|
||||
Login {}
|
||||
}
|
||||
} else {
|
||||
rsx! {
|
||||
else {
|
||||
Conversations {}
|
||||
}
|
||||
}
|
||||
|
@@ -181,18 +181,14 @@ $border-thin: solid $border-thin-width $border-default-color;
|
||||
// TODO: Radius should be a percentage(eg: 1024/16px).
|
||||
$border-radius: 16px;
|
||||
|
||||
$geist-font-path: "../fonts/Geist";
|
||||
|
||||
$transition-duration: 300ms;
|
||||
|
||||
@font-face {
|
||||
src: url("#{$geist-font-path}/Geist-Medium.woff2") format("woff2");
|
||||
font-family: "Geist";
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
src: url("#{$geist-font-path}/Geist-Bold.woff2") format("woff2");
|
||||
font-family: "Geist";
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -218,6 +214,11 @@ input {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
// Hide the preloader as soon as the application is loaded and ready to be rendered
|
||||
#preloader {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#main {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
@@ -3,7 +3,7 @@ use dioxus_free_icons::{Icon, IconShape};
|
||||
|
||||
turf::style_sheet!("src/ui/components/button.scss");
|
||||
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
#[derive(Clone, PartialEq, Props)]
|
||||
struct _ButtonProps {
|
||||
children: Element,
|
||||
#[props(default = false)]
|
||||
@@ -15,7 +15,7 @@ struct _ButtonProps {
|
||||
|
||||
macro_rules! svg_text_icon {
|
||||
($name:ident,$text:literal) => {
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
struct $name;
|
||||
impl IconShape for $name {
|
||||
fn view_box(&self) -> &str {
|
||||
@@ -67,7 +67,7 @@ macro_rules! svg_text_button {
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
#[derive(Clone, PartialEq, Props)]
|
||||
pub struct ButtonProps {
|
||||
#[props(default = false)]
|
||||
focus: bool,
|
||||
|
@@ -5,7 +5,7 @@ turf::style_sheet!("src/ui/components/chat_panel.scss");
|
||||
#[component]
|
||||
pub fn ChatPanel(name: String) -> Element {
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
div {
|
||||
class: ClassName::CHAT_PANEL,
|
||||
|
@@ -237,12 +237,16 @@ pub fn ConversationAvatar(
|
||||
let on_press = {
|
||||
let room_id = room_id.clone();
|
||||
move || {
|
||||
on_selected.map(|c| c.call(room_id.as_ref().clone()));
|
||||
if let Some(c) = on_selected {
|
||||
c.call(room_id.as_ref().clone())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let on_long_press = move || {
|
||||
on_pressed.map(|c| c.call(room_id.as_ref().clone()));
|
||||
if let Some(c) = on_pressed {
|
||||
c.call(room_id.as_ref().clone())
|
||||
}
|
||||
};
|
||||
|
||||
let long_press_hook = use_long_press(long_press_duration, on_press, on_long_press);
|
||||
|
@@ -87,7 +87,7 @@ const _PYRAMID_VIEWBOX_HEIGHT: i64 = (_PYRAMID_CENTRAL_EDGE_E2_Y + _PYRAMID_STRO
|
||||
const _PYRAMID_VIEWBOX_WIDTH: i64 = (_PYRAMID_RIGHT_EDGE_E2_X + _PYRAMID_STROKE_WIDTH) as i64;
|
||||
const _PYRAMID_VIEWBOX: &str = formatcp!("0 0 {_PYRAMID_VIEWBOX_WIDTH} {_PYRAMID_VIEWBOX_HEIGHT}");
|
||||
|
||||
#[derive(PartialEq, Clone)]
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct PyramidShape {
|
||||
color: String,
|
||||
ratio: f64,
|
||||
@@ -154,7 +154,7 @@ impl IconShape for PyramidShape {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
#[derive(Clone, PartialEq, Props)]
|
||||
pub struct PyramidProps {
|
||||
color: Option<String>,
|
||||
#[props(default = 0.5)]
|
||||
|
@@ -4,7 +4,7 @@ use const_format::formatcp;
|
||||
use dioxus::prelude::*;
|
||||
use tracing::{debug, error, warn};
|
||||
use validator::{Validate, ValidateArgs, ValidateEmail, ValidationError, ValidationErrors};
|
||||
use zxcvbn::zxcvbn;
|
||||
use zxcvbn::{zxcvbn, Score};
|
||||
|
||||
use crate::{
|
||||
domain::model::session::Session,
|
||||
@@ -348,14 +348,14 @@ fn validate_id(id: &Option<String>, process: &Process) -> Result<(), ValidationE
|
||||
}
|
||||
|
||||
struct PasswordValidationResult {
|
||||
score: u8,
|
||||
score: Score,
|
||||
rating: f64, // 0 <= rating <= 1
|
||||
suggestions: Vec<String>,
|
||||
}
|
||||
impl PasswordValidationResult {
|
||||
pub fn new() -> Self {
|
||||
PasswordValidationResult {
|
||||
score: 0,
|
||||
score: Score::Zero,
|
||||
rating: 0.0,
|
||||
suggestions: Vec::<String>::new(),
|
||||
}
|
||||
@@ -366,9 +366,7 @@ fn compute_password_score(
|
||||
password: &str,
|
||||
with_suggestions: Option<bool>,
|
||||
) -> Option<PasswordValidationResult> {
|
||||
let Ok(estimate) = zxcvbn(password, &[]) else {
|
||||
return None;
|
||||
};
|
||||
let estimate = zxcvbn(password, &[]);
|
||||
|
||||
let mut result = PasswordValidationResult::new();
|
||||
result.score = estimate.score();
|
||||
@@ -396,7 +394,7 @@ fn validate_password(password: &Option<String>, process: &Process) -> Result<(),
|
||||
if let Some(password) = password {
|
||||
if let Some(result) = compute_password_score(password, Some(true)) {
|
||||
// TODO: To configuration?
|
||||
if result.score <= 2 {
|
||||
if [Score::Zero, Score::One, Score::Two].contains(&result.score) {
|
||||
let mut err = ValidationError::new(TOO_WEAK_PASSWORD_ERROR_NAME);
|
||||
err.add_param(Cow::from("score"), &result.score);
|
||||
err.add_param(Cow::from("rating"), &result.rating);
|
||||
|
@@ -15,7 +15,7 @@ use style::{COLOR_CRITICAL_100, COLOR_SUCCESS_100, COLOR_WARNING_100};
|
||||
|
||||
turf::style_sheet!("src/ui/components/modal.scss");
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub enum Severity {
|
||||
Ok,
|
||||
Warning,
|
||||
@@ -42,7 +42,7 @@ fn avatar_configs() -> &'static HashMap<Severity, AvatarConfig<'static>> {
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Props, Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, Props)]
|
||||
pub struct ModalProps {
|
||||
pub severity: Severity,
|
||||
#[props(optional)]
|
||||
|
@@ -5,7 +5,7 @@ use crate::ui::components::icons::LogoShape;
|
||||
|
||||
turf::style_sheet!("src/ui/components/spinner.scss");
|
||||
|
||||
#[derive(PartialEq, Clone, Props)]
|
||||
#[derive(Clone, PartialEq, Props)]
|
||||
pub struct SpinnerProps {
|
||||
#[props(default = true)]
|
||||
animate: bool,
|
||||
|
@@ -9,7 +9,7 @@ turf::style_sheet!("src/ui/components/text_input.scss");
|
||||
|
||||
pub trait InputPropsData {}
|
||||
|
||||
#[derive(Props, Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, Props)]
|
||||
pub struct InputProps<D: InputPropsData + 'static + std::cmp::PartialEq + std::clone::Clone> {
|
||||
value: Option<String>,
|
||||
placeholder: Option<String>,
|
||||
@@ -97,7 +97,7 @@ pub fn TextInput(props: InputProps<TextInputState>) -> Element {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Props, Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, Props)]
|
||||
pub struct PasswordInputState {
|
||||
text_input_state: TextInputState,
|
||||
#[props(default = 0.0)]
|
||||
|
@@ -7,10 +7,8 @@ turf::style_sheet!("src/ui/components/wallpaper.scss");
|
||||
|
||||
#[component]
|
||||
pub fn Wallpaper(display_version: Option<bool>) -> Element {
|
||||
let background_image = format!(
|
||||
"url({})",
|
||||
manganis::mg!(file("public/images/wallpaper-pattern.svg"))
|
||||
);
|
||||
let background_image_asset = asset!("/public/images/wallpaper-pattern.svg");
|
||||
let background_image = format!("url({})", background_image_asset.to_string());
|
||||
|
||||
let version = display_version.map(|flag| if flag { Some(GIT_VERSION) } else { None });
|
||||
|
||||
|
Reference in New Issue
Block a user