Compare commits

..

No commits in common. "f7a8069859098e04993cfba8c784f90436dd1288" and "da48f005a3c9d11f3df87855fa0916f5421c8f20" have entirely different histories.

25 changed files with 417 additions and 579 deletions

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,6 @@
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"format": "prettier --config .prettierrc '**/*.ts' '**/*.tsx' '**/*.js' '**/*.json' --write",
"fmt": "prettier --config .prettierrc 'src/**/*.ts' 'src/**/*.tsx' --write && npx eslint --fix 'src/**/*.ts' 'src/**/*.tsx'"
},
"dependencies": {
@ -35,4 +34,4 @@
"vite-plugin-qrcode": "^0.2.2",
"vite-plugin-solid": "^2.7.2"
}
}
}

View file

@ -3,4 +3,4 @@ export default {
tailwindcss: {},
autoprefixer: {},
},
};
}

View file

@ -17,7 +17,7 @@ export function Footer(): JSXElement {
viewBox="0 0 24 24"
class="fill-current"
>
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z" />
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"></path>
</svg>
</a>
<a>
@ -28,7 +28,7 @@ export function Footer(): JSXElement {
viewBox="0 0 24 24"
class="fill-current"
>
<path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z" />
<path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"></path>
</svg>
</a>
<a>
@ -39,7 +39,7 @@ export function Footer(): JSXElement {
viewBox="0 0 24 24"
class="fill-current"
>
<path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z" />
<path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"></path>
</svg>
</a>
</div>

View file

@ -47,7 +47,7 @@ export function GlobalStateProvider(props: {
return token() != "" && username() != "";
}
function logIn(username: string, token: string): void {
function logIn (username: string, token: string): void {
setUsername(username);
setToken(token);
localStorage.setItem("token", token);
@ -63,19 +63,9 @@ export function GlobalStateProvider(props: {
return (
<>
<ModalContext.Provider
value={{ isOpen: loginModalOpen, setOpen: setLoginModalOpen }}
>
<ModalContext.Provider value={{ isOpen: loginModalOpen, setOpen: setLoginModalOpen }}>
<LoginContext.Provider
value={{
token,
setToken,
username,
setUsername,
loggedIn,
logOut,
logIn,
}}
value={{ token, setToken, username, setUsername, loggedIn, logOut, logIn }}
>
{props.children}
</LoginContext.Provider>

View file

@ -1,7 +1,7 @@
import { JSXElement, Show, useContext } from "solid-js";
import { LoginContext, ModalContext } from "../Context/GlobalState";
import { UserCircle } from "../Util/Icons";
import { LoginContext, ModalContext } from "./GlobalState";
import { UserCircle } from "./Icons";
export function LoginButton(): JSXElement {
const modal_ctx = useContext(ModalContext)!;

View file

@ -1,8 +1,8 @@
import { JSXElement, Show, onCleanup, useContext } from "solid-js";
import { LoginForm } from "../Components/Login";
import { RegisterForm } from "../Components/Register";
import { ModalContext } from "../Context/GlobalState";
import { ModalContext } from "./GlobalState";
import { LoginForm } from "./RegLogin/Login";
import { RegisterForm } from "./RegLogin/Register";
export function LoginModal(): JSXElement {
const modal_ctx = useContext(ModalContext)!;

View file

@ -1,8 +1,8 @@
import { A } from "@solidjs/router";
import { JSXElement, Show, useContext } from "solid-js";
import { LoginContext } from "../Context/GlobalState";
import { Home, Plus } from "../Util/Icons";
import { LoginContext } from "./GlobalState";
import { Home, Plus } from "./Icons";
// Represents a single list item in the menu bar
export function MenuItem(props: {

View file

@ -1,9 +1,9 @@
import { A } from "@solidjs/router";
import { JSXElement } from "solid-js";
import { LoginButton } from "../Components/LoginButton";
import { Menu } from "../Components/Menu";
import { Flake } from "../Util/Icons";
import { Flake } from "./Icons";
import { LoginButton } from "./LoginButton";
import { Menu } from "./Menu";
export function Navbar(): JSXElement {
return (

View file

@ -1,8 +1,8 @@
import { useNavigate } from "@solidjs/router";
import { JSXElement, Show, createSignal, onMount, useContext } from "solid-js";
import { LoginContext } from "../Context/GlobalState";
import { NewPost, createPost } from "../Util/api";
import { LoginContext } from "./GlobalState";
import { NewPost, createPost } from "./api";
export function NewPostInputArea(): JSXElement {
const [content, setContent] = createSignal("");

View file

@ -1,8 +1,8 @@
import { useNavigate } from "@solidjs/router";
import { For, JSXElement, Show, createSignal } from "solid-js";
import { Arrow, loadSpinner } from "../Util/Icons";
import { Post, getPosts } from "../Util/api";
import { Arrow, loadSpinner } from "./Icons";
import { Post, getPosts } from "./api";
export function Posts(): JSXElement {
const [posts, setPosts] = createSignal([] as Post[]);

View file

@ -1,9 +1,9 @@
import { Route, Routes } from "@solidjs/router";
import { JSXElement } from "solid-js";
import { NewPostInputArea } from "../Components/NewPost";
import { Posts } from "../Components/Posts";
import { SinglePost } from "../Components/SinglePost";
import { NewPostInputArea } from "./NewPost";
import { Posts } from "./Posts";
import { SinglePost } from "./SinglePost";
// Primary is the section of the page that holds the main content
export function Primary(): JSXElement {

View file

@ -1,7 +1,7 @@
import { JSXElement, Show, createSignal, useContext } from "solid-js";
import { LoginContext, ModalContext } from "../Context/GlobalState";
import { AuthResponse, submitLogin } from "../Util/api";
import { LoginContext, ModalContext } from "../GlobalState";
import { AuthResponse, submitLogin } from "../api";
export function LoginForm(): JSXElement {
const modal_ctx = useContext(ModalContext)!;

View file

@ -1,7 +1,7 @@
import { JSXElement, Show, createSignal, useContext } from "solid-js";
import { LoginContext, ModalContext } from "../Context/GlobalState";
import { AuthResponse, submitRegistration } from "../Util/api";
import { LoginContext, ModalContext } from "../GlobalState";
import { AuthResponse, submitRegistration } from "../api";
export function RegisterForm(): JSXElement {
const modal_ctx = useContext(ModalContext)!;

View file

@ -1,10 +1,10 @@
import { JSXElement } from "solid-js";
import { GlobalStateProvider } from "../Context/GlobalState";
import { Footer } from "./Footer";
import { GlobalStateProvider } from "./GlobalState";
import { LoginModal } from "./LoginModal";
import { Navbar } from "./Navbar";
import { Primary } from "./Primary";
import { Footer } from "./Footer";
function Root(): JSXElement {
return (
@ -14,7 +14,7 @@ function Root(): JSXElement {
<div class="flex flex-col items-center">
<Navbar />
<LoginModal />
<div class="mb-8 flex min-h-[65vh] w-full flex-col items-center space-y-2 px-2 md:max-w-3xl">
<div class="flex w-full min-h-[65vh] flex-col items-center mb-8 space-y-2 px-2 md:max-w-3xl">
<Primary />
</div>
<Footer />

View file

@ -1,9 +1,9 @@
import { useParams } from "@solidjs/router";
import { JSXElement, Show, Suspense, createResource } from "solid-js";
import { loadSpinner } from "../Util/Icons";
import { getPost } from "../Util/api";
import { loadSpinner } from "./Icons";
import { PostSegment } from "./Posts";
import { getPost } from "./api";
export function SinglePost(): JSXElement {
const params = useParams();

View file

@ -72,4 +72,4 @@ export async function submitLogin(
});
if (response.ok) return await response.json();
}
}

View file

@ -1,7 +1,7 @@
import { Router } from "@solidjs/router";
import { render } from "solid-js/web";
import Root from "./Containers/Root";
import Root from "./Root";
import "./index.css";
const root = document.getElementById("root");

View file

@ -1,27 +1,32 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
daisyui: {
themes: [
{
mytheme: {
primary: "#64279e",
secondary: "#9454af",
accent: "#6ff7c5",
neutral: "#1f2329",
"primary": "#64279e",
"secondary": "#9454af",
"accent": "#6ff7c5",
"neutral": "#1f2329",
"base-100": "#2a3a47",
info: "#8b9be5",
success: "#79e2b4",
warning: "#efb261",
error: "#e1604c",
"info": "#8b9be5",
"success": "#79e2b4",
"warning": "#efb261",
"error": "#e1604c",
},
},
],
},
theme: {
extend: {},
},
// eslint-disable-next-line no-undef
plugins: [require("daisyui")],
};
}

View file

@ -3,7 +3,11 @@
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
@ -19,10 +23,12 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"include": [
"src"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}
}

View file

@ -1,6 +1,6 @@
import { defineConfig } from "vite";
import { qrcode } from "vite-plugin-qrcode";
import solid from "vite-plugin-solid";
import { defineConfig } from 'vite'
import solid from 'vite-plugin-solid'
import { qrcode } from 'vite-plugin-qrcode'
// https://vitejs.dev/config/
export default defineConfig({
@ -12,12 +12,12 @@ export default defineConfig({
port: 3000,
open: true,
proxy: {
"/api": {
target: "http://localhost:8080/api",
'/api': {
target: 'http://localhost:8080/api',
changeOrigin: true,
secure: false,
rewrite: (path): string => path.replace(/^\/api/, ""),
},
},
},
});
rewrite: (path): string => path.replace(/^\/api/, '')
}
}
}
})

View file

@ -32,7 +32,8 @@ build-container-release:
podman build -t fb-server -f container/Containerfile .
# Builds a release container and runs it
start-release: start-postgres-dev clean-podman init-sqlx build-container-release create-network
start-release: start-postgres-dev clean-podman init-sqlx build-container-release
podman network create {{network}} --ignore
podman run -d --network {{network}} -e {{env_string}} -p 8080:8080 --name frostbyte fb-server
# Initializes the database, runs migrations and then prepares sqlx
@ -44,14 +45,10 @@ init-sqlx:
# Starts a postgres container for development
[private]
start-postgres-dev: create-network
start-postgres-dev:
podman rm -f {{pg_container}}
podman run --network {{network}} --name {{pg_container}} -e POSTGRES_PASSWORD={{pg_pass}} -d -p {{pg_port}}:5432 docker.io/postgres:16.1-alpine
[private]
create-network:
podman network create {{network}} --ignore
# Forcefully stops and removes the frostbyte container
[private]
clean-podman:

View file

@ -84,14 +84,13 @@ pub struct CaptchaResponse {
}
/// Request a captcha from the captcha service
#[allow(unreachable_code, unused_variables)]
#[post("/captcha")]
pub async fn captcha_request(cstate: Data<CaptchaState>) -> Result<impl Responder> {
unimplemented!("Captcha is currently disabled");
return Ok(HttpResponse::InternalServerError().json("Error"));
// This might block the thread a bit too long
let (answer, svg) = get_captcha();
// let (answer, svg) = get_captcha();
// let id = rand_core::OsRng.next_u32() as i32;

View file

@ -1,4 +1,4 @@
use rand::Rng;
use rand::{Rng, RngCore};
// This will do for now
pub fn hex_string(length: usize) -> String {
@ -9,9 +9,11 @@ pub fn hex_string(length: usize) -> String {
}
mod tests {
use super::*;
#[test]
fn test_random_hex_string() {
let s = super::hex_string(16);
let s = hex_string(16);
assert_eq!(s.len(), 16);
}
}