improve ergonomics for sub-templates in TemplateView

- renames if to ifView
 - adds map and if that immediately take a sub template render function
   rather than having to call createTemplate
This commit is contained in:
Bruno Windels 2021-03-18 12:43:00 +01:00
parent 25cf72a9b6
commit eba4d8a28b
7 changed files with 31 additions and 20 deletions

View file

@ -296,11 +296,6 @@ class TemplateBuilder {
return root; return root;
} }
// sugar
createTemplate(render) {
return vm => new TemplateView(vm, render);
}
// map a value to a view, every time the value changes // map a value to a view, every time the value changes
mapView(mapFn, viewCreator) { mapView(mapFn, viewCreator) {
return this._addReplaceNodeBinding(mapFn, (prevNode) => { return this._addReplaceNodeBinding(mapFn, (prevNode) => {
@ -321,13 +316,29 @@ class TemplateBuilder {
}); });
} }
// creates a conditional subtemplate // Special case of mapView for a TemplateView.
if(fn, viewCreator) { // Always creates a TemplateView, if this is optional depending
// on mappedValue, use `if` or `mapView`
map(mapFn, renderFn) {
return this.mapView(mapFn, mappedValue => {
return new TemplateView(this._value, (t, vm) => {
return renderFn(mappedValue, t, vm);
});
});
}
ifView(predicate, viewCreator) {
return this.mapView( return this.mapView(
value => !!fn(value), value => !!predicate(value),
enabled => enabled ? viewCreator(this._value) : null enabled => enabled ? viewCreator(this._value) : null
); );
} }
// creates a conditional subtemplate
// use mapView if you need to map to a different view class
if(predicate, renderFn) {
return this.ifView(predicate, vm => new TemplateView(vm, renderFn));
}
} }

View file

@ -45,7 +45,7 @@ export class LoginView extends TemplateView {
t.div({className: "logo"}), t.div({className: "logo"}),
t.div({className: "LoginView form"}, [ t.div({className: "LoginView form"}, [
t.h1([vm.i18n`Sign In`]), t.h1([vm.i18n`Sign In`]),
t.if(vm => vm.error, t.createTemplate(t => t.div({className: "error"}, vm => vm.error))), t.if(vm => vm.error, t => t.div({className: "error"}, vm => vm.error)),
t.form({ t.form({
onSubmit: evnt => { onSubmit: evnt => {
evnt.preventDefault(); evnt.preventDefault();

View file

@ -70,14 +70,14 @@ class SessionPickerItemView extends TemplateView {
disabled: vm => vm.isClearing, disabled: vm => vm.isClearing,
onClick: () => vm.export(), onClick: () => vm.export(),
}, "Export"); }, "Export");
const downloadExport = t.if(vm => vm.exportDataUrl, t.createTemplate((t, vm) => { const downloadExport = t.if(vm => vm.exportDataUrl, (t, vm) => {
return t.a({ return t.a({
href: vm.exportDataUrl, href: vm.exportDataUrl,
download: `brawl-session-${vm.id}.json`, download: `brawl-session-${vm.id}.json`,
onClick: () => setTimeout(() => vm.clearExport(), 100), onClick: () => setTimeout(() => vm.clearExport(), 100),
}, "Download"); }, "Download");
})); });
const errorMessage = t.if(vm => vm.error, t.createTemplate(t => t.p({className: "error"}, vm => vm.error))); const errorMessage = t.if(vm => vm.error, t => t.p({className: "error"}, vm => vm.error));
return t.li([ return t.li([
t.a({className: "session-info", href: vm.openUrl}, [ t.a({className: "session-info", href: vm.openUrl}, [
t.div({className: `avatar usercolor${vm.avatarColorNumber}`}, vm => vm.avatarInitials), t.div({className: `avatar usercolor${vm.avatarColorNumber}`}, vm => vm.avatarInitials),
@ -118,7 +118,7 @@ export class SessionPickerView extends TemplateView {
href: vm.cancelUrl href: vm.cancelUrl
}, vm.i18n`Sign In`) }, vm.i18n`Sign In`)
]), ]),
t.if(vm => vm.loadViewModel, vm => new SessionLoadStatusView(vm.loadViewModel)), t.ifView(vm => vm.loadViewModel, () => new SessionLoadStatusView(vm.loadViewModel)),
t.p(hydrogenGithubLink(t)) t.p(hydrogenGithubLink(t))
]) ])
]); ]);

View file

@ -25,9 +25,9 @@ export class SessionStatusView extends TemplateView {
}}, [ }}, [
spinner(t, {hidden: vm => !vm.isWaiting}), spinner(t, {hidden: vm => !vm.isWaiting}),
t.p(vm => vm.statusLabel), t.p(vm => vm.statusLabel),
t.if(vm => vm.isConnectNowShown, t.createTemplate(t => t.button({className: "link", onClick: () => vm.connectNow()}, "Retry now"))), t.if(vm => vm.isConnectNowShown, t => t.button({className: "link", onClick: () => vm.connectNow()}, "Retry now")),
t.if(vm => vm.isSecretStorageShown, t.createTemplate(t => t.a({href: vm.setupSessionBackupUrl}, "Go to settings"))), t.if(vm => vm.isSecretStorageShown, t => t.a({href: vm.setupSessionBackupUrl}, "Go to settings")),
t.if(vm => vm.canDismiss, t.createTemplate(t => t.div({className: "end"}, t.button({className: "dismiss", onClick: () => vm.dismiss()})))), t.if(vm => vm.canDismiss, t => t.div({className: "end"}, t.button({className: "dismiss", onClick: () => vm.dismiss()}))),
]); ]);
} }
} }

View file

@ -54,7 +54,7 @@ export class BaseMediaView extends TemplateView {
} }
return renderMessage(t, vm, [ return renderMessage(t, vm, [
t.div({className: "media", style: `max-width: ${vm.width}px`}, children), t.div({className: "media", style: `max-width: ${vm.width}px`}, children),
t.if(vm => vm.error, t.createTemplate((t, vm) => t.p({className: "error"}, vm.error))) t.if(vm => vm.error, t => t.p({className: "error"}, vm.error))
]); ]);
} }
} }

View file

@ -26,7 +26,7 @@ export class GapView extends TemplateView {
return t.li({className}, [ return t.li({className}, [
spinner(t), spinner(t),
t.div(vm.i18n`Loading more messages …`), t.div(vm.i18n`Loading more messages …`),
t.if(vm => vm.error, t.createTemplate(t => t.strong(vm => vm.error))) t.if(vm => vm.error, t => t.strong(vm => vm.error))
]); ]);
} }
} }

View file

@ -67,11 +67,11 @@ function renderEnableFieldRow(t, vm, label, callback) {
} }
function renderError(t) { function renderError(t) {
return t.if(vm => vm.error, t.createTemplate((t, vm) => { return t.if(vm => vm.error, (t, vm) => {
return t.div([ return t.div([
t.p({className: "error"}, vm => vm.i18n`Could not enable session backup: ${vm.error}.`), t.p({className: "error"}, vm => vm.i18n`Could not enable session backup: ${vm.error}.`),
t.p(vm.i18n`Try double checking that you did not mix up your security key, security phrase and login password as explained above.`) t.p(vm.i18n`Try double checking that you did not mix up your security key, security phrase and login password as explained above.`)
]) ])
})); });
} }