Compare commits

...

3 Commits

16 changed files with 2922 additions and 67 deletions

View File

@ -44,6 +44,7 @@
pkgs.sqlx-cli pkgs.sqlx-cli
pkgs.udev pkgs.udev
pkgs.wasm-pack pkgs.wasm-pack
pkgs.go-task
typeshare.packages."x86_64-linux".default typeshare.packages."x86_64-linux".default
pkgs.nodePackages_latest.typescript-language-server pkgs.nodePackages_latest.typescript-language-server
]; ];

View File

@ -30,7 +30,7 @@ impl Core {
Self(Arc::new(RwLock::new(AppState { Self(Arc::new(RwLock::new(AppState {
image_base: PathBuf::from("/home/savanni/Pictures"), image_base: PathBuf::from("/home/savanni/Pictures"),
tabletop: Tabletop { tabletop: Tabletop {
background_color: RGB{ red: 15, green: 0, blue: 0 }, background_color: RGB{ red: 0xca, green: 0xb9, blue: 0xbb },
background_image: None, background_image: None,
}, },
clients: HashMap::new(), clients: HashMap::new(),

View File

@ -139,7 +139,7 @@ pub async fn main() {
let core = core.clone(); let core = core.clone();
move |body| { move |body| {
println!("background_image: {}", body); println!("background_image: {}", body);
core.set_background_image(body); let _ = core.set_background_image(body);
warp::reply() warp::reply()
} }
}); });

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,8 @@
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"react-use-websocket": "^4.11.1", "react-use-websocket": "^4.11.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4",
"visions-types": "../visions-types"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",

View File

@ -1,10 +1,10 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import './App.css'; import './App.css';
import { TabletopElement } from './components/Tabletop/Tabletop';
import { Client } from './client'; import { Client } from './client';
import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { GmPlayingFieldComponent } from './components/GmPlayingField/GmPlayingField'; import { GmPlayingFieldComponent } from './components/GmPlayingField/GmPlayingField';
import { WebsocketProvider } from './components/WebsocketProvider'; import { WebsocketProvider } from './components/WebsocketProvider';
import { PlayerView } from './views/PlayerView/PlayerView';
interface AppProps { interface AppProps {
client: Client; client: Client;
@ -26,7 +26,7 @@ const App = ({ client }: AppProps) => {
}, },
{ {
path: "/", path: "/",
element: websocketUrl ? <WebsocketProvider websocketUrl={websocketUrl}> <TabletopElement client={client} /> </WebsocketProvider> : <div> </div> element: websocketUrl ? <WebsocketProvider websocketUrl={websocketUrl}> <PlayerView client={client} /> </WebsocketProvider> : <div> </div>
} }
]); ]);
return ( return (

View File

@ -1,9 +1,5 @@
.playing-field {
display: flex;
}
.playing-field__background { .playing-field__background {
max-width: 50%; flex-grow: 1;
} }
.playing-field__background > img { .playing-field__background > img {

View File

@ -1,23 +1,14 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import './Tabletop.css'; import './Tabletop.css';
import { WebsocketContext } from '../WebsocketProvider'; import { RGB } from 'visions-types';
import { Client } from '../../client';
interface TabletopElementProps { interface TabletopElementProps {
client: Client; backgroundColor: RGB;
backgroundUrl: URL | undefined;
} }
export const TabletopElement = ({ client }: TabletopElementProps) => { export const TabletopElement = ({ backgroundColor, backgroundUrl }: TabletopElementProps) => {
const { tabletop } = useContext(WebsocketContext); const tabletopColorStyle = `rgb(${backgroundColor.red}, ${backgroundColor.green}, ${backgroundColor.blue})`;
console.log("backgroundImage", tabletop.backgroundImage);
if (tabletop.backgroundImage) { return <div> {backgroundUrl && <img src={backgroundUrl.toString()} alt="playing field" />} </div>
return (<div className="playing-field">
<div className="playing-field__background"> {tabletop.backgroundImage && <img src={client.imageUrl(tabletop.backgroundImage).toString()} alt="playing field" />} </div>
</div>)
} else {
return (<div className="playing-field">
<div> </div>
</div>
);
}
} }

View File

@ -1,6 +1,6 @@
import React, { createContext, PropsWithChildren, useEffect, useReducer } from "react"; import React, { createContext, PropsWithChildren, useEffect, useReducer } from "react";
import useWebSocket from "react-use-websocket"; import useWebSocket from "react-use-websocket";
import { Message, Tabletop } from "visions"; import { Message, Tabletop } from "visions-types";
type TabletopState = { type TabletopState = {
tabletop: Tabletop; tabletop: Tabletop;

View File

@ -0,0 +1,18 @@
.player-view {
display: flex;
width: 100%;
}
.player-view__left-panel {
flex-grow: 0;
min-width: 100px;
max-width: 20%;
}
.player-view__right-panel {
flex-grow: 0;
min-width: 100px;
max-width: 20%;
}

View File

@ -0,0 +1,24 @@
import React, { useContext } from 'react';
import './PlayerView.css';
import { WebsocketContext } from '../../components/WebsocketProvider';
import { Client } from '../../client';
import { TabletopElement } from '../../components/Tabletop/Tabletop';
interface PlayerViewProps {
client: Client;
}
export const PlayerView = ({ client }: PlayerViewProps) => {
const { tabletop } = useContext(WebsocketContext);
const backgroundColor = tabletop.backgroundColor;
const tabletopColorStyle = `rgb(${backgroundColor.red}, ${backgroundColor.green}, ${backgroundColor.blue})`;
const backgroundUrl = tabletop.backgroundImage ? client.imageUrl(tabletop.backgroundImage) : undefined;
return (<div className="player-view" style={{ backgroundColor: tabletopColorStyle}}>
<div className="player-view__left-panel"> Left Side </div>
<TabletopElement backgroundColor={backgroundColor} backgroundUrl={backgroundUrl} />
<div className="player-view__right-panel"> Right Side </div>
</div>)
}

2
visions/visions-types/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
dist
visions.ts

View File

@ -0,0 +1,7 @@
version: '3'
tasks:
build:
cmds:
- typeshare --lang typescript --output-file visions.ts ../server/src
- npx tsc

28
visions/visions-types/package-lock.json generated Normal file
View File

@ -0,0 +1,28 @@
{
"name": "visions-types",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "visions-types",
"version": "0.0.1",
"license": "ISC",
"dependencies": {
"typescript": "^5.6.3"
}
},
"node_modules/typescript": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
}
}
}

View File

@ -0,0 +1,14 @@
{
"name": "visions-types",
"version": "0.0.1",
"description": "Shared data types for Visions",
"main": "visions.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"typescript": "^5.6.3"
}
}

View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["./visions.ts"]
}