also render steps on open stage of client view as actions

This commit is contained in:
Bruno Windels 2021-02-04 17:06:48 +01:00
parent 28fb6dfe9d
commit cd4f62d178
2 changed files with 103 additions and 62 deletions

View file

@ -65,12 +65,7 @@ export class ClientView extends TemplateView {
class OpenClientView extends TemplateView { class OpenClientView extends TemplateView {
render(t, vm) { render(t, vm) {
return t.div({className: "OpenClientView"}, [ return t.div({className: "OpenClientView"}, [
t.a({ ...vm.openActions.map(a => renderAction(t, a)),
className: "primary fullwidth",
href: vm.deepLink,
rel: "noopener noreferrer",
onClick: () => vm.deepLinkActivated(),
}, "Continue"),
showBack(t, vm), showBack(t, vm),
]); ]);
} }
@ -98,34 +93,14 @@ class InstallClientView extends TemplateView {
children.push(t.p({className: "instructions"}, renderInstructions(textInstructions).concat(copyButton))); children.push(t.p({className: "instructions"}, renderInstructions(textInstructions).concat(copyButton)));
} }
const actions = t.div({className: "actions"}, vm.actions.map(a => { const actions = t.div({className: "actions"}, vm.installActions.map(a => renderAction(t, a)));
let badgeUrl;
switch (a.kind) {
case "play-store": badgeUrl = "images/google-play-us.svg"; break;
case "fdroid": badgeUrl = "images/fdroid-badge.png"; break;
case "apple-app-store": badgeUrl = "images/app-store-us-alt.svg"; break;
case "flathub": badgeUrl = "images/flathub-badge.svg"; break;
}
return t.a({
href: a.url,
className: {
fullwidth: !badgeUrl,
primary: a.primary && !badgeUrl,
secondary: !a.primary && !badgeUrl,
badge: !!badgeUrl,
},
rel: "noopener noreferrer",
["aria-label"]: a.label,
onClick: () => a.activated()
}, badgeUrl ? t.img({src: badgeUrl}) : a.label);
}));
children.push(actions); children.push(actions);
if (vm.showDeepLinkInInstall) { if (vm.showDeepLinkInInstall) {
const deepLink = t.a({ const deepLink = t.a({
rel: "noopener noreferrer", rel: "noopener noreferrer",
href: vm.deepLink, href: vm.openActions[0].url,
onClick: () => vm.deepLinkActivated(), onClick: () => vm.openActions[0].activated(),
}, "open it here"); }, "open it here");
children.push(t.p([`If you already have ${vm.name} installed, you can `, deepLink, "."])) children.push(t.p([`If you already have ${vm.name} installed, you can `, deepLink, "."]))
} }
@ -142,3 +117,25 @@ function showBack(t, vm) {
t.button({className: "text", onClick: () => vm.back()}, "Change"), t.button({className: "text", onClick: () => vm.back()}, "Change"),
]); ]);
} }
function renderAction(t, a) {
let badgeUrl;
switch (a.kind) {
case "play-store": badgeUrl = "images/google-play-us.svg"; break;
case "fdroid": badgeUrl = "images/fdroid-badge.png"; break;
case "apple-app-store": badgeUrl = "images/app-store-us-alt.svg"; break;
case "flathub": badgeUrl = "images/flathub-badge.svg"; break;
}
return t.a({
href: a.url,
className: {
fullwidth: !badgeUrl,
primary: a.primary && !badgeUrl,
secondary: !a.primary && !badgeUrl,
badge: !!badgeUrl,
},
rel: "noopener noreferrer",
["aria-label"]: a.label,
onClick: () => a.activated()
}, badgeUrl ? t.img({src: badgeUrl}) : a.label);
}

View file

