Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Commit

Permalink
Merge pull request #119 from latitudegames/TTH-290/add-redux
Browse files Browse the repository at this point in the history
Tth 290/add redux
  • Loading branch information
michaelsharpe authored Oct 9, 2021
2 parents 74eec91 + 530d727 commit 09e058f
Show file tree
Hide file tree
Showing 19 changed files with 447 additions and 96 deletions.
4 changes: 4 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
"@material-ui/icons": "^4.11.2",
"@monaco-editor/react": "^4.2.1",
"@rebass/forms": "^4.0.6",
"@reduxjs/toolkit": "^1.6.2",
"@types/jest": "^26.0.24",
"@types/node": "^16.4.3",
"@types/react": "^17.0.15",
"@types/react-dom": "^17.0.9",
"@types/react-redux": "^7.1.18",
"classnames": "^2.3.1",
"deep-equal": "^2.0.5",
"eslint-config-react-app": "^6.0.0",
Expand All @@ -42,9 +44,11 @@
"react-hotkeys-hook": "^3.3.2",
"react-icons": "^4.2.0",
"react-pouchdb": "^2.1.0",
"react-redux": "^7.2.5",
"react-select": "^4.3.1",
"react-simple-code-editor": "^0.11.0",
"rebass": "^4.0.7",
"redux": "^4.1.1",
"regenerator-runtime": "^0.13.9",
"rete-connection-reroute-plugin": "^0.4.0",
"rete-context-menu-plugin": "^0.6.0-rc.1",
Expand Down
75 changes: 29 additions & 46 deletions client/src/contexts/EditorProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,21 @@
import { initEditor, EngineContext } from '@latitudegames/thoth-core'
import React, { useRef, useContext, createContext, useState } from 'react'
import { initEditor } from '@latitudegames/thoth-core'
import React, {
useRef,
useContext,
createContext,
useState,
useEffect,
} from 'react'

import { useLazyGetSpellQuery, Spell } from '../state/spells'

import LoadingScreen from '../features/common/LoadingScreen/LoadingScreen'
import { MyNode } from '../features/common/Node/Node'
import gridimg from '../grid.png'
import { usePubSub } from './PubSubProvider'
import { useRete } from './ReteProvider'
import { useSpell } from './SpellProvider'

export type SpellContext = {
currentSpell: {}
getCurrentSpell: () => void
updateCurrentSpell: {}
loadSpell: () => void
saveSpell: () => void
newSpell: () => void
saveCurrentSpell: () => void
stateHistory: never[]
currentGameState: {}
getCurrentGameState: () => Record<string, unknown>
rewriteCurrentGameState: () => Record<string, unknown>
updateCurrentGameState: () => void
getThothVersion: () => void
}

export interface ReteContext extends EngineContext {
onInspector: () => void
onPlayTest: () => void
onGameState: () => void
sendToPlaytest: () => void
sendToInspector: () => void
clearTextEditor: () => void
getSpell: () => void
getModule: () => void
getGameState: () => void
setGameState: () => void
getModules: () => void
}
import { usePubSub } from './PubSubProvider'
import { useRete, ReteContext } from './ReteProvider'
// import { ThothTab } from './TabManagerProvider'

