diff --git a/client/src/App.css b/client/src/App.css
index 6c035b17..e18a9ac6 100644
--- a/client/src/App.css
+++ b/client/src/App.css
@@ -1,6 +1,6 @@
-body {
+html {
background: rgb(0,131,77);
- background: radial-gradient(circle, rgba(0,131,77,1) 0%, rgba(17,66,0,1) 100%);
+ /*background: radial-gradient(circle, rgba(0,131,77,1) 0%, rgba(17,66,0,1) 100%);*/
font-family: sans-serif;
}
@@ -41,4 +41,14 @@ header hr {
margin: 1rem;
padding: 1rem;
border-radius: 1rem;
+}
+
+input {
+ background: none;
+ border: none;
+ padding: 0;
+ font-size: unset;
+ color: unset;
+ width: auto;
+ overflow: visible;
}
\ No newline at end of file
diff --git a/client/src/App.jsx b/client/src/App.jsx
index 880043b7..782cc9d7 100644
--- a/client/src/App.jsx
+++ b/client/src/App.jsx
@@ -8,6 +8,8 @@ import Profile from '/src/login/Profile.jsx';
import GhostPage from '/src/page/GhostPage.jsx';
import Live from '/src/embodied/Live.jsx';
+//import Browsing from '/src/entwined/Browsing.jsx';
+
import AuthProvider from '/src/AuthProvider.jsx';
import './App.css';
diff --git a/client/src/apiTools.jsx b/client/src/apiTools.jsx
index 4cec4b57..d47d4b5f 100644
--- a/client/src/apiTools.jsx
+++ b/client/src/apiTools.jsx
@@ -42,6 +42,10 @@ export async function fetchPage(number) {
return shoofetch(`${apiUrl}/page/${number}`, {method: 'GET'});
}
+export async function fetchPageAttributes(number) {
+ return shoofetch(`${apiUrl}/page/${number}/attributes`, {method: 'GET'});
+}
+
export async function fetchPageHistory(number) {
return shoofetch(`${apiUrl}/page/${number}/history`, {method: 'GET'});
}
@@ -50,10 +54,10 @@ export async function fetchPageAtEdit(number, id) {
return shoofetch(`${apiUrl}/page/${number}/${id}`, {method: 'GET'});
}
-export async function postPage({id, title, description, type}) {
- return shoofetch(`${apiUrl}/page/${id}`, {
+export async function postPage({number, title, description, type}) {
+ return shoofetch(`${apiUrl}/page/${number}`, {
method: 'POST',
- body: JSON.stringify({id: id, title: title, description: description, type: type}),
+ body: JSON.stringify({number: number, title: title, description: description, type: type}),
})
}
diff --git a/client/src/embodied/CommandEntry.css b/client/src/embodied/CommandEntry.css
index 22f2ef94..ad415b34 100644
--- a/client/src/embodied/CommandEntry.css
+++ b/client/src/embodied/CommandEntry.css
@@ -10,6 +10,7 @@
left: 20%;
right: 20%;
border-radius: 1rem;
+ border: 1px solid gray;
}
.commandline form {
display: flex;
@@ -21,7 +22,7 @@
font-size: 16pt;
border: none;
padding: 2rem;
-
+ border-radius: 1rem;
background: transparent;
}
diff --git a/client/src/embodied/CommandEntry.jsx b/client/src/embodied/CommandEntry.jsx
index 84d536d4..cf73a5d2 100644
--- a/client/src/embodied/CommandEntry.jsx
+++ b/client/src/embodied/CommandEntry.jsx
@@ -1,18 +1,30 @@
+import { forwardRef } from 'react';
import { useForm } from "react-hook-form";
import './CommandEntry.css';
-function CommandEntry({ onSubmit }) {
+const CommandEntry = forwardRef(({ setCommand, onSubmitCommand, command }, ref) => {
const { register, handleSubmit, setValue } = useForm();
return (
-
);
-}
+});
export default CommandEntry;
\ No newline at end of file
diff --git a/client/src/embodied/Live.jsx b/client/src/embodied/Live.jsx
index 5c89726c..805340f9 100644
--- a/client/src/embodied/Live.jsx
+++ b/client/src/embodied/Live.jsx
@@ -1,70 +1,179 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useRef } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useParams, useNavigate } from 'react-router-dom';
-import { apiUrl, wsUrl } from '../apiTools.jsx';
+import { apiUrl, wsUrl, fetchPage, fetchPageAttributes, fetchPageAtEdit, postPage, fetchCurrentVerbs } from '../apiTools.jsx';
import { useFixLinks } from '../clientStuff.jsx';
import { useLoggedIn } from '../AuthProvider.jsx';
import useWebSocket, { ReadyState } from 'react-use-websocket';
import Page from '../page/Page.jsx';
+import ExtendedAttributes from '../page/ExtendedAttributes.jsx';
import MessageFeed from './MessageFeed.jsx';
import Sidebar from './Sidebar.jsx';
import CommandEntry from './CommandEntry.jsx';
-function Live({editing, ...props}) {
+function Live({...props}) {
const navigate = useNavigate();
const loggedIn = useLoggedIn();
+ const queryClient = useQueryClient();
+ const [ command, setCommand ] = useState('');
const [ messageHistory, setMessageHistory ] = useState([]);
const [ currentNumber, setCurrentNumber ] = useState(1);
+ const [ editing, setEditing ] = useState(false);
const [ connecting, setConnecting ] = useState(true);
+ const commandEntryRef = useRef(null);
+
+ //setting up the websocket and using its data!
const { sendMessage, lastMessage, lastJsonMessage, readyState } = useWebSocket(`${wsUrl}/embody`, {
- onClose: () => setConnecting(false)
+ onClose: () => console.log("broke connection!"),
+ onOpen: () => console.log("opened connection"),
+ shouldReconnect: (closeEvent) => true,
}, connecting);
+ useEffect(() => console.log(lastMessage), [lastMessage]);
+
useEffect(() => {
- if (lastMessage !== null) {
- console.log(lastMessage);
- setMessageHistory((prev) => prev.concat(lastMessage));
-
- if (lastMessage.data.startsWith("location change to: ")) {
- const num = Number(lastMessage.data.replace("location change to: #", ""));
- setCurrentNumber(num);
- }
+ if (!(lastJsonMessage === null || lastJsonMessage === undefined)) {
+ setMessageHistory((prev) => prev.concat(lastJsonMessage));
+ //if (lastJsonMessage["error"]) alert(lastJsonMessage["error"]);
+ if (lastJsonMessage["setPageNumber"])
+ setCurrentNumber(Number(lastJsonMessage["setPageNumber"]));
}
- }, [lastMessage]);
+ }, [lastJsonMessage, lastMessage]);
+
+
+ // first class object data values!
+ const fetchPageQuery = useQuery({
+ queryKey: ['page', currentNumber, null],
+ queryFn: () => fetchPage(currentNumber),
+ });
+
+ // setting up for editing and suchlike
+ const [title, setTitle] = useState(null);
+ useEffect(() => {
+ setTitle(fetchPageQuery.data?.title);
+ }, [fetchPageQuery.data?.title]);
+
+ const [text, setText] = useState(null);
+ useEffect(() => {
+ setText(fetchPageQuery.data?.description);
+ }, [fetchPageQuery.data?.description]);
+
+ const [type, setType] = useState(false);
+ useEffect(() => {
+ setType(fetchPageQuery.data?.type == 1);
+ }, [fetchPageQuery.data?.type]);
+
+ // extended attribute store!
+ const fetchAttributesQuery = useQuery({
+ queryKey: ['attributes', currentNumber],
+ queryFn: () => fetchPageAttributes(currentNumber)
+ });
+
+ // verbs available to us
+ const fetchVerbsQuery = useQuery({
+ queryKey: ['my verbs'],
+ queryFn: fetchCurrentVerbs,
+ });
+
+ let verbs = fetchVerbsQuery.data || [];
+ if (!editing) verbs = ["edit this"].concat(verbs);
+ else verbs = ["save changes"].concat(verbs);
+
+ const postMutation = useMutation({ // for changing the value when we're done with it
+ mutationFn: postPage,
+ onSettled: async (data, error, variables) => {
+ queryClient.invalidateQueries(['page', variables.number, null])
+ },
+ });
+
+ function saveChanges() {
+ postMutation.mutate({
+ number: currentNumber,
+ title: title,
+ description: text,
+ type: type ? 1 : 0,
+ });
+ }
+
+ function handleSubmitCommand() {
+ const c = command.trim();
+ if (c == "edit this") setEditing(true);
+ else if (c == "save changes") {
+ saveChanges();
+ setEditing(false);
+ }
+ else sendMessage(c);
+
+ setCommand("");
+ }
// spread this return value on elements in order to make them navigate
const commandLinkClick = (e) => {
- if (e.target.tagName != "A") { return; }
- if (!e.target.href.includes(window.location.origin)) { return; }
+ if (e.target.tagName != "A") return;
+ if (!e.target.href.includes(window.location.origin)) return;
+ if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;
+
+ // if it was an tag, if it's to a subdomain of this website, and a modifier wasn't held
+ // then we should prevent default behavior and execute our own.
e.preventDefault();
const localLink = e.target.href.replace(window.location.origin, "");
const targetString = localLink.replace("/", "");
const targetNumber = Number(targetString);
- if (targetNumber != 0 && targetNumber != NaN) {
- const warpMessage = `warp #${targetString}`;
- console.log(`clicked a link, executing "warp #${targetString}"`);
+ if (targetNumber != 0 && !isNaN(targetNumber)) {
+ const warpMessage = `warp #${targetNumber}`;
+ console.log(`clicked a link, executing "warp #${targetNumber}"`);
sendMessage(warpMessage);
return;
}
-
+
navigate(e.target.href.replace(window.location.origin, ""));
};
+ useEffect(() => {
+ window.history.replaceState(null, "", window.location.origin + "/" + currentNumber);
+ }, [currentNumber]);
+
return (
<>
-
+
+
setTitle(e.target.value)}
+ onChangeText={setText}
+ onChangeType={() => setType(!type)}
+ {...props} />
+
+
-
+
- setCommand((command + " " + word).trim())}>
+ {
+ setCommand((command + " " + word).trim());
+ commandEntryRef.current.focus();
+ // maybe set focus to the command entry?
+ }}>
- { console.log(w); sendMessage(w); } }/>
+ {setCommand(val)}}
+ onSubmitCommand={handleSubmitCommand}
+ command={command} />
>
);
}
diff --git a/client/src/embodied/MessageFeed.jsx b/client/src/embodied/MessageFeed.jsx
index d46cb4af..c5d25f8a 100644
--- a/client/src/embodied/MessageFeed.jsx
+++ b/client/src/embodied/MessageFeed.jsx
@@ -17,7 +17,7 @@ function MessageFeed({messages=[], children}) {
{messages.map((message, idx) =>
-
- {message.data}
+ {JSON.stringify(message)}
)}
diff --git a/client/src/embodied/Sidebar.jsx b/client/src/embodied/Sidebar.jsx
index c9e64aff..6b57120e 100644
--- a/client/src/embodied/Sidebar.jsx
+++ b/client/src/embodied/Sidebar.jsx
@@ -5,24 +5,17 @@ import { fetchCurrentVerbs } from '../apiTools.jsx';
import './Sidebar.css';
-function Sidebar({children, pagenumber, hidden=false, sendWord=(()=>null)}) {
+function Sidebar({children, verbs, hidden=true, sendWord=(()=>null)}) {
const [open, setOpen] = useState(!hidden);
const loggedIn = useLoggedIn();
- const { isPending, isError, error, data } = useQuery({ // fetch the currrent values
- queryKey: ['my verbs'],
- queryFn: fetchCurrentVerbs,
- });
-
- const verbs = data;
-
return (