Skip to content

Commit

Permalink
Merge branch 'gbishop:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
gbishop authored Apr 15, 2024
2 parents cbcb7e1 + 981612b commit 8cbc24c
Show file tree
Hide file tree
Showing 60 changed files with 1,340 additions and 538 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ You can see a few simple and rough demos of the current capabilities by followin
- <a href="https://unc-project-open-aac.github.io/OS-DPI/?fetch=examples/updated/utterance_Contact.osdpi">Contact-like utterance-based system</a>
- <a href="https://unc-project-open-aac.github.io/OS-DPI/">Start a new design</a>

**These demos are known to not work in Safari.** Please use Google Chrome or one if its variants.
**These demos work in Safari 17+ but not in earlier versions.**

In these demos you can switch between the developer mode and full-screen user-interface pressing the **Alt** or **Option** key followed by the **d** key.

Expand Down
Binary file modified examples/updated/grid_ex_2.osdpi
Binary file not shown.
Binary file modified examples/updated/keyboard_predict_ex_1.osdpi
Binary file not shown.
Binary file modified examples/updated/utterance_Contact.osdpi
Binary file not shown.
2 changes: 2 additions & 0 deletions src/.rgignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
thinking/*
**/tracky-mouse/**
84 changes: 84 additions & 0 deletions src/UHTML.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { html as _html } from "uhtml";

export { render } from "uhtml";

const typeMap = new WeakMap();

/** @param {TemplateStringsArray} strings
* @param {any[]} args
*/
export function html(strings, ...args) {
let types = typeMap.get(strings);
if (!types) {
types = args.map((arg) => getTypeOf(arg));
typeMap.set(strings, types);
}

if (!strings[0].match(/\s*</)) {
throw new Error(`html does not begin with < ${strings[0]}`);
}

args.forEach((arg, index) => {
const string = strings[index];
if (!string.endsWith("=") && !string.endsWith('="')) {
// must be a content node
if (arg === null) {
throw new Error(`html arg after ${string} is null`);
}
if (arg === undefined) {
throw new Error(`html arg after ${string} is undefined`);
}
const atype = getTypeOf(arg);
if (atype != types[index]) {
const t = types[index];
if (
!atype.startsWith("Array") ||
!t.startsWith("Array") ||
!(atype.endsWith("empty") || t.endsWith("empty"))
)
throw new Error(
`type of arg after ${string} changed from ${types[index]} to ${atype}`,
);
}
} else {
// must be an attribute
const atype = getTypeOf(arg);
if (
atype != types[index] &&
atype != "undefined" &&
types[index] != "undefined" &&
atype != "null" &&
types[index] != "null"
) {
throw new Error(
`attribute ${string} changed from ${types[index]} to ${atype}`,
);
}
}
});
return _html(strings, ...args);
}

/** @param {any} arg
* @returns {string} */
function getTypeOf(arg) {
const t = typeof arg;
if (t != "object") return t;
if (arg == null) return "null";

if (Array.isArray(arg)) {
if (arg.length) {
const ts = arg.map((a) => getTypeOf(a));
if (!ts.every((t) => t == t[0])) {
return `Array of ${ts[0]}`;
} else {
console.error("array", ts);
throw new Error("Array elements of different types");
}
} else return `Array empty`;
}
if (arg.constructor.name == "Hole") {
return "Hole";
}
return "object";
}
1 change: 0 additions & 1 deletion src/components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ monitor.js: Show internal state in the designer.
toolbar.js: The designer toolbar.
treebase.js: Nearly every component is derived from TreeBase.
wait.js: Display "Please Wait" during asynchronous operations that take too long.
welcome.js: Display the welcome screen.

## Helpers

