Skip to content

Instantly share code, notes, and snippets.

View mweststrate's full-sized avatar
💭
I may be slow to respond.

Michel Weststrate mweststrate

💭
I may be slow to respond.
View GitHub Profile
@mweststrate
mweststrate / index.html
Created March 25, 2021 11:09
electron crash v2
<!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. -->
@mweststrate
mweststrate / computed-views-with-args.js
Last active May 25, 2022 00:04
React AMA - Michel Weststrate / MobX
// 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) {
@mweststrate
mweststrate / action.js
Last active February 21, 2019 13:53
Decorator usage in mobx
// 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 {
@mweststrate
mweststrate / onStopDrag.ts
Created August 31, 2018 17:56
No concurrency
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;
});
@mweststrate
mweststrate / server.ts
Last active August 31, 2018 16:06
Server
export interface Change {
base: string;
changeId: string;
patches: Patch[];
}
export class Server {
clients: Client[] = [];
@mweststrate
mweststrate / onReceive.ts
Last active August 31, 2018 17:44
Rebase actions after receiving changes by the server
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;
@mweststrate
mweststrate / distributeFirstChange.ts
Created August 31, 2018 12:56
Sending changes to the server
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
@mweststrate
mweststrate / Client-state.ts
Last active August 31, 2018 12:50
Client state
interface PendingAction {
id: string;
fn: (draft: any) => void;
patches: Patch[];
}
export class Client {
pendingActions: PendingAction[] = [];
confirmedState!: {
id: string;
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);
@mweststrate
mweststrate / a_old-react-api.js
Last active July 21, 2018 13:33
React api difference
// 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)
}