@ -40,44 +40,108 @@ export class ClientViewModel extends ViewModel {
_update() { _update() {
const matchingPlatforms = getMatchingPlatforms(this._client, this.platforms); const matchingPlatforms = getMatchingPlatforms(this._client, this.platforms);
const webPlatform = matchingPlatforms.find(p => isWebPlatform(p)); this._webPlatform = matchingPlatforms.find(p => isWebPlatform(p));
this._nativePlatform = matchingPlatforms.find(p => !isWebPlatform(p)); this._nativePlatform = matchingPlatforms.find(p => !isWebPlatform(p));
this._proposedPlatform = this.preferences.platform || this._nativePlatform || webPlatform; this._proposedPlatform = this.preferences.platform || this._nativePlatform || webPlatform;
this.actions = this._createActions(this._client, this._link, this._nativePlatform, webPlatform); this.openActions = this._createOpenActions();
this.installActions = this._createInstallActions();
this._clientCanIntercept = !!(this._nativePlatform && this._client.canInterceptMatrixToLinks(this._nativePlatform)); this._clientCanIntercept = !!(this._nativePlatform && this._client.canInterceptMatrixToLinks(this._nativePlatform));
this._showOpen = this.deepLink && !this._clientCanIntercept; this._showOpen = this.openActions.length && !this._clientCanIntercept;
}
// these are only shown in the open stage
_createOpenActions() {
const hasPreferredWebInstance = this.hasPreferredWebInstance;
let deepLinkLabel = "Continue";
if (hasPreferredWebInstance) {
if (this._proposedPlatform === this._nativePlatform) {
deepLinkLabel = "Open in app";
} else {
deepLinkLabel = `Open on ${this._client.getPreferredWebInstance(this._link)}`;
}
}
const actions = [];
actions.push({
label: deepLinkLabel,
url: this._client.getDeepLink(this._proposedPlatform, this._link),
primary: true,
activated: () => {
this._pickClient(this._client);
this.preferences.setClient(this._client.id, this._proposedPlatform);
// only show install screen if we tried to open a native deeplink
if (this._showOpen && this._proposedPlatform === this._nativePlatform) {
this._showOpen = false;
this.emitChange();
}
},
});
// show only if there is a preferred instance, and if we don't already link to it in the first button
if (hasPreferredWebInstance && this._webPlatform && this._proposedPlatform !== this._webPlatform) {
actions.push({
label: `Open on ${this._client.getPreferredWebInstance(this._link)}`,
url: this._client.getDeepLink(this._webPlatform, this._link),
kind: "open-in-web",
activated: () => {} // don't persist this choice as we don't persist the preferred web instance, it's in the url
});
}
return actions;
} }
// these are only shown in the install stage // these are only shown in the install stage
_createActions(client, link, nativePlatform, webPlatform) { _createInstallActions() {
let actions = []; let actions = [];
if (nativePlatform) { if (this._nativePlatform) {
const nativeActions = (client.getInstallLinks(nativePlatform) || []).map(installLink => { const nativeActions = (this._client.getInstallLinks(this._nativePlatform) || []).map(installLink => {
return { return {
label: installLink.getDescription(nativePlatform), label: installLink.getDescription(this._nativePlatform),
url: installLink.createInstallURL(link), url: installLink.createInstallURL(this._link),
kind: installLink.channelId, kind: installLink.channelId,
primary: true, primary: true,
activated: () => this.preferences.setClient(client.id, nativePlatform), activated: () => this.preferences.setClient(this._client.id, this._nativePlatform),
}; };
}); });
actions.push(...nativeActions); actions.push(...nativeActions);
} }
if (webPlatform) { if (this._webPlatform) {
const webDeepLink = client.getDeepLink(webPlatform, link); const webDeepLink = this._client.getDeepLink(this._webPlatform, this._link);
if (webDeepLink) { if (webDeepLink) {
const webLabel = this.hasPreferredWebInstance ?
`Open on ${this._client.getPreferredWebInstance(this._link)}` :
`Continue in your browser`;
actions.push({ actions.push({
label: `Continue in your browser`, label: webLabel,
url: webDeepLink, url: webDeepLink,
kind: "open-in-web", kind: "open-in-web",
activated: () => this.preferences.setClient(client.id, webPlatform), activated: () => {
if (!this.hasPreferredWebInstance) {
this.preferences.setClient(this._client.id, this._webPlatform);
}
},
}); });
} }
} }
return actions; return actions;
} }
get hasPreferredWebInstance() {
// also check there is a web platform that matches the platforms the user is on (mobile or desktop web)
return this._webPlatform && typeof this._client.getPreferredWebInstance(this._link) === "string";
}
get hostedByBannerLabel() {
const preferredWebInstance = this._client.getPreferredWebInstance(this._link);
if (this._webPlatform && preferredWebInstance) {
let label = preferredWebInstance;
const subDomainIdx = preferredWebInstance.lastIndexOf(".", preferredWebInstance.lastIndexOf("."));
if (subDomainIdx !== -1) {
label = preferredWebInstance.substr(preferredWebInstance.length - subDomainIdx + 1);
}
return `Hosted by ${label}`;
}
return;
}
get homepage() { get homepage() {
return this._client.homepage; return this._client.homepage;
} }
@ -145,26 +209,6 @@ export class ClientViewModel extends ViewModel {
return textPlatforms; return textPlatforms;
} }
get _deepLinkPlatform() {
// in install stage, always show the native link in the small "open it here" link, independent of preference.
return this._showOpen ? this._proposedPlatform : this._nativePlatform;
}
// both used for big "Continue" button in open stage,
// and for small "open it here" link in the install stage.
get deepLink() {
return this._client.getDeepLink(this._deepLinkPlatform, this._link);
}
deepLinkActivated() {
this._pickClient(this._client);
this.preferences.setClient(this._client.id, this._deepLinkPlatform);
if (this._showOpen) {
this._showOpen = false;
this.emitChange();
}
}
pick(clientListViewModel) { pick(clientListViewModel) {
this._clientListViewModel = clientListViewModel; this._clientListViewModel = clientListViewModel;
this.emitChange(); this.emitChange();