Initial commit

This commit is contained in:
Amanda Graven 2025-02-10 09:34:10 +01:00
commit 560f88949f
10 changed files with 5623 additions and 0 deletions

7
.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
/target
.DS_Store
# These are backup files generated by rustfmt
**/*.rs.bk

5157
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

30
Cargo.toml Normal file
View file

@ -0,0 +1,30 @@
[package]
name = "why5"
version = "0.1.0"
authors = ["Amanda Graven <amanda.graven@subaio.com>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { version = "0.6.0", features = [] }
getrandom = { version = "0.2" }
rand = "0.8"
[features]
default = ["web"]
web = ["dioxus/web", "getrandom/js"]
desktop = ["dioxus/desktop"]
mobile = ["dioxus/mobile"]
[profile]
[profile.wasm-dev]
inherits = "dev"
opt-level = 1
[profile.server-dev]
inherits = "dev"
[profile.android-dev]
inherits = "dev"

24
Dioxus.toml Normal file
View file

@ -0,0 +1,24 @@
[application]
# App (Project) Name
name = "why5"
[web.app]
# HTML title tag content
title = "why5"
# include `assets` in web platform
[web.resource]
# Additional CSS style files
style = []
# Additional JavaScript files
script = []
[web.resource.dev]
# Javascript code file
# serve: [dev-server] only
script = []

17
README.md Normal file
View file

@ -0,0 +1,17 @@
# Development
Your new bare-bones project includes minimal organization with a single `main.rs` file and a few assets.
### Serving Your App
Run the following command in the root of your project to start developing with the default platform:
```bash
dx serve
```
To run for a different platform, use the `--platform platform` flag. E.g.
```bash
dx serve --platform desktop
```

BIN
assets/favicon.ico Normal file

Binary file not shown.

After

Width: 256px  |  Height: 256px  |  Size: 130 KiB

116
assets/icon.svg Normal file
View file

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="64"
height="64"
viewBox="0 0 16.933333 16.933333"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="icon.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="false"
showguides="true"
inkscape:zoom="14.638496"
inkscape:cx="27.940029"
inkscape:cy="29.20382"
inkscape:window-width="2560"
inkscape:window-height="1371"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid4448" />
<sodipodi:guide
position="8.4666662,8.4666668"
orientation="1,0"
id="guide6706"
inkscape:locked="false" />
<sodipodi:guide
position="8.4666664,8.4666666"
orientation="0,-1"
id="guide6708"
inkscape:locked="false" />
<sodipodi:guide
position="5.0270834,11.90625"
orientation="0,-1"
id="guide6710"
inkscape:locked="false" />
<sodipodi:guide
position="5.0270834,11.90625"
orientation="1,0"
id="guide6712"
inkscape:locked="false" />
<sodipodi:guide
position="11.90625,11.90625"
orientation="1,0"
id="guide6714"
inkscape:locked="false" />
<sodipodi:guide
position="5.0270834,5.027083"
orientation="0,-1"
id="guide6716"
inkscape:locked="false" />
</sodipodi:namedview>
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5875;stroke-dasharray:none;stroke-opacity:1"
id="rect1877"
width="15.345833"
height="15.345833"
x="0.79374999"
y="0.79374999"
ry="3.175" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5875;stroke-dasharray:none;stroke-opacity:1"
id="path2394"
cx="5.0270834"
cy="5.0270834"
r="1.5875" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5875;stroke-dasharray:none;stroke-opacity:1"
id="path2394-3"
cx="5.0270834"
cy="11.90625"
r="1.5875" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5875;stroke-dasharray:none;stroke-opacity:1"
id="path2394-6"
cx="8.4666662"
cy="8.4666662"
r="1.5875" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5875;stroke-dasharray:none;stroke-opacity:1"
id="path2394-7"
cx="11.90625"
cy="11.90625"
r="1.5875" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5875;stroke-dasharray:none;stroke-opacity:1"
id="path2394-5"
cx="11.90625"
cy="5.0270834"
r="1.5875" />
</g>
</svg>

After

(image error) Size: 3.4 KiB

39
assets/main.css Normal file
View file

@ -0,0 +1,39 @@
/* App-wide styling */
body {
background-color: #efeffc;
color: #000000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 20px;
}
main {
margin: auto;
max-width: 40rem;
justify-content: center;
display: flex;
flex-direction: column;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
tr {
border: 1px solid gray;
}
td {
border: 1px solid gray;
text-align: center;
}
.number {
width: 1rem;
animation: 1s ease-in-out 1s backwards number-scale;
}
@keyframes number-scale {
from { font-size: xx-large; }
to { font-size: initial; }
}

149
assets/snow.css Normal file
View file

@ -0,0 +1,149 @@
/* https://pajasevi.github.io/CSSnowflakes/ */
.snowflake {
color: #fff;
font-size: 1em;
font-family: Arial, sans-serif;
text-shadow: 0 0 5px #000;
}
.snowflake,
.snowflake .inner {
animation-iteration-count: infinite;
animation-play-state: running
}
@keyframes snowflakes-fall {
0% {
transform: translateY(0)
}
100% {
transform: translateY(110vh)
}
}
@keyframes snowflakes-shake {
0%,
100% {
transform: translateX(0)
}
50% {
transform: translateX(80px)
}
}
.snowflake {
position: fixed;
top: -10%;
z-index: 9999;
-webkit-user-select: none;
user-select: none;
cursor: default;
animation-name: snowflakes-shake;
animation-duration: 3s;
animation-timing-function: ease-in-out
}
.snowflake .inner {
animation-duration: 10s;
animation-name: snowflakes-fall;
animation-timing-function: linear
}
.snowflake:nth-of-type(0) {
left: 1%;
animation-delay: 0s
}
.snowflake:nth-of-type(0) .inner {
animation-delay: 0s
}
.snowflake:first-of-type {
left: 10%;
animation-delay: 1s
}
.snowflake:first-of-type .inner,
.snowflake:nth-of-type(8) .inner {
animation-delay: 1s
}
.snowflake:nth-of-type(2) {
left: 20%;
animation-delay: .5s
}
.snowflake:nth-of-type(2) .inner,
.snowflake:nth-of-type(6) .inner {
animation-delay: 6s
}
.snowflake:nth-of-type(3) {
left: 30%;
animation-delay: 2s
}
.snowflake:nth-of-type(11) .inner,
.snowflake:nth-of-type(3) .inner {
animation-delay: 4s
}
.snowflake:nth-of-type(4) {
left: 40%;
animation-delay: 2s
}
.snowflake:nth-of-type(10) .inner,
.snowflake:nth-of-type(4) .inner {
animation-delay: 2s
}
.snowflake:nth-of-type(5) {
left: 50%;
animation-delay: 3s
}
.snowflake:nth-of-type(5) .inner {
animation-delay: 8s
}
.snowflake:nth-of-type(6) {
left: 60%;
animation-delay: 2s
}
.snowflake:nth-of-type(7) {
left: 70%;
animation-delay: 1s
}
.snowflake:nth-of-type(7) .inner {
animation-delay: 2.5s
}
.snowflake:nth-of-type(8) {
left: 80%;
animation-delay: 0s
}
.snowflake:nth-of-type(9) {
left: 90%;
animation-delay: 1.5s
}
.snowflake:nth-of-type(9) .inner {
animation-delay: 3s
}
.snowflake:nth-of-type(10) {
left: 25%;
animation-delay: 0s
}
.snowflake:nth-of-type(11) {
left: 65%;
animation-delay: 2.5s
}

84
src/main.rs Normal file
View file

@ -0,0 +1,84 @@
use dioxus::prelude::*;
use rand::Rng;
const FAVICON: Asset = asset!("/assets/icon.svg");
const MAIN_CSS: Asset = asset!("/assets/main.css");
const SNOW_CSS: Asset = asset!("/assets/snow.css");
#[derive(Clone, Debug, Default)]
struct State {
pub rows: Vec<Vec<u8>>,
}
impl State {
pub fn roll(&mut self) {
if self.rows.is_empty() {
self.rows.push(Vec::new());
}
let row = match self.rows.last_mut() {
Some(row) if row.len() > 1 && row.last().copied() == Some(5) => {
self.rows.push(Vec::new());
self.rows.last_mut().unwrap()
}
Some(row) => row,
None => unreachable!(),
};
row.push(rand::thread_rng().gen_range(1..=6));
}
}
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
let mut rows = use_signal(State::default);
let snow = true;
rsx! {
document::Link { rel: "icon", href: FAVICON }
document::Link { rel: "stylesheet", href: MAIN_CSS }
main {
table {
thead {
for _ in 0..20 {
th {}
}
}
tbody {
tr {
th { colspan: 100, "Game 1" }
}
for row in &rows().rows {
tr {
for number in &row {
td { class: "number", "{number}" }
}
}
}
}
}
button { onclick: move |_| rows.write().roll(), "Roll" }
}
if snow {
Snow {}
}
}
}
#[component]
fn Snow() -> Element {
rsx! {
div {
"aria-hidden": "true",
class: "snowflakes",
document::Stylesheet { href: SNOW_CSS }
for _ in 0..12 {
div {
class: "snowflake",
div { class: "inner", "" }
}
}
}
}
}