Expand Down
12 changes: 6 additions & 6 deletions src/components/access/cues/defaultCues.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default {
Name: "red overlay",
Key: "idl7w16hghqop9hcgn95",
CueType: "CueOverlay",
Default: true,
Default: "true",
Color: "red",
Opacity: "0.2",
},
Expand All @@ -26,11 +26,11 @@ export default {
Name: "fill",
Key: "idl7ysqw4agxg63qvx4j5",
CueType: "CueFill",
Default: false,
Default: "false",
Color: "#7BAFD4",
Opacity: "0.3",
Direction: "top",
Repeat: false,
Repeat: "false",
},
children: [],
},
Expand All @@ -40,9 +40,9 @@ export default {
Name: "circle",
Key: "idl7ythslqew02w4pom29",
CueType: "CueCircle",
Default: false,
Default: "false",
Color: "#7BAFD4",
Opacity: 0.7,
Opacity: "0.7",
},
children: [],
},
Expand All @@ -52,7 +52,7 @@ export default {
Name: "yellow overlay using CSS",
Key: "idl7qm4cs28fh2ogf4ni",
CueType: "CueCss",
Default: false,
Default: "false",
Code: `button[cue="$Key"] {
position: relative;
border-color: yellow;
Expand Down
5 changes: 4 additions & 1 deletion src/components/access/cues/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ export class CueList extends DesignerPanel {
// update any CueCss entries to the new style interpolation
if (obj.className == "CueList") {
for (const child of obj.children) {
if (child.className == "CueCss") {
if (
child.className == "CueCss" &&
typeof child.props.Code === "string"
) {
child.props.Code = child.props.Code.replaceAll("{{Key}}", "$Key");
}
}
Expand Down
22 changes: 9 additions & 13 deletions src/components/access/method/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ export class MethodChooser extends DesignerPanel {
static tableName = "method";
static defaultValue = defaultMethods;

onUpdate() {
super.onUpdate();
this.configure();
}

configure() {
// tear down the old configuration if any
this.stop();
Expand Down Expand Up @@ -118,7 +113,7 @@ export class Method extends TreeBase {
PointerEnterDebounce = new Props.Float(0, { label: "Pointer enter/leave" });
PointerDownDebounce = new Props.Float(0, { label: "Pointer down/up" });
Key = new Props.UID();
Active = new Props.OneOfGroup(false, { group: "ActiveMethod" });
Active = new Props.Boolean(false);

allowedChildren = [
"Timer",
Expand Down Expand Up @@ -249,7 +244,7 @@ export class Method extends TreeBase {
if (this.Active.value) {
this.streams = {};
for (const child of this.handlers) {
child.configure(stop$);
child.configure();
}
const streams = Object.values(this.streams);
if (streams.length > 0) {
Expand All @@ -272,7 +267,7 @@ export class Method extends TreeBase {

/** Refresh the pattern and other state on redraw */
refresh() {
this.pattern.refresh();
if (this.pattern) this.pattern.refresh();
}
}
TreeBase.register(Method, "Method");
Expand Down Expand Up @@ -350,10 +345,7 @@ export class Handler extends TreeBase {
);
}

/**
* @param {RxJs.Subject} _stop$
* */
configure(_stop$) {
configure() {
throw new TypeError("Must override configure");
}

Expand Down Expand Up @@ -403,7 +395,11 @@ export class HandlerKeyCondition extends HandlerCondition {

/** @param {EvalContext} context */
eval(context) {
return this.Key.value == context.data.key;
return !!(
context.data &&
context.data.key &&
this.Key.value == context.data.key
);
}
}
TreeBase.register(HandlerKeyCondition, "HandlerKeyCondition");
Expand Down
3 changes: 1 addition & 2 deletions src/components/access/method/keyHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ export class KeyHandler extends Handler {
`;
}

