Merge branch 'main' of https://gitlab.com/robossembler/webservice into alexander

This commit is contained in:
IDONTSUDO 2024-04-19 13:52:07 +03:00
commit 7e25cc216a
15 changed files with 641 additions and 18 deletions

View file

@ -24,13 +24,13 @@
"chai": "latest",
"eslint": "^8.47.0",
"mocha": "latest",
"node-watch": "^0.7.4",
"nodemon": "^3.0.1",
"nyc": "latest",
"source-map-support": "latest",
"ts-node": "^10.9.1",
"tslint": "latest",
"typescript": "^5.1.6"
"typescript": "^5.1.6",
"node-watch": "^0.7.4",
"nodemon": "^3.0.1"
},
"dependencies": {
"@grpc/grpc-js": "^1.9.0",

View file

@ -44,6 +44,7 @@ declare global {
toArray(): V[];
getPredicateValue(callBack: (value: V) => boolean): K[];
}
interface Vector3 {}
}
export const extensions = () => {
StringExtensions();

View file

@ -21,9 +21,7 @@ import {
Quaternion,
MeshBasicMaterial,
PlaneGeometry,
BoxGeometry,
BufferGeometry,
Line,
BoxGeometry
} from "three";
import { TypedEvent } from "../helper/typed_event";
import { Result } from "../helper/result";
@ -36,8 +34,7 @@ import {
import { SceneMode } from "../../features/scene_manager/model/scene_view";
import { throttle } from "../helper/throttle";
import { Asset, InstanceRgbCamera, RobossemblerAssets, SceneSimpleObject } from "../model/robossembler_assets";
import { CoreVector3 } from "../model/core_vector3";
export enum UserData {
selectedObject = "selected_object",
cameraInitialization = "camera_initialization",
@ -288,6 +285,18 @@ export class CoreThreeRepository extends TypedEvent<BaseSceneItemModel> {
floor.userData = {};
floor.userData[UserData.cameraInitialization] = true;
this.scene.add(floor);
const planeMesh = new Mesh(
new PlaneGeometry(10, 10, 10, 10),
new MeshBasicMaterial({ color: 0x808080, wireframe: true })
);
planeMesh.userData[UserData.selectedObject] = true;
planeMesh.userData[UserData.objectForMagnetism] = true;
planeMesh.rotation.x = -Math.PI / 2;
this.makeCube(1);
this.makeCube(2, new Vector3(20, 0, 10), "yellow");
this.scene.add(planeMesh);
}
render() {

View file

@ -1,6 +1,5 @@
import makeAutoObservable from "mobx-store-inheritance";
import xmlFormat from "xml-formatter";
import { HttpError } from "../../../core/repository/http_repository";
import { UiErrorState } from "../../../core/store/base_store";
import { BtBuilderModel, BtNodeView, ReteObserver } from "../model/editor_view";

View file

@ -0,0 +1,19 @@
.fill-area {
display: table;
z-index: -1;
position: absolute;
top: -320000px;
left: -320000px;
width: 640000px;
height: 640000px;
}
.background {
background-color: #ffffff;
opacity: 1;
background-image: linear-gradient(#f1f1f1 3.2px, transparent 3.2px),
linear-gradient(90deg, #f1f1f1 3.2px, transparent 3.2px), linear-gradient(#f1f1f1 1.6px, transparent 1.6px),
linear-gradient(90deg, #f1f1f1 1.6px, #ffffff 1.6px);
background-size: 80px 80px, 80px 80px, 16px 16px, 16px 16px;
background-position: -3.2px -3.2px, -3.2px -3.2px, -1.6px -1.6px, -1.6px -1.6px;
}

View file

@ -0,0 +1,164 @@
import * as React from "react";
import { ClassicScheme, RenderEmit, Presets } from "rete-react-plugin";
import styled, { css } from "styled-components";
import { $nodewidth, $socketmargin, $socketsize } from "./vars";
const { RefSocket, RefControl } = Presets.classic;
type NodeExtraData = { width?: number; height?: number };
export const NodeStyles = styled.div<NodeExtraData & { selected: boolean; styles?: (props: any) => any }>`
background: black;
border: 2px solid grey;
border-radius: 10px;
cursor: pointer;
box-sizing: border-box;
width: ${(props) => (Number.isFinite(props.width) ? `${props.width}px` : `${$nodewidth}px`)};
height: ${(props) => (Number.isFinite(props.height) ? `${props.height}px` : "auto")};
padding-bottom: 6px;
position: relative;
user-select: none;
&:hover {
background: #333;
}
${(props) =>
props.selected &&
css`
border-color: red;
`}
.title {
color: white;
font-family: sans-serif;
font-size: 18px;
padding: 8px;
}
.output {
text-align: right;
}
.input {
text-align: left;
}
.output-socket {
text-align: right;
margin-right: -1px;
display: inline-block;
}
.input-socket {
text-align: left;
margin-left: -1px;
display: inline-block;
}
.input-title,
.output-title {
vertical-align: middle;
color: white;
display: inline-block;
font-family: sans-serif;
font-size: 14px;
margin: ${$socketmargin}px;
line-height: ${$socketsize}px;
}
.input-control {
z-index: 1;
width: calc(100% - ${$socketsize + 2 * $socketmargin}px);
vertical-align: middle;
display: inline-block;
}
.control {
display: block;
padding: ${$socketmargin}px ${$socketsize / 2 + $socketmargin}px;
}
${(props) => props.styles && props.styles(props)}
`;
function sortByIndex<T extends [string, undefined | { index?: number }][]>(entries: T) {
entries.sort((a, b) => {
const ai = a[1]?.index || 0;
const bi = b[1]?.index || 0;
return ai - bi;
});
}
type Props<S extends ClassicScheme> = {
data: S["Node"] & NodeExtraData;
styles?: () => any;
emit: RenderEmit<S>;
};
export type NodeComponent<Scheme extends ClassicScheme> = (props: Props<Scheme>) => JSX.Element;
export function CustomNode<Scheme extends ClassicScheme>(props: Props<Scheme>) {
const inputs = Object.entries(props.data.inputs);
const outputs = Object.entries(props.data.outputs);
const controls = Object.entries(props.data.controls);
const selected = props.data.selected || false;
const { id, label, width, height } = props.data;
sortByIndex(inputs);
sortByIndex(outputs);
sortByIndex(controls);
return (
<NodeStyles selected={selected} width={width} height={height} styles={props.styles} data-testid="node">
<div
onPointerDown={(e) => {
e.stopPropagation();
console.log(">>>");
}}
className="title"
data-testid="title"
>
{label}
</div>
{outputs.map(
([key, output]) =>
output && (
<div className="output" key={key} data-testid={`output-${key}`}>
<div style={{ color: "white" }}>BODY</div>
<div className="output-title" data-testid="output-title">
{output?.label}
</div>
<RefSocket
name="output-socket"
side="output"
emit={props.emit}
socketKey={key}
nodeId={id}
payload={output.socket}
/>
</div>
)
)}
{controls.map(([key, control]) => {
return control ? <RefControl key={key} name="control" emit={props.emit} payload={control} /> : null;
})}
{inputs.map(
([key, input]) =>
input && (
<div className="input" key={key} data-testid={`input-${key}`}>
<RefSocket
name="input-socket"
emit={props.emit}
side="input"
socketKey={key}
nodeId={id}
payload={input.socket}
/>
{input && (!input.control || !input.showControl) && (
<div className="input-title" data-testid="input-title">
{input?.label}
</div>
)}
{input?.control && input?.showControl && (
<span className="input-control">
<RefControl key={key} name="input-control" emit={props.emit} payload={input.control} />
</span>
)}
</div>
)
)}
</NodeStyles>
);
}

View file

@ -0,0 +1,7 @@
import { TypedEvent } from "../../../../../core/helper/typed_event";
export interface BtDrawView {
x: number;
y: number;
name: string;
}
export class BtNodeView extends TypedEvent<BtDrawView> {}

View file

@ -0,0 +1,30 @@
import { Presets } from "rete-react-plugin";
import { css } from "styled-components";
import "./background.css";
const styles = css<{ selected?: boolean }>`
background: #ebebeb;
border-color: #646464;
.title {
color: #646464;
}
&:hover {
background: #f2f2f2;
}
.output-socket {
margin-right: -1px;
}
.input-socket {
margin-left: -1px;
}
${(props) =>
props.selected &&
css`
border-color: red;
`}
`;
export function StyledNode(props: any) {
// eslint-disable-next-line react/jsx-pascal-case
return <Presets.classic.Node styles={() => styles} {...props} />;
}

View file

@ -0,0 +1,3 @@
export const $nodewidth = 200;
export const $socketmargin = 6;
export const $socketsize = 16;

View file

@ -1,13 +1,8 @@
import * as React from "react";
import { SceneMangerStore } from "./scene_manager_store";
import { observer } from "mobx-react-lite";
import { StaticAssetModelView } from "./components/static_asset_item_view";
import { useParams } from "react-router-dom";
import { SceneManagerView, SceneMode } from "../model/scene_view";
import { Button } from "antd";
import { Form, Input, ResetButton, SubmitButton } from "formik-antd";
import { Formik } from "formik";
import { CameraViewModel } from "../model/scene_assets";
import { MainPage } from "../../../core/ui/pages/main_page";
export const SceneManagerPath = "/scene/manager/";

View file

@ -1,6 +1,6 @@
import makeAutoObservable from "mobx-store-inheritance";
import { CoreThreeRepository } from "../../../core/repository/core_three_repository";
import { Object3D, Vector2 } from "three";
import { CoreThreeRepository, UserData } from "../../../core/repository/core_three_repository";
import { Object3D, Vector2, Vector3 } from "three";
import { HttpError } from "../../../core/repository/http_repository";
import { UiErrorState } from "../../../core/store/base_store";
import { UiBaseError } from "../../../core/model/ui_base_error";

View file

@ -0,0 +1,133 @@
import * as React from "react";
import { observer } from "mobx-react-lite";
import { useParams } from "react-router-dom";
import { Button } from "antd";
import { StickObjectsMarkingStore, StickObjectsMarkingStoreMode } from "./stick_objects_marking_store";
import { Vector3 } from "three";
export const StickObjectsMarking = "/stick/objects/marking";
interface StickButtonsProps {
isVisible: boolean;
name: string;
groupMode: StickObjectsMarkingStoreMode;
storeMode: StickObjectsMarkingStoreMode;
storeModePoints: StickObjectsMarkingStoreMode;
setMode: Function;
setPointMode: Function;
points: Vector3[];
body: string;
}
export const StickButtons: React.FunctionComponent<StickButtonsProps> = observer((props) => {
return (
<>
{props.isVisible ? (
<>
{props.name}
<Button
style={{
backgroundColor: props.storeMode === props.storeModePoints ? "#ff7e1e" : "",
}}
onClick={() => props.setPointMode()}
>
add points
</Button>
{props.points.map((el) => {
return (
<>
{el.x} {el.y} {el.z}
</>
);
})}
</>
) : (
<Button
style={{
backgroundColor: props.groupMode === props.storeMode ? "#ff7e1e" : "",
}}
onClick={() => props.setMode(props.storeMode)}
>
{props.body}
</Button>
)}
</>
);
});
export const StickObjectsMarkingScreen = observer(() => {
const canvasRef = React.useRef<HTMLCanvasElement>(null);
const [store] = React.useState(() => new StickObjectsMarkingStore());
const id = useParams().id as string;
React.useEffect(() => {
store.init();
store.loadScene(canvasRef.current!);
document.body.style.overflow = "hidden";
return () => {
document.body.style.overflow = "scroll";
store.dispose();
};
}, [id, store]);
return (
<div>
<canvas ref={canvasRef} style={{ position: "absolute", overflow: "hidden" }} />
<div
style={{
display: "flex",
flexDirection: "row",
alignContent: "center",
justifyContent: "space-between",
position: "absolute",
width: "100vw",
}}
>
<div style={{ backgroundColor: "white", padding: "20px" }}>
{Object.keys(store.points).map((el) => {
// @ts-expect-error
const v = store.points[el];
return (
<>
<div>
{el as string}:{v}
</div>
</>
);
})}
<div>Marking objects for sticking</div>
<div>
<StickButtons
storeMode={store.mode}
setMode={() => store.setMode(StickObjectsMarkingStoreMode.objectThatSticks)}
groupMode={StickObjectsMarkingStoreMode.objectThatSticks}
name={store.objectThatSticksName}
storeModePoints={StickObjectsMarkingStoreMode.addPointsObjectThatSticks}
isVisible={store.objectThatSticksName !== undefined}
setPointMode={() => store.setMode(StickObjectsMarkingStoreMode.addPointsObjectThatSticks)}
points={store.objectThatSticksNamePoints}
body="objectThatSticksName"
/>
<StickButtons
body="objectsToWhichItSticksName"
points={store.objectsToWhichItSticksPoints}
storeMode={store.mode}
setMode={() => store.setMode(StickObjectsMarkingStoreMode.objectsToWhichItSticks)}
groupMode={StickObjectsMarkingStoreMode.objectsToWhichItSticks}
name={store.objectsToWhichItSticksName}
storeModePoints={StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks}
isVisible={store.objectsToWhichItSticksName !== undefined}
setPointMode={() => store.setMode(StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks)}
/>
<Button onClick={() => store.onSaveSticky()}>save</Button>
<Button
onClick={() => store.setMode(StickObjectsMarkingStoreMode.move)}
style={{ backgroundColor: store.mode === StickObjectsMarkingStoreMode.move ? "#ff7e1e" : "" }}
>
run
</Button>
</div>
</div>
</div>
</div>
);
});

View file

@ -0,0 +1,164 @@
import makeAutoObservable from "mobx-store-inheritance";
import { Box3, Vector2, Vector3 } from "three";
import { UiErrorState } from "../../core/store/base_store";
import { HttpError } from "../../core/repository/http_repository";
import { UiBaseError } from "../../core/model/ui_base_error";
import { RobossemblerFiles } from "../scene_manager/model/scene_assets";
import { StickObjectsMarkingThreeRepository } from "./stick_objects_marking_three_repository";
import { UserData } from "../../core/repository/core_three_repository";
import { ObjectExtensionsIsKeyExists } from "../../core/extensions/object";
export enum StickObjectsMarkingStoreMode {
objectsToWhichItSticks = "objectsToWhichItSticks",
objectThatSticks = "objectThatSticks",
addPointsObjectsToWhichItSticks = "addPointsObjectsToWhichItSticks",
addPointsObjectThatSticks = "addPointsObjectThatSticks",
move = "move",
}
export class StickyHelper {
objectThatSticksName: string;
objectThatSticksNamePoints: Vector3[] = [];
objectsToWhichItSticksName: string;
objectsToWhichItSticksPoints: Vector3[] = [];
constructor(
objectThatSticksName: string,
objectThatSticksNamePoints: Vector3[],
objectsToWhichItSticksName: string,
objectsToWhichItSticksPoints: Vector3[]
) {
this.objectThatSticksName = objectThatSticksName;
this.objectThatSticksNamePoints = objectThatSticksNamePoints;
this.objectsToWhichItSticksName = objectsToWhichItSticksName;
this.objectsToWhichItSticksPoints = objectsToWhichItSticksPoints;
}
}
export class StickObjectsMarkingStore extends UiErrorState<HttpError> {
mode: StickObjectsMarkingStoreMode;
stickObjectsMarkingThreeRepository: null | StickObjectsMarkingThreeRepository = null;
objectThatSticksName: string;
objectThatSticksNamePoints: Vector3[] = [];
objectsToWhichItSticksName: string;
objectsToWhichItSticksPoints: Vector3[] = [];
points = {};
constructor() {
super();
makeAutoObservable(this);
this.points = {};
this.mode = StickObjectsMarkingStoreMode.move;
this.loadStickyJSON(
'{"objectThatSticksName":"cube2","objectThatSticksNamePoints":[{"x":5,"y":-0.5419443937360455,"z":0.041458499858311626}],"objectsToWhichItSticksName":"cube1","objectsToWhichItSticksPoints":[{"x":-5,"y":-2.2134708060033113,"z":1.1937718220731925}]}'
);
}
updatePoint = (key: string, value: any) => {
// @ts-expect-error
this.points[key] = value;
};
onSaveSticky(): void {
window.prompt(
"Copy to clipboard: Ctrl+C, Enter",
JSON.stringify(
new StickyHelper(
this.objectThatSticksName,
this.objectThatSticksNamePoints,
this.objectsToWhichItSticksName,
this.objectsToWhichItSticksPoints
)
)
);
}
setMode(stickObjectsMarkingStoreMode: StickObjectsMarkingStoreMode): void {
this.mode = stickObjectsMarkingStoreMode;
}
loaderWatcher() {}
async init(): Promise<any> {}
errorHandingStrategy = (error: HttpError) => {
if (error.status === 404) {
this.errors.push(new UiBaseError(`${RobossemblerFiles.robossemblerAssets} not found to project`));
}
};
async loadScene(canvasRef: HTMLCanvasElement) {
this.loadWebGl(canvasRef);
}
watcherSceneEditorObject() {}
loadWebGl(canvasRef: HTMLCanvasElement): void {
this.stickObjectsMarkingThreeRepository = new StickObjectsMarkingThreeRepository(
canvasRef as HTMLCanvasElement,
this.watcherSceneEditorObject,
this.updatePoint
);
this.stickObjectsMarkingThreeRepository.stickyHelperLoader([
new StickyHelper(
this.objectThatSticksName,
this.objectThatSticksNamePoints,
this.objectsToWhichItSticksName,
this.objectsToWhichItSticksPoints
),
]);
this.stickObjectsMarkingThreeRepository.render();
window.addEventListener("click", (event) => this.clickLister(event));
}
clickLister(event: MouseEvent) {
const vector = new Vector2();
vector.x = (event.clientX / window.innerWidth) * 2 - 1;
vector.y = -(event.clientY / window.innerHeight) * 2 + 1;
if (this.mode) {
if (this.mode === StickObjectsMarkingStoreMode.move) {
this.stickObjectsMarkingThreeRepository?.setRayCastAndGetFirstObject(vector).fold(
(success) => this.stickObjectsMarkingThreeRepository?.setTransformControlsAttach(success),
(_error) => this.stickObjectsMarkingThreeRepository?.disposeTransformControlsMode()
);
}
this.stickObjectsMarkingThreeRepository?.setRayCast(vector).map((touch) => {
const objectMagnetism = touch.filter((el) => el.object.userData[UserData.objectForMagnetism] === true);
const BoundBoxVector = new Box3().setFromObject(objectMagnetism[0].object).getCenter(new Vector3());
const centerRelativeVector = new Vector3().subVectors(BoundBoxVector, objectMagnetism[0].point);
if (objectMagnetism.isNotEmpty()) {
if (this.mode === StickObjectsMarkingStoreMode.objectsToWhichItSticks) {
this.objectsToWhichItSticksName = objectMagnetism[0].object.name;
}
if (this.mode === StickObjectsMarkingStoreMode.objectThatSticks) {
this.objectThatSticksName = objectMagnetism[0].object.name;
}
if (this.mode === StickObjectsMarkingStoreMode.addPointsObjectThatSticks) {
this.objectThatSticksNamePoints.push(centerRelativeVector);
}
if (this.mode === StickObjectsMarkingStoreMode.addPointsObjectsToWhichItSticks) {
this.objectsToWhichItSticksPoints.push(centerRelativeVector);
}
}
});
}
}
dispose() {
window.removeEventListener("click", this.clickLister);
}
loadStickyJSON(value: string): void {
const object = JSON.parse(value) as Object;
if (
ObjectExtensionsIsKeyExists(object, [
"objectThatSticksName",
"objectThatSticksNamePoints",
"objectsToWhichItSticksName",
"objectsToWhichItSticksPoints",
])
) {
// @ts-expect-error
this.objectThatSticksName = object["objectThatSticksName"];
// @ts-expect-error
this.objectThatSticksNamePoints = object["objectThatSticksNamePoints"];
// @ts-expect-error
this.objectsToWhichItSticksName = object["objectsToWhichItSticksName"];
// @ts-expect-error
this.objectsToWhichItSticksPoints = object["objectsToWhichItSticksPoints"];
}
}
}

View file

@ -0,0 +1,101 @@
import { Box3, BoxGeometry, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three";
import { CoreThreeRepository } from "../../core/repository/core_three_repository";
import { StickyHelper } from "./stick_objects_marking_store";
import { CoreVector3 } from "../../core/model/core_vector3";
export class StickObjectsMarkingThreeRepository extends CoreThreeRepository {
stickyObjects: StickyHelper[];
drawUiPoint: Function;
constructor(htmlCanvasRef: HTMLCanvasElement, watcherSceneEditorObject: Function, updatePoint: Function) {
super(htmlCanvasRef, watcherSceneEditorObject);
this.drawUiPoint = updatePoint;
this.sceneWatcher();
}
getStickyObject(name: string, pointNameHelper: string, index: number) {
const objectThatSticksNameMesh = this.scene.getObjectByName(name);
const pointName = objectThatSticksNameMesh!.name + ":point:" + index + pointNameHelper;
return this.scene.getObjectByName(pointName);
}
mapperStickyObject(point: Vector3, index: number, name: string, pointNameHelper: string) {
const objectThatSticksNameMesh = this.scene.getObjectByName(name);
const pointName = objectThatSticksNameMesh!.name + ":point:" + index + pointNameHelper;
const sceneObject = this.scene.getObjectByName(pointName);
let pointMesh: Object3D;
if (sceneObject) {
pointMesh = sceneObject;
} else {
pointMesh = new Mesh(new BoxGeometry(1.1, 1.1, 1.1), new MeshBasicMaterial({ color: "#8BC34A" }));
}
pointMesh.position.copy(new Box3().setFromObject(objectThatSticksNameMesh!).getCenter(new Vector3()).add(point));
pointMesh.name = pointName;
if (sceneObject === undefined) this.scene.add(pointMesh);
}
stickyHelperLoader(stickyObjects: StickyHelper[]) {
this.stickyObjects = stickyObjects;
stickyObjects.forEach((el) => {
el.objectThatSticksNamePoints.forEach((point, index) =>
this.mapperStickyObject(point, index, el.objectThatSticksName, "objectThatSticksNamePoints")
);
el.objectsToWhichItSticksPoints.forEach((point, index) =>
this.mapperStickyObject(point, index, el.objectsToWhichItSticksName, "objectsToWhichItSticksPoints")
);
});
}
getCenter(obj: Object3D) {
return new Box3().setFromObject(obj).getCenter(new Vector3());
}
sceneWatcher() {
this.transformControls.addEventListener("objectChange", (event) => {
//@ts-expect-error
const sceneActiveObject = event.target.object as Mesh;
this.stickyObjects.forEach((stickyHelper) => {
if (sceneActiveObject.name === stickyHelper.objectThatSticksName) {
//локальные векторы точек
const objectThatSticksNameLocalVector = stickyHelper.objectThatSticksNamePoints[0];
const objectsToWhichItSticksPointLocalVector = stickyHelper.objectsToWhichItSticksPoints[0];
//глобальные векторы обьектов
const globalVectorObjStickyName = this.scene.getObjectByName(stickyHelper.objectThatSticksName);
const globalVectorObjToWhichSticks = this.scene.getObjectByName(stickyHelper.objectsToWhichItSticksName);
const objectsToWhichItSticksNamePosition = new CoreVector3(globalVectorObjToWhichSticks!.position).add(
objectsToWhichItSticksPointLocalVector
).vector;
this.scene
.getObjectByName("cube2:point:0objectThatSticksNamePoints")
?.position.copy(objectsToWhichItSticksNamePosition);
// this.scene.getObjectByName("cube2:point:0objectThatSticksNamePoints")?.position;
globalVectorObjStickyName?.position.copy(
this.scene
.getObjectByName("cube2:point:0objectThatSticksNamePoints")!
.position.add(objectsToWhichItSticksPointLocalVector)
);
// console.log(this.scene.children.map((e) => console.log(e.name)));
// cube2:point:0objectThatSticksNamePoints
// cube1:point:0objectsToWhichItSticksPoints
// this.makePoint(objectThatSticksNamePosition, "red", 1.1);
// this.makePoint(objectsToWhichItSticksNamePosition, "red", 1.1);
// const movePosition = objectThatSticksNamePosition.sub(objectsToWhichItSticksNamePosition);
// const movePosition = new Vector3().subVectors(
// objectThatSticksNamePosition,
// objectsToWhichItSticksNamePosition
// );
// this.scene.getObjectByName(stickyHelper.objectsToWhichItSticksName)?.position.copy(movePosition);
}
});
});
}
}

View file

@ -1,9 +1,7 @@
import React from "react";
import ReactDOM from "react-dom/client";
import "reflect-metadata";
import "antd/dist/antd.min.css";
import { extensions } from "./core/extensions/extensions";
import { SocketLister } from "./features/socket_lister/socket_lister";
import { RouterProvider } from "react-router-dom";