diff --git a/src/clients/Element.ts b/src/clients/Element.ts index 369c0e9..2b9fb8d 100644 --- a/src/clients/Element.ts +++ b/src/clients/Element.ts @@ -20,7 +20,9 @@ import { ClientKind, ClientId, Platform, - StoreDistribution, + AppleStoreLink, + PlayStoreLink, + FDroidLink } from './types'; import { LinkKind } from '../parser/types'; import logo from '../imgs/element.svg'; @@ -61,25 +63,9 @@ export const Element: LinkedClient = { }, linkSupport: () => true, installLinks: [ - new StoreDistribution( - 'App Store', - Platform.iOS, - 'https://apps.apple.com/app/vector/id1083446067', - false - ), - new StoreDistribution( - 'Google Play', - Platform.Android, - 'https://play.google.com/store/apps/details?id=im.vector.app', - true - ), - new StoreDistribution( - 'F-Droid', - Platform.Android, - 'https://f-droid.org/fr/packages/im.vector.app/', - false - ), - // TODO desktop clients? + new AppleStoreLink("vector", "id1083446067"), + new PlayStoreLink("im.vector.app"), + new FDroidLink("im.vector.app"), ], }; diff --git a/src/clients/types.ts b/src/clients/types.ts index 8e41546..7a2f8c4 100644 --- a/src/clients/types.ts +++ b/src/clients/types.ts @@ -57,22 +57,73 @@ export enum ClientId { * Define a native distribution channel for a client. * E.g App store for apple, PlayStore or F-Droid for Android */ -export class StoreDistribution { - public name: string; - public platform: Platform; - public download: string; - public supportReferrer: boolean; +export interface InstallLink { + createInstallURL(deepLink: SafeLink) : string; + //get buttonCSSClass(): string; + platform: Platform; + // in AppleStoreLink, we can set the cookie here + // onInstallChosen(deepLink: SafeLink); + channelId: string; + description: string; +} - constructor( - name: string, - platform: Platform, - download: string, - supportReferrer: boolean - ) { - this.name = name; - this.platform = platform; - this.download = download; - this.supportReferrer = supportReferrer; +export class AppleStoreLink implements InstallLink { + constructor(private org: string, private appId: string) {} + + createInstallURL(deepLink: SafeLink) : string { + return `https://apps.apple.com/app/${encodeURIComponent(this.org)}/${encodeURIComponent(this.appId)}`; + } + + get platform() : Platform { + return Platform.iOS; + } + + get channelId(): string { + return "apple-app-store"; + } + + get description() { + return "Download on the App Store"; + } +} + +export class PlayStoreLink implements InstallLink { + constructor(private appId: string) {} + + createInstallURL(deepLink: SafeLink) : string { + return `https://play.google.com/store/apps/details?id=${encodeURIComponent(this.appId)}&referrer=${encodeURIComponent(deepLink.originalLink)}`; + } + + get platform() : Platform { + return Platform.Android; + } + + get channelId(): string { + return "play-store"; + } + + get description() { + return "Get it on Google Play"; + } +} + +export class FDroidLink implements InstallLink { + constructor(private appId: string) {} + + createInstallURL(deepLink: SafeLink) : string { + return `https://f-droid.org/packages/${encodeURIComponent(this.appId)}`; + } + + get platform() : Platform { + return Platform.Android; + } + + get channelId(): string { + return "fdroid"; + } + + get description() { + return "Get it on F-Droid"; } } @@ -90,7 +141,7 @@ export interface ClientDescription { clientId: ClientId; experimental: boolean; linkSupport: (link: SafeLink) => boolean; - installLinks: StoreDistribution[]; + installLinks: InstallLink[]; } /* diff --git a/src/components/ClientTile.scss b/src/components/ClientTile.scss index 6bd4dfb..a697aea 100644 --- a/src/components/ClientTile.scss +++ b/src/components/ClientTile.scss @@ -67,6 +67,15 @@ limitations under the License. &:hover { background-color: $app-background; } + + .installLink { + display: inline-block; + height: 40px; + margin: 8px 16px 8px 0; + img { + height: 100%; + } + } } .clientTileLink { diff --git a/src/components/ClientTile.tsx b/src/components/ClientTile.tsx index 7076bc2..5ec1311 100644 --- a/src/components/ClientTile.tsx +++ b/src/components/ClientTile.tsx @@ -23,6 +23,10 @@ import { SafeLink } from '../parser/types'; import Tile from './Tile'; import Button from './Button'; +import appStoreBadge from '../imgs/app-store-us-alt.svg'; +import playStoreBadge from '../imgs/google-play-us.svg'; +import fdroidBadge from '../imgs/fdroid-badge.png'; + import './ClientTile.scss'; interface IProps { @@ -30,6 +34,16 @@ interface IProps { link: SafeLink; } +interface IInstallBadgeImages { + [index: string]: string; +} + +const installBadgeImages : IInstallBadgeImages = { + "fdroid": fdroidBadge, + "apple-app-store": appStoreBadge, + "play-store": playStoreBadge +}; + const ClientTile: React.FC = ({ client, link }: IProps) => { const inviteLine = client.kind === ClientKind.TEXT_CLIENT ? ( @@ -43,47 +57,32 @@ const ClientTile: React.FC = ({ client, link }: IProps) => { }); let inviteButton: JSX.Element = <>; - let hasNativeClient = false; - let installButton = undefined; - if (client.kind === ClientKind.LINKED_CLIENT) { - const availableClients = client.installLinks.filter((distrib) => { - if ((uaResults as any).ios) { - return distrib.platform == Platform.iOS; - } else if ((uaResults as any).android) { - return distrib.platform == Platform.Android; - } else { - return false; - } - }); - hasNativeClient = availableClients.length > 0; - if (hasNativeClient) { - inviteButton = ( - - ); + const matchingInstallLinks = client.installLinks.filter((installLink) => { + if ((uaResults as any).ios) { + return installLink.platform === Platform.iOS; + } else if ((uaResults as any).android) { + return installLink.platform === Platform.Android; } else { - inviteButton = ; + return false; } + }); + const hasNativeClient = matchingInstallLinks.length > 0; + let installButtons = undefined; + if (matchingInstallLinks.length) { + installButtons =

{matchingInstallLinks.map((installLink) => { + return + {installLink.description} + ; + })}

; + } - installButton = availableClients.map((distrib) => ( - - )); + if (client.kind === ClientKind.LINKED_CLIENT) { + inviteButton = ; } else { const copyString = client.copyString(link); if (copyString !== '') { @@ -104,8 +103,8 @@ const ClientTile: React.FC = ({ client, link }: IProps) => {

{client.name}

{client.description}

+ {installButtons} {inviteLine} - {hasNativeClient && installButton} {inviteButton}
diff --git a/src/imgs/app-store-us-alt.svg b/src/imgs/app-store-us-alt.svg new file mode 100644 index 0000000..83437ba --- /dev/null +++ b/src/imgs/app-store-us-alt.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/imgs/fdroid-badge.png b/src/imgs/fdroid-badge.png new file mode 100644 index 0000000..7c8c3c5 Binary files /dev/null and b/src/imgs/fdroid-badge.png differ diff --git a/src/imgs/google-play-us.svg b/src/imgs/google-play-us.svg new file mode 100644 index 0000000..888691a --- /dev/null +++ b/src/imgs/google-play-us.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file