export type ThothTab = {
layoutJson: string
Expand All @@ -54,7 +33,8 @@ const Context = createContext({
serialize: () => {},
buildEditor: (
el: HTMLDivElement,
spell: SpellContext,
// todo update this to use proper spell type
spell: Spell | undefined,
tab: ThothTab,
reteInterface: ReteContext
) => {},
Expand Down Expand Up @@ -89,10 +69,10 @@ const EditorProvider = ({ children }) => {
return editorRef.current
}

const buildEditor = async (container, spell, tab, thoth) => {
// console.log('init editor', initEditor)
const buildEditor = async (container, _spell, tab, thoth) => {
// copy spell in case it is read only
const spell = JSON.parse(JSON.stringify(_spell))
// eslint-disable-next-line no-console
console.log('building editor for tab', tab)
const newEditor = await initEditor({
container,
pubSub,
Expand All @@ -106,10 +86,7 @@ const EditorProvider = ({ children }) => {
// set editor to the map
setEditor(newEditor)

if (tab.type === 'spell') {
const spellDoc = await thoth.getSpell(tab.spell)
newEditor.loadGraph(spellDoc.toJSON().graph)
}
if (tab.type === 'spell') newEditor.loadGraph(spell.graph)

if (tab.type === 'module') {
const moduleDoc = await thoth.getModule(tab.module)
Expand Down Expand Up @@ -169,14 +146,20 @@ const EditorProvider = ({ children }) => {
}

const RawEditor = ({ tab, children }) => {
const [getSpell, { data: spell, isLoading }] = useLazyGetSpellQuery()
const [loaded, setLoaded] = useState(false)
const { buildEditor } = useEditor()
const spell = useSpell()
const { getCurrentGameState, updateCurrentGameState } = spell
const { getCurrentGameState, updateCurrentGameState } = useSpell()
// This will be the main interface between thoth and rete
const reteInterface = useRete()

if (!tab) return <LoadingScreen />
useEffect(() => {
if (!tab) return

getSpell(tab.spell)
}, [tab])

if (isLoading || !tab || !spell) return <LoadingScreen />

return (
<>
Expand Down Expand Up @@ -214,6 +197,6 @@ const RawEditor = ({ tab, children }) => {

export const Editor = React.memo(RawEditor)

Editor.whyDidYouRender = true
Editor.whyDidYouRender = false

export default EditorProvider
17 changes: 17 additions & 0 deletions client/src/contexts/ReteProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EngineContext } from '@latitudegames/thoth-core'
import { useContext, createContext } from 'react'

import { postEnkiCompletion } from '../services/game-api/enki'
Expand All @@ -11,6 +12,20 @@ Some notes here. The new rete provider, not to be confused with the old rete pr
Not all functions will be needed on the server, and functions which are not will be labeled as such.
*/

export interface ReteContext extends EngineContext {
onInspector: () => void
onPlayTest: () => void
onGameState: () => void
sendToPlaytest: () => void
sendToInspector: () => void
clearTextEditor: () => void
getSpell: () => void
getModule: () => void
getGameState: () => void
setGameState: () => void
getModules: () => void
}

const Context = createContext({
onInspector: () => {},
onPlayTest: () => {},
Expand Down Expand Up @@ -134,6 +149,8 @@ const ReteProvider = ({ children, tab }) => {
enkiCompletion,
huggingface,
...modules,

// going to need to manuall create theses
...spells,
}

Expand Down
16 changes: 14 additions & 2 deletions client/src/contexts/SpellProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@ import { useContext, createContext, useState, useRef } from 'react'

import { useDB } from './DatabaseProvider'

export type SpellContext = {
currentSpell: {}
getCurrentSpell: () => void
loadSpell: () => void
saveSpell: () => void
saveCurrentSpell: () => void
stateHistory: never[]
currentGameState: {}
getCurrentGameState: () => Record<string, unknown>
rewriteCurrentGameState: () => Record<string, unknown>
updateCurrentGameState: () => void
getThothVersion: () => void
}

const Context = createContext({
currentSpell: {},
getCurrentSpell: () => {},
updateCurrentSpell: {},
loadSpell: () => {},
saveSpell: () => {},
newSpell: () => {},
saveCurrentSpell: () => {},
stateHistory: [],
currentGameState: {},
Expand Down
7 changes: 5 additions & 2 deletions client/src/database/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import userCollection from './schemas/user'
// eslint-disable-next-line @typescript-eslint/no-var-requires
addRxPlugin(require('pouchdb-adapter-idb'))

let databaseReturn = null
let database = null
const databaseName = 'thoth_alpha'
const adapter = 'idb'

export const initDB = async () => {
if (database !== null) return database
if (databaseReturn !== null) return databaseReturn

// Uncomment this for fast deletion of DB
if (process.env.NODE_ENV !== 'production') {
Expand Down Expand Up @@ -107,8 +108,10 @@ export const initDB = async () => {
user: userModel(database),
}

return {
databaseReturn = {
database,
models,
}

return databaseReturn
}
17 changes: 17 additions & 0 deletions client/src/database/models/spellModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const loadSpellModel = db => {
.exec()
}

const getSpells = async spellId => {
return await db.spells.find().exec()
}

const updateSpell = async (spellId, update) => {
const spell = await getSpell(spellId)

Expand All @@ -20,6 +24,17 @@ const loadSpellModel = db => {
})
}

const saveSpell = async (spellId, spellUpdate) => {
const spell = await getSpell(spellId)

return spell.atomicUpdate(oldData => {
return {
...oldData,
...spellUpdate,
}
})
}

const newSpell = async ({ graph, name, gameState = {} }) => {
const newSpell = {
name,
Expand All @@ -32,7 +47,9 @@ const loadSpellModel = db => {

return {
getSpell,
getSpells,
updateSpell,
saveSpell,
newSpell,
}
}
Expand Down
7 changes: 4 additions & 3 deletions client/src/features/StartScreen/StartScreen.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react'

import { useNewSpellMutation } from '../../state/spells'
import { useDB } from '../../contexts/DatabaseProvider'
import { useTabManager } from '../../contexts/TabManagerProvider'
import AllProjects from './components/AllProjects'
Expand All @@ -15,6 +16,8 @@ const StartScreen = ({ createNew, allProjects }) => {
} = useDB()
const { openTab } = useTabManager()

const [newSpell] = useNewSpellMutation()

const projects = [
{ label: 'Lorem ipsum' },
{ label: 'Dolor sit' },
Expand All @@ -27,9 +30,7 @@ const StartScreen = ({ createNew, allProjects }) => {
// TODO check for proper values here and throw errors

const existingSpell = await spells.getSpell(spellData.name)
const spell = existingSpell
? existingSpell
: await spells.newSpell(spellData)
const spell = existingSpell ? existingSpell : await newSpell(spellData)

// Load modules from the spell
if (spellData?.modules && spellData.modules.length > 0)
Expand Down
10 changes: 6 additions & 4 deletions client/src/features/StartScreen/components/CreateNew.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useState } from 'react'
import { useState, useEffect } from 'react'
import {
uniqueNamesGenerator,
adjectives,
colors,
} from 'unique-names-generator'
import { useLocation } from 'wouter'

import { useSpell } from '../../../contexts/SpellProvider'
import { useNewSpellMutation } from '../../../state/spells'
import { useTabManager } from '../../../contexts/TabManagerProvider'
import Panel from '../../common/Panel/Panel'
import emptyImg from '../empty.png'
Expand Down Expand Up @@ -35,12 +35,14 @@ const templates = [
const CreateNew = () => {
const [, setLocation] = useLocation()
const [selectedTemplate, setSelectedTemplate] = useState(null)
const { newSpell } = useSpell()

const [newSpell] = useNewSpellMutation()

const { openTab, clearTabs } = useTabManager()

const onCreate = async () => {
const placeholderName = uniqueNamesGenerator(customConfig)
const spell = await newSpell({
const { data: spell } = await newSpell({
graph: defaultGraph,
name: placeholderName,
})
Expand Down
1 change: 1 addition & 0 deletions client/src/features/StartScreen/components/OpenProject.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const OpenProject = ({
loadFile,
}) => {
const { tabs } = useTabManager()
// TODO remove thoth version from spellprovider
const { getThothVersion } = useSpell()
// eslint-disable-next-line no-unused-vars
const [, setLocation] = useLocation()
Expand Down
Loading

0 comments on commit 09e058f

Please sign in to comment.