mirror of
https://github.com/Vale54321/schafkop-neu.git
synced 2025-12-16 11:49:34 +01:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4a3b19f59 | |||
| 7f2fcd9ba0 | |||
| 4866a74f68 | |||
| 1b0cd8913b | |||
| 355e8754a8 | |||
| a13e4ed9bc | |||
| ce9fece708 | |||
| 60b6d57dd3 | |||
| c1344a3553 | |||
| 6efdc7a0d0 | |||
| 7da9b0484f | |||
| 4784a156a9 | |||
| 730b4c508b |
80
.github/workflows/deploy-pages.yml
vendored
Normal file
80
.github/workflows/deploy-pages.yml
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
name: Deploy WebAssembly to GitHub Pages
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- rust
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: pages
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build WebAssembly
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Rust
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
targets: wasm32-unknown-unknown
|
||||||
|
|
||||||
|
- name: Cache cargo registry and git
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('schafkopf-logic/Cargo.toml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-cargo-
|
||||||
|
|
||||||
|
- name: Cache trunk build artifacts
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/trunk/
|
||||||
|
schafkopf-logic/target/wasm-bindgen/
|
||||||
|
schafkopf-logic/target/wasm-opt/
|
||||||
|
schafkopf-logic/target/wasm32-unknown-unknown/
|
||||||
|
~/.cache/.wasm-pack/
|
||||||
|
~/.cache/wasm-pack/
|
||||||
|
key: ${{ runner.os }}-trunk-${{ hashFiles('schafkopf-logic/Cargo.toml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-trunk-
|
||||||
|
|
||||||
|
- name: Install trunk
|
||||||
|
run: cargo install trunk --locked --force
|
||||||
|
|
||||||
|
- name: Build with trunk
|
||||||
|
working-directory: schafkopf-logic
|
||||||
|
run: |
|
||||||
|
trunk build --release --public-url "/${{ github.event.repository.name }}/"
|
||||||
|
|
||||||
|
- name: Upload Pages artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
path: schafkopf-logic/dist
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy to GitHub Pages
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
steps:
|
||||||
|
- name: Deploy
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
4
schafkopf-logic/.gitignore
vendored
Normal file
4
schafkopf-logic/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
target
|
||||||
|
Cargo.lock
|
||||||
|
shell.nix
|
||||||
|
dist
|
||||||
11
schafkopf-logic/Cargo.toml
Normal file
11
schafkopf-logic/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "schafkopf-game"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
schafkopf-logic = "0.1.0"
|
||||||
|
bevy = { version = "0.17", features = ["png", "default_font"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
getrandom = { version = "0.3", features = ["wasm_js"] }
|
||||||
7
schafkopf-logic/Trunk.toml
Normal file
7
schafkopf-logic/Trunk.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[build]
|
||||||
|
dist = "dist"
|
||||||
|
release = true
|
||||||
|
|
||||||
|
[serve]
|
||||||
|
open = false
|
||||||
|
port = 8080
|
||||||
BIN
schafkopf-logic/assets/symbole.png
Normal file
BIN
schafkopf-logic/assets/symbole.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
33
schafkopf-logic/index.html
Normal file
33
schafkopf-logic/index.html
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Schafkopf Logic</title>
|
||||||
|
<link data-trunk rel="rust" href="Cargo.toml" />
|
||||||
|
|
||||||
|
<link data-trunk rel="copy-dir" href="assets" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
1146
schafkopf-logic/src/main.rs
Normal file
1146
schafkopf-logic/src/main.rs
Normal file
File diff suppressed because it is too large
Load Diff
2075
schafkopf-os/Cargo.lock
generated
2075
schafkopf-os/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -2,3 +2,12 @@
|
|||||||
name = "schafkopf-os"
|
name = "schafkopf-os"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
octocrab = { version = "0.47"}
|
||||||
|
axum = "0.8.6"
|
||||||
|
askama = "0.14.0"
|
||||||
|
tower-http = { version = "0.6", features = ["fs", "compression-full", "set-header"] }
|
||||||
|
tower = "0.5.2"
|
||||||
|
http = "1.3.1"
|
||||||
@@ -1,3 +1,134 @@
|
|||||||
fn main() {
|
use octocrab::{Octocrab, Result};
|
||||||
println!("Hello, world!");
|
|
||||||
|
use http::{header, HeaderValue};
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
routing::{get},
|
||||||
|
http::StatusCode,
|
||||||
|
Json, Router,
|
||||||
|
};
|
||||||
|
use axum::extract::Path;
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
use axum::response::Response;
|
||||||
|
use http::HeaderMap;
|
||||||
|
|
||||||
|
use tower_http::{
|
||||||
|
services::{ServeDir},
|
||||||
|
};
|
||||||
|
use tower_http::set_header::SetResponseHeaderLayer;
|
||||||
|
use tower::ServiceBuilder;
|
||||||
|
|
||||||
|
use askama::Template;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
let static_service = ServiceBuilder::new()
|
||||||
|
.layer(SetResponseHeaderLayer::if_not_present(
|
||||||
|
header::CACHE_CONTROL,
|
||||||
|
HeaderValue::from_static("no-cache, no-store, must-revalidate"),
|
||||||
|
))
|
||||||
|
.layer(SetResponseHeaderLayer::if_not_present(
|
||||||
|
header::PRAGMA,
|
||||||
|
HeaderValue::from_static("no-cache"),
|
||||||
|
))
|
||||||
|
.layer(SetResponseHeaderLayer::if_not_present(
|
||||||
|
header::EXPIRES,
|
||||||
|
HeaderValue::from_static("0"),
|
||||||
|
))
|
||||||
|
.service(ServeDir::new("static"));
|
||||||
|
|
||||||
|
// build our application with a route
|
||||||
|
let app: Router = Router::new()
|
||||||
|
.route("/api", get(root))
|
||||||
|
.route("/", get(index))
|
||||||
|
.route("/api/firmware/{tag}", get(download_firmware))
|
||||||
|
.nest_service("/static", static_service);
|
||||||
|
|
||||||
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn root() -> Result<Json<Vec<String>>, StatusCode> {
|
||||||
|
let gh = Octocrab::builder().build().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
|
|
||||||
|
let owner = "Vale54321";
|
||||||
|
let repo = "schafkop-neu";
|
||||||
|
|
||||||
|
let mut tags: Vec<String> = vec![];
|
||||||
|
|
||||||
|
let page = gh.repos(owner, repo).releases().list().per_page(100).send().await.map_err(|_| StatusCode::BAD_GATEWAY)?;
|
||||||
|
|
||||||
|
for release in &page.items {
|
||||||
|
tags.push(release.tag_name.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Json(tags))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn index() -> impl axum::response::IntoResponse {
|
||||||
|
let index = Index {
|
||||||
|
title: "Schafkopf OS",
|
||||||
|
message: "Welcome to Schafkopf OS!",
|
||||||
|
version: app_version(),
|
||||||
|
};
|
||||||
|
axum::response::Html(index.render().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn app_version() -> &'static str {
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "index.html")]
|
||||||
|
struct Index<'a> {
|
||||||
|
title: &'a str,
|
||||||
|
message: &'a str,
|
||||||
|
version: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn download_firmware(
|
||||||
|
Path(tag): Path<String>,
|
||||||
|
) -> std::result::Result<Response, StatusCode> {
|
||||||
|
let gh = Octocrab::builder()
|
||||||
|
.build()
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
|
|
||||||
|
let owner = "Vale54321";
|
||||||
|
let repo = "schafkop-neu";
|
||||||
|
|
||||||
|
// Get the release for the provided tag
|
||||||
|
let release = gh
|
||||||
|
.repos(owner, repo)
|
||||||
|
.releases()
|
||||||
|
.get_by_tag(&tag)
|
||||||
|
.await
|
||||||
|
.map_err(|_| StatusCode::BAD_GATEWAY)?;
|
||||||
|
|
||||||
|
// List assets for the release
|
||||||
|
let assets = gh
|
||||||
|
.repos(owner, repo)
|
||||||
|
.releases()
|
||||||
|
.assets(release.id.0)
|
||||||
|
.per_page(100)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|_| StatusCode::BAD_GATEWAY)?;
|
||||||
|
|
||||||
|
// Find the "firmware.uf2" asset
|
||||||
|
let Some(asset) = assets.items.into_iter().find(|a| a.name == "firmware.uf2") else {
|
||||||
|
return Err(StatusCode::NOT_FOUND);
|
||||||
|
};
|
||||||
|
|
||||||
|
let location = asset.browser_download_url.to_string();
|
||||||
|
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
header::LOCATION,
|
||||||
|
HeaderValue::from_str(&location).map_err(|_| StatusCode::BAD_GATEWAY)?,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 302 Found with Location header
|
||||||
|
let resp = (StatusCode::FOUND, headers).into_response();
|
||||||
|
Ok(resp)
|
||||||
|
}
|
||||||
@@ -1,22 +1,10 @@
|
|||||||
const btn = document.getElementById('pingBtn');
|
const btn = document.getElementById('pingBtn');
|
||||||
const versionBtn = document.getElementById('versionBtn');
|
|
||||||
const out = document.getElementById('result');
|
const out = document.getElementById('result');
|
||||||
|
|
||||||
btn?.addEventListener('click', async () => {
|
btn?.addEventListener('click', async () => {
|
||||||
out.textContent = 'Requesting /api/ping…';
|
out.textContent = 'Requesting /api/ping…';
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/api/ping');
|
const res = await fetch('/api');
|
||||||
const json = await res.json();
|
|
||||||
out.textContent = JSON.stringify(json, null, 2);
|
|
||||||
} catch (err) {
|
|
||||||
out.textContent = 'Error: ' + (err?.message || String(err));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
versionBtn?.addEventListener('click', async () => {
|
|
||||||
out.textContent = 'Requesting /api/version…';
|
|
||||||
try {
|
|
||||||
const res = await fetch('/api/version');
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
out.textContent = JSON.stringify(json, null, 2);
|
out.textContent = JSON.stringify(json, null, 2);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -10,12 +10,11 @@
|
|||||||
<main class="container">
|
<main class="container">
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
<p class="lead">{{ message }}</p>
|
<p class="lead">{{ message }}</p>
|
||||||
<p class="version">Version: {{ version }}</p>
|
<p class="version">Schafkopf OS Version: {{ version }}</p>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>API Test</h2>
|
<h2>API Test</h2>
|
||||||
<button id="pingBtn">Ping API</button>
|
<button id="pingBtn">Ping API</button>
|
||||||
<button id="versionBtn">Get Version</button>
|
|
||||||
<pre id="result">Waiting…</pre>
|
<pre id="result">Waiting…</pre>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
Reference in New Issue
Block a user