/** @param {RxJs.Subject} _stop$ */
configure(_stop$) {
configure() {
const method = this.method;
const streamName = "key";

Expand Down
12 changes: 5 additions & 7 deletions src/components/access/method/pointerHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ export class PointerHandler extends Handler {
`;
}

/** @param {RxJs.Subject} _ */
configure(_) {
configure() {
const method = this.method;
const streamName = "pointer";
// only create it once
if (method.streams[streamName]) return;

const pattern = method.pattern;

if (!pattern) return;

const inOutThreshold = method.PointerEnterDebounce.value * 1000;
const upDownThreshold = method.PointerDownDebounce.value * 1000;

Expand Down Expand Up @@ -110,7 +111,7 @@ export class PointerHandler extends Handler {
if (emittedEvents.length > 0 && over !== None) {
const newOver = pattern.remapEventTarget({
...over,
target: over.originalTarget,
target: over.originalTarget || null,
});
if (newOver.target !== over.target) {
// copy the accumulator to the new target
Expand Down Expand Up @@ -218,15 +219,12 @@ export class PointerHandler extends Handler {
let w = {
...event,
timeStamp: state.timeStamp,
access: event.access,
access: { ...event.access, eventType: event.type },
};
w.access.eventType = event.type;
return w;
}),
),
),
// multicast the stream
RxJs.share(),
);

method.streams[streamName] = pointerStream$;
Expand Down
5 changes: 2 additions & 3 deletions src/components/access/method/socketHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ export class SocketHandler extends Handler {
* @type {RxJs.Observable<EventLike> | undefined} */
socket$ = undefined;

/** @param {RxJs.Subject} _stop$ */
configure(_stop$) {
configure() {
const method = this.method;
const streamName = "socket";
// only create it once
Expand Down Expand Up @@ -101,7 +100,7 @@ export class SocketHandler extends Handler {
*/
let dynamicRows = [];
const fields = [];
for (const [key, value] of Object.entries(event.access)) {
for (const [key, value] of Object.entries(event.access || {})) {
console.log(key, value);
if (
Array.isArray(value) &&
Expand Down
3 changes: 1 addition & 2 deletions src/components/access/method/timerHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ export class TimerHandler extends Handler {
`;
}

/** @param {RxJs.Subject} _stop$ */
configure(_stop$) {
configure() {
const method = this.method;
const timerName = this.TimerName.value;
// there could be multiple timers active at once
Expand Down
8 changes: 6 additions & 2 deletions src/components/access/pattern/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export class PatternManager extends PatternBase {
group: "pattern-active",
label: "Default",
});
StartVisible = new Props.Boolean(false);

settingsSummary() {
const { Name, Active } = this;
Expand All @@ -201,11 +202,12 @@ export class PatternManager extends PatternBase {
}

settingsDetails() {
const { Cue, Name, Active } = this;
const { Cue, Name, Active, StartVisible } = this;
return [
html`
<div>
${Name.input()} ${Active.input()} ${Cue.input()}
${StartVisible.input()}
<button
@click=${() => {
this.animate();
Expand Down Expand Up @@ -269,7 +271,9 @@ export class PatternManager extends PatternBase {
members = buttons;
}
this.targets = new Group(members, { ...this.propsAsObject, Cycles: 1 });
this.stack = [{ group: this.targets, index: 0 }];
this.stack = [
{ group: this.targets, index: this.StartVisible.value ? 0 : -1 },
];
this.cue();

// stop any running animations
Expand Down
11 changes: 6 additions & 5 deletions src/components/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ export class Content extends DesignerPanel {
@input=${this.selectAll}
/>Select All</label
>
<ol
id="ContentMedia"
style="column-count: 3"
<div
ref=${(/** @type {HTMLOListElement} */ ol) => {
db.listMedia().then((names) => {
const list = names.map(
Expand All @@ -175,10 +173,13 @@ export class Content extends DesignerPanel {
<label><input type="checkbox" name=${name} />${name}</label>
</li>`,
);
render(ol, html`${list}`);
const body = html`<ol id="ContentMedia" style="column-count: 3">
${list}
</ol> `;
render(ol, body);
});
}}
></ol>
></div>
</div>
</div>`;
}
Expand Down
Loading

0 comments on commit 8cbc24c

Please sign in to comment.