add app store install badges

This commit is contained in:
Bruno Windels 2020-11-23 18:23:23 +01:00
parent c78a91ea46
commit d484a9a423
7 changed files with 168 additions and 75 deletions

View File

@ -20,7 +20,9 @@ import {
ClientKind, ClientKind,
ClientId, ClientId,
Platform, Platform,
StoreDistribution, AppleStoreLink,
PlayStoreLink,
FDroidLink
} from './types'; } from './types';
import { LinkKind } from '../parser/types'; import { LinkKind } from '../parser/types';
import logo from '../imgs/element.svg'; import logo from '../imgs/element.svg';
@ -61,25 +63,9 @@ export const Element: LinkedClient = {
}, },
linkSupport: () => true, linkSupport: () => true,
installLinks: [ installLinks: [
new StoreDistribution( new AppleStoreLink("vector", "id1083446067"),
'App Store', new PlayStoreLink("im.vector.app"),
Platform.iOS, new FDroidLink("im.vector.app"),
'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?
], ],
}; };

View File

@ -57,22 +57,73 @@ export enum ClientId {
* Define a native distribution channel for a client. * Define a native distribution channel for a client.
* E.g App store for apple, PlayStore or F-Droid for Android * E.g App store for apple, PlayStore or F-Droid for Android
*/ */
export class StoreDistribution { export interface InstallLink {
public name: string; createInstallURL(deepLink: SafeLink) : string;
public platform: Platform; //get buttonCSSClass(): string;
public download: string; platform: Platform;
public supportReferrer: boolean; // in AppleStoreLink, we can set the cookie here
// onInstallChosen(deepLink: SafeLink);
channelId: string;
description: string;
}
constructor( export class AppleStoreLink implements InstallLink {
name: string, constructor(private org: string, private appId: string) {}
platform: Platform,
download: string, createInstallURL(deepLink: SafeLink) : string {
supportReferrer: boolean return `https://apps.apple.com/app/${encodeURIComponent(this.org)}/${encodeURIComponent(this.appId)}`;
) { }
this.name = name;
this.platform = platform; get platform() : Platform {
this.download = download; return Platform.iOS;
this.supportReferrer = supportReferrer; }
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; clientId: ClientId;
experimental: boolean; experimental: boolean;
linkSupport: (link: SafeLink) => boolean; linkSupport: (link: SafeLink) => boolean;
installLinks: StoreDistribution[]; installLinks: InstallLink[];
} }
/* /*

View File

@ -67,6 +67,15 @@ limitations under the License.
&:hover { &:hover {
background-color: $app-background; background-color: $app-background;
} }
.installLink {
display: inline-block;
height: 40px;
margin: 8px 16px 8px 0;
img {
height: 100%;
}
}
} }
.clientTileLink { .clientTileLink {

View File

@ -23,6 +23,10 @@ import { SafeLink } from '../parser/types';
import Tile from './Tile'; import Tile from './Tile';
import Button from './Button'; 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'; import './ClientTile.scss';
interface IProps { interface IProps {
@ -30,6 +34,16 @@ interface IProps {
link: SafeLink; link: SafeLink;
} }
interface IInstallBadgeImages {
[index: string]: string;
}
const installBadgeImages : IInstallBadgeImages = {
"fdroid": fdroidBadge,
"apple-app-store": appStoreBadge,
"play-store": playStoreBadge
};
const ClientTile: React.FC<IProps> = ({ client, link }: IProps) => { const ClientTile: React.FC<IProps> = ({ client, link }: IProps) => {
const inviteLine = const inviteLine =
client.kind === ClientKind.TEXT_CLIENT ? ( client.kind === ClientKind.TEXT_CLIENT ? (
@ -43,47 +57,32 @@ const ClientTile: React.FC<IProps> = ({ client, link }: IProps) => {
}); });
let inviteButton: JSX.Element = <></>; let inviteButton: JSX.Element = <></>;
let hasNativeClient = false; const matchingInstallLinks = client.installLinks.filter((installLink) => {
let installButton = undefined; if ((uaResults as any).ios) {
if (client.kind === ClientKind.LINKED_CLIENT) { return installLink.platform === Platform.iOS;
const availableClients = client.installLinks.filter((distrib) => { } else if ((uaResults as any).android) {
if ((uaResults as any).ios) { return installLink.platform === Platform.Android;
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 = (
<Button
onClick={() => window.open('matrix://' + link.originalLink)}
>
Accept invite
</Button>
);
} else { } else {
inviteButton = <Button>Accept invite</Button>; return false;
} }
});
const hasNativeClient = matchingInstallLinks.length > 0;
let installButtons = undefined;
if (matchingInstallLinks.length) {
installButtons = <p>{matchingInstallLinks.map((installLink) => {
return <a
rel="noopener noreferrer"
key={installLink.channelId}
href={installLink.createInstallURL(link)}
className="installLink"
target="_blank">
<img src={installBadgeImages[installLink.channelId]} alt={installLink.description} />
</a>;
})}</p>;
}
installButton = availableClients.map((distrib) => ( if (client.kind === ClientKind.LINKED_CLIENT) {
<Button inviteButton = <Button>Accept invite</Button>;
onClick={() =>
window.open(
distrib.supportReferrer
? distrib.download +
'&referrer=' +
link.originalLink
: distrib.download,
'_blank'
)
}
>
Get it on {distrib.name}
</Button>
));
} else { } else {
const copyString = client.copyString(link); const copyString = client.copyString(link);
if (copyString !== '') { if (copyString !== '') {
@ -104,8 +103,8 @@ const ClientTile: React.FC<IProps> = ({ client, link }: IProps) => {
<div> <div>
<h1>{client.name}</h1> <h1>{client.name}</h1>
<p>{client.description}</p> <p>{client.description}</p>
{installButtons}
{inviteLine} {inviteLine}
{hasNativeClient && installButton}
{inviteButton} {inviteButton}
</div> </div>
</Tile> </Tile>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

BIN
src/imgs/fdroid-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB