This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Hello World!</title> | |
<link rel="stylesheet" type="text/css" href="./styles.css"> | |
</head> | |
<body> | |
<h1>Hello World!</h1> | |
<!-- All of the Node.js APIs are available in this renderer process. --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Parameterized computed views: | |
// Create computed's and store them in a cache | |
import { observable, computed } from "mobx" | |
class Todos { | |
@observable todos = [] | |
private todosByUserCache = new Map() | |
getAllTodosByUser(userId) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// case 2: manipulates the value of the descriptor, returns fresh descriptor | |
class MyClass { | |
@action someMethod() { | |
} | |
} | |
function action(target, key, descriptor) { | |
const baseValue = descriptor.value | |
return { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
onStopDrag = (id, { dx, dy }) => { | |
// we capture this outside the propose closure! | |
const baseBox = this.client.currentState.boxes.find(b => b.id === id); | |
this.client.propose(draft => { | |
const box = draft.boxes.find(b => b.id === id); | |
if (box.x !== baseBox.x || box.y !== baseBox.y) | |
throw "Somebody else already dragged this box!"; | |
box.x += dx; | |
box.y += dy; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface Change { | |
base: string; | |
changeId: string; | |
patches: Patch[]; | |
} | |
export class Server { | |
clients: Client[] = []; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
onReceive(change: Change) { | |
this.confirmedState = { | |
id: change.changeId, | |
state: applyPatches(this.confirmedState.state, change.patches) | |
}; | |
// reapply all the pending actions, filter out the ones that can't be applied anymore | |
const { pendingActions } = this; | |
// reset the pending changes collection. We will fill it again by replaying all actions. | |
this.pendingActions = []; | |
this.currentState = this.confirmedState.state; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async distributeFirstChange() { | |
const p = this.pendingActions[0]; | |
const response = await this.server.propose(this, { | |
base: this.confirmedState.id, | |
patches: p.patches, | |
changeId: p.id | |
}); | |
if (response === "NOPE") { | |
console.warn(this.name + ": Change rejected; outdated"); | |
// we keep the actions for now, and we will try to replay them after receiving the next change |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface PendingAction { | |
id: string; | |
fn: (draft: any) => void; | |
patches: Patch[]; | |
} | |
export class Client { | |
pendingActions: PendingAction[] = []; | |
confirmedState!: { | |
id: string; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
onStopDrag = (id, { dx, dy }) => { | |
// dx and dy are captured in the closure! | |
this.client.propose(draft => { | |
const box = draft.boxes.find(b => b.id === id); | |
box.x += dx; | |
box.y += dy; | |
if (box.x < 0 || box.x > 400 || box.y < 0 || box.y > 400) | |
// throwing here is safe; as original state will be untouched. | |
// This can happen when actions are being replayed | |
throw "Invalid drop coordinates: " + JSON.stringify(box); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Example component: render the current value of a stream. Support switching streams during the lifecycle of the component | |
// N.B. code is untested | |
// Old: | |
class RenderStream extends Component { | |
subscription | |
componentWillMount() { | |
this.subscribeToStream(this.props.stream) | |
} |
NewerOlder