also render steps on open stage of client view as actions
This commit is contained in:
parent
28fb6dfe9d
commit
cd4f62d178
2 changed files with 103 additions and 62 deletions
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue