diff --git a/css/main.css b/css/main.css index 5c2196a..16048ce 100644 --- a/css/main.css +++ b/css/main.css @@ -120,8 +120,23 @@ textarea { padding: 0; } -a { +a, button.text { color: var(--link); + text-decoration: underline; +} + +button.text { + background: none; + border: none; + font-style: normal; + font-weight: normal; + font-size: inherit; + padding: 8px 0; + margin: -8px 0; +} + +button.text:hover { + cursor: pointer; } .ClientListView ul { @@ -152,4 +167,29 @@ a { .ClientView .icon.element-io { background-image: url('../images/client-icons/element.svg'); +} + +button.primary, a.primary { + background: var(--link); + color: var(--background); + border-radius: 32px; + text-decoration: none; + font-weight: bold; +} + +.ClientView .actions a { + display: block; + text-align: center; + padding: 8px; + margin: 8px; +} + +.ClientView .actions a.badge { + display: inline-block; + height: 40px; + margin: 8px 16px 8px 0; +} + +.ClientView .actions img { + height: 100%; } \ No newline at end of file diff --git a/images/app-store-us-alt.svg b/images/app-store-us-alt.svg new file mode 100644 index 0000000..83437ba --- /dev/null +++ b/images/app-store-us-alt.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/images/fdroid-badge.png b/images/fdroid-badge.png new file mode 100644 index 0000000..7c8c3c5 Binary files /dev/null and b/images/fdroid-badge.png differ diff --git a/images/google-play-us.svg b/images/google-play-us.svg new file mode 100644 index 0000000..888691a --- /dev/null +++ b/images/google-play-us.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/client/ClientListView.js b/src/client/ClientListView.js index ef3ae16..8a62cea 100644 --- a/src/client/ClientListView.js +++ b/src/client/ClientListView.js @@ -22,7 +22,7 @@ export class ClientListView extends TemplateView { const clients = vm.clients.map(clientViewModel => t.view(new ClientView(clientViewModel))); return t.div({className: "ClientListView"}, [ t.h3("You need an app to continue"), - t.ul({className: "ClientListView"}, clients) + t.div({className: "ClientListView"}, clients) ]); } } diff --git a/src/client/ClientListViewModel.js b/src/client/ClientListViewModel.js index c998075..6cc1d47 100644 --- a/src/client/ClientListViewModel.js +++ b/src/client/ClientListViewModel.js @@ -22,6 +22,6 @@ export class ClientListViewModel extends ViewModel { constructor(options) { super(options); const {clients, link} = options; - this.clients = clients.map(client => new ClientViewModel(this.childOptions({client, link}))); + this.clients = clients.map(client => new ClientViewModel(this.childOptions({client, link, showAcceptAnyway: true}))); } } diff --git a/src/client/ClientView.js b/src/client/ClientView.js index d5c789e..3bf3784 100644 --- a/src/client/ClientView.js +++ b/src/client/ClientView.js @@ -18,7 +18,7 @@ import {TemplateView} from "../utils/TemplateView.js"; export class ClientView extends TemplateView { render(t, vm) { - return t.li({className: "ClientView"}, [ + return t.div({className: "ClientView"}, [ t.div({className: "header"}, [ t.div({className: "description"}, [ t.h3(vm.name), @@ -27,7 +27,23 @@ export class ClientView extends TemplateView { t.div({className: `icon ${vm.clientId}`}) ]), t.div({className: "actions"}, vm.actions.map(a => { - return t.a({href: a.url, className: a.kind, rel: "noopener noreferrer", onClick: () => a.activated()}, a.label); + 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; + } + return t.a({ + href: a.url, + className: { + 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); })) ]); } diff --git a/src/client/ClientViewModel.js b/src/client/ClientViewModel.js index 1ad7c23..683c6f4 100644 --- a/src/client/ClientViewModel.js +++ b/src/client/ClientViewModel.js @@ -40,7 +40,8 @@ export class ClientViewModel extends ViewModel { label: installLink.description, url: installLink.createInstallURL(link), kind: installLink.channelId, - activated() {}, + primary: true, + activated: () => this.preferences.setClient(client.id, nativePlatform), }; }); actions.push(...nativeActions); @@ -50,7 +51,7 @@ export class ClientViewModel extends ViewModel { label: `Or open in ${client.getName(webPlatform)}`, url: client.getDeepLink(webPlatform, link), kind: "open-in-web", - activated() {}, + activated: () => this.preferences.setClient(client.id, webPlatform), }); } return actions; diff --git a/src/preview/PreviewView.js b/src/preview/PreviewView.js index f4c217b..ca76446 100644 --- a/src/preview/PreviewView.js +++ b/src/preview/PreviewView.js @@ -16,6 +16,7 @@ limitations under the License. import {TemplateView} from "../utils/TemplateView.js"; import {ClientListView} from "../client/ClientListView.js"; +import {ClientView} from "../client/ClientView.js"; export class PreviewView extends TemplateView { render(t, vm) { @@ -31,8 +32,18 @@ export class PreviewView extends TemplateView { ]), ]), t.p({hidden: vm => !!vm.clientsViewModel}, t.button({onClick: () => vm.accept()}, vm => vm.acceptLabel)), - t.mapView(vm => vm.clientsViewModel, vm => vm ? new ClientListView(vm) : null) + t.mapView(vm => vm.clientsViewModel, childVM => childVM ? new ClientListView(childVM) : null), + t.mapView(vm => vm.missingClientViewModel, childVM => childVM ? new MissingClientView(childVM) : null), ]) ]); } +} + +class MissingClientView extends TemplateView { + render(t, vm) { + return t.div({className: "MissingClientView"}, [ + t.h3(`It looks like you don't have ${vm.name} installed.`), + t.view(new ClientView(vm)), + ]); + } } \ No newline at end of file diff --git a/src/preview/PreviewViewModel.js b/src/preview/PreviewViewModel.js index e232ca4..919e01b 100644 --- a/src/preview/PreviewViewModel.js +++ b/src/preview/PreviewViewModel.js @@ -88,6 +88,11 @@ export class PreviewViewModel extends ViewModel { const deepLink = this._preferredClient.getDeepLink(this._preferredPlatform, this._link); this.openLink(deepLink); // show "looks like you don't have the native app installed" + const protocol = new URL(deepLink).protocol; + const isWebProtocol = protocol === "http:" || protocol === "https:"; + if (!isWebProtocol) { + this.missingClientViewModel = new ClientViewModel(this.childOptions({client: this._preferredClient, link: this._link})); + } } else { this.acceptInstructions = this._preferredClient.getLinkInstructions(this._preferredPlatform, this._link); }