Skip to content

Commit e153598

Browse files
authored
Merge v0.11.0 into master (#70)
* Restructure DMV code (#67) * Merge shared code into common.js * Refactor dmv/dispatchers into dispatch * Refactor dmv into transform and store.js * Refactor notifications.js into notify.js * Remove 'how it works' from DEVELOPERS.md Closes #66 * Add character name to commands (#69) Closes #65 * Update emote block format * Bump version to v0.11.0 * Update README formatting
1 parent 3d655b6 commit e153598

33 files changed

+174
-199
lines changed

DEVELOPERS.md

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -64,43 +64,4 @@ Notes:
6464

6565
- The test harness will create and activate a Python virtual environment in `tests/venv`.
6666
- Characters will be loaded from `tests/characters.json`.
67-
- Logs will be written to `tests/logs`.
68-
69-
## How does the extension work?
70-
71-
### Content and Background Scripts
72-
73-
- `dmv.js`: Loaded on Dungeon Master's Vault. Responsible for managing buttons and creating commands.
74-
- `background.js`: Loaded in the background. Responsible for managing the command queue.
75-
- `roll20.js`: Loaded on Roll20. Responsible for running commands.
76-
77-
### Queue-based Architecture
78-
79-
VTT Bridge uses a queue-based architecture. Commands are created by `dmv.js`, relayed through `background.js`, then ran by `roll20.js`. This relay is necessary because content scripts cannot directly communicate.
80-
81-
`roll20.js` polls `background.js` at regular intervals (e.g. every second) to ask for new commands. This implementation was chosen because the `activeTab` permission is required to send messages from background scripts to content scripts. We can avoid this permission by allowing the `roll20.js` content script to initiate the connection.
82-
83-
### Walkthrough
84-
85-
- The extension is loaded.
86-
- `background.js` creates an empty command queue.
87-
- `background.js` starts listening for messages.
88-
- The user opens a character sheet on Dungeon Master's Vault.
89-
- `dmv.js` displays a welcome notification.
90-
- `dmv.js` adds buttons and event listeners to the page.
91-
- `dmv.js` starts listening for dispatched actions.
92-
- The user joins a Roll20 game.
93-
- `roll20.js` displays a welcome notification.
94-
- `roll20.js` sends a `clear` message to `background.js`.
95-
- `background.js` receives the `clear` message and empties its queue.
96-
- The user clicks a button on Dungeon Master's Vault.
97-
- `dmv.js` dispatches a `click` action with the class name, event, and data.
98-
- `dmv.js` receives the `click` action.
99-
- `dmv.js` parses the `click` action into a notification and a list of commands.
100-
- `dmv.js` displays the notification.
101-
- `dmv.js` sends an `enqueue` message (with the commands) to `background.js`.
102-
- `background.js` receives the `enqueue` message and adds the commands to its queue.
103-
- `roll20.js` sends a `dequeue` message to `background.js`.
104-
- `background.js` receives the `dequeue` message and responds with all commands in its queue.
105-
- `background.js` empties its queue.
106-
- `roll20.js` receives the response and runs the commands.
67+
- Logs will be written to `tests/logs`.

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Install the VTT Bridge extension for Firefox or Google Chrome.
6969
<img src="assets/chrome.png" alt="Chrome logo">
7070
</a>
7171

72-
Open your Dungeon Master's Vault character sheet and click the <kbd>www</kbd> link. Launch your Roll 20 game in another tab.
72+
Open your Dungeon Master's Vault character sheet and click the <kbd>www</kbd> link. Launch your Roll20 game in another tab.
7373

7474
![www link](assets/www_link.png)
7575

@@ -81,23 +81,23 @@ Click one of the buttons on your Dungeon Master's Vault character sheet. Your ro
8181

8282
## FAQ
8383

84-
> Help, the buttons on Dungeon Master's Vault aren't working!
84+
**Help, the buttons on Dungeon Master's Vault aren't working!**
8585

8686
Make sure that you clicked the `www` link in the top right. The URL should end with `?frame`.
8787

88-
> Why does the extension need to "Access your data for www.dungeonmastersvault.com"?
88+
**Why does the extension need to "Access your data for www.dungeonmastersvault.com"?**
8989

9090
VTT Bridge needs to create buttons, add event listeners, and show notifications.
9191

92-
> Why does the extension need to "Access your data for app.roll20.net"?
92+
**Why does the extension need to "Access your data for app.roll20.net"?**
9393

94-
VTT Bridge needs to run commands and show notifications.
94+
VTT Bridge needs to create chat messages and show notifications.
9595

96-
> I found a bug! What should I do?
96+
**I found a bug! What should I do?**
9797

9898
[Open an issue](https://github.com/averycrespi/vtt-bridge/issues/new/choose), select "Bug report", then complete the issue template.
9999

100-
> I have an idea for a new feature! What should I do?
100+
**I have an idea for a new feature! What should I do?**
101101

102102
[Open an issue](https://github.com/averycrespi/vtt-bridge/issues/new/choose), select "Feature request", then complete the issue template.
103103

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 2,
33
"name": "VTT Bridge",
4-
"version": "0.10.0",
4+
"version": "0.11.0",
55
"description": "Connect Dungeon Master's Vault to Roll20.",
66
"icons": {
77
"48": "icons/48.png",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vtt-bridge",
33
"description": "Connect Dungeon Master's Vault to Roll20.",
44
"author": "Avery Crespi",
5-
"version": "0.10.0",
5+
"version": "0.11.0",
66
"license": "MIT",
77
"dependencies": {
88
"beedle": "^0.8.1",

src/callbacks.js

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/common.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export const classes = {
2+
attackWithSpell: "vtt-attack-with-spell",
3+
attackWithWeapon: "vtt-attack-with-weapon",
4+
castSpell: "vtt-cast-spell",
5+
rollAbilityScore: "vtt-roll-ability-score",
6+
rollInitiative: "vtt-roll-initiative",
7+
rollProficiency: "vtt-roll-proficiency",
8+
rollSavingThrow: "vtt-roll-saving-throw",
9+
rollSkill: "vtt-roll-skill",
10+
rollWeaponDamage: "vtt-roll-weapon-damage",
11+
useFeature: "vtt-use-feature",
12+
};
13+
14+
export const messageType = { enqueue: 0, dequeue: 1, clear: 2 };
15+
16+
/**
17+
* Run a callback after an element loads.
18+
*/
19+
export const onElementLoad = (selector, callback) => onPredicate(() => !!document.querySelector(selector), callback);
20+
21+
/**
22+
* Run a callback after an element's child loads.
23+
*/
24+
export const onChildLoad = (element, selector, callback) =>
25+
onPredicate(() => !!element.querySelector(selector), callback);
26+
27+
/**
28+
* Run a callback after a predicate is satisfied.
29+
*
30+
* Uses exponential backoff with limited attempts.
31+
*/
32+
const onPredicate = (predicate, callback, attempts = 10, timeout = 100) => {
33+
if (predicate()) {
34+
callback();
35+
} else if (attempts <= 0) {
36+
console.warn("Maximum number of attempts exceeded");
37+
} else {
38+
setTimeout(function () {
39+
onPredicate(predicate, callback, attempts - 1, timeout * 2);
40+
}, timeout);
41+
}
42+
};

src/dmv/dispatchers/expandSpell.js renamed to src/dispatch/expandSpell.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import * as classes from "../classes";
2-
3-
import { onElementLoad } from "../../callbacks";
1+
import { classes, onElementLoad } from "../common";
42

53
export const addExpandSpellListeners = (store) => onElementLoad(".details-columns tr.spell", () => ready(store));
64

src/dmv/dispatchers/index.js renamed to src/dispatch/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { addRollSavingThrowListeners } from "./rollSavingThrow";
33
import { addRollSkillListeners } from "./rollSkill";
44
import { addSelectTabListeners } from "./selectTab";
55
import { addToggleVisibilityListeners } from "./toggleVisibility";
6-
import { onElementLoad } from "../../callbacks";
6+
import { onElementLoad } from "../common";
7+
import { setCharacter } from "./setCharacter";
78

89
export const addDispatchers = (store, callback) =>
910
onElementLoad(".character-summary .class-name", () => {
11+
setCharacter(store);
1012
addToggleVisibilityListeners(store);
1113
addSelectTabListeners(store);
1214
addRollAbilityScoreListeners(store);

src/dmv/dispatchers/rollAbilityScore.js renamed to src/dispatch/rollAbilityScore.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import * as classes from "../classes";
2-
3-
import { onElementLoad } from "../../callbacks";
1+
import { classes, onElementLoad } from "../common";
42

53
export const addRollAbilityScoreListeners = (store) =>
64
onElementLoad(".ability-scores .ability-score-name", () => ready(store));

src/dmv/dispatchers/rollInitiative.js renamed to src/dispatch/rollInitiative.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import * as classes from "../classes";
2-
3-
import { onElementLoad } from "../../callbacks";
1+
import { classes, onElementLoad } from "../common";
42

53
export const addRollInitiativeListeners = (store) => onElementLoad(".initiative", () => ready(store));
64

0 commit comments

Comments
 (0)