adjust service marketplace button for installation source relevance (#1571)

* adjust service marketplace button for installation source relevance

* cleanup

* show marketplace name instead of url; cleanup from PR feedback

* fix spacing

* further cleanup
This commit is contained in:
Lucy C
2022-06-27 10:09:27 -06:00
committed by GitHub
parent 83755e93dc
commit 31952afe1e
7 changed files with 134 additions and 26 deletions

View File

@@ -36,3 +36,16 @@ export function debounce(delay: number = 300): MethodDecorator {
return descriptor
}
}
export function removeTrailingSlash(word: string): string {
return word.replace(/\/+$/, '')
}
export function isValidHttpUrl(string: string): boolean {
try {
const _ = new URL(string)
return true
} catch (_) {
return false
}
}

View File

@@ -111,3 +111,11 @@ ion-modal::part(content) {
.montserrat {
font-family: 'Montserrat', sans-serif !important;
}
.color-success-shade {
color: var(--ion-color-success-shade)
}
.color-primary-shade {
color: var(--ion-color-primary-shade)
}

View File

@@ -24,7 +24,9 @@
[dependencies]="dependencies"
></app-show-dependencies>
<!-- ** menu ** -->
<app-show-menu [buttons]="pkg | toButtons"></app-show-menu>
<app-show-menu
[buttons]="pkg | toButtons: (currentMarketplace$ | async): (altMarketplaceData$ | async)"
></app-show-menu>
</ng-container>
</ion-item-group>

View File

@@ -1,10 +1,11 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'
import { NavController } from '@ionic/angular'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
import {
PackageDataEntry,
PackageMainStatus,
PackageState,
UIMarketplaceData,
} from 'src/app/services/patch-db/data-model'
import {
PackageStatus,
@@ -17,6 +18,12 @@ import {
import { map, startWith, filter } from 'rxjs/operators'
import { ActivatedRoute } from '@angular/router'
import { getPkgId } from '@start9labs/shared'
import { MarketplaceService } from 'src/app/services/marketplace.service'
import {
AbstractMarketplaceService,
Marketplace,
} from '@start9labs/marketplace'
import { Observable } from 'rxjs'
const STATES = [
PackageState.Installing,
@@ -53,6 +60,12 @@ export class AppShowPage {
),
)
readonly currentMarketplace$: Observable<Marketplace> =
this.marketplaceService.getMarketplace()
readonly altMarketplaceData$: Observable<UIMarketplaceData | undefined> =
this.marketplaceService.getAltMarketplace()
readonly connectionFailure$ = this.connectionService
.watchFailure$()
.pipe(map(failure => failure !== ConnectionFailure.None))
@@ -62,7 +75,9 @@ export class AppShowPage {
private readonly navCtrl: NavController,
private readonly patch: PatchDbService,
private readonly connectionService: ConnectionService,
) { }
@Inject(AbstractMarketplaceService)
private readonly marketplaceService: MarketplaceService,
) {}
isInstalled(
{ state }: PackageDataEntry,

View File

@@ -2,12 +2,19 @@ import { Inject, Pipe, PipeTransform } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { DOCUMENT } from '@angular/common'
import { AlertController, ModalController, NavController } from '@ionic/angular'
import { MarkdownComponent } from '@start9labs/shared'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import {
isValidHttpUrl,
MarkdownComponent,
removeTrailingSlash,
} from '@start9labs/shared'
import {
PackageDataEntry,
UIMarketplaceData,
} from 'src/app/services/patch-db/data-model'
import { ModalService } from 'src/app/services/modal.service'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { from } from 'rxjs'
import { Marketplace } from '@start9labs/marketplace'
export interface Button {
title: string
description: string
@@ -30,7 +37,11 @@ export class ToButtonsPipe implements PipeTransform {
private readonly apiService: ApiService,
) {}
transform(pkg: PackageDataEntry): Button[] {
transform(
pkg: PackageDataEntry,
currentMarketplace: Marketplace | null,
altMarketplaces: UIMarketplaceData | null | undefined,
): Button[] {
const pkgTitle = pkg.manifest.title
return [
@@ -87,7 +98,7 @@ export class ToButtonsPipe implements PipeTransform {
icon: 'receipt-outline',
},
// view in marketplace
this.viewInMarketplaceButton(pkg),
this.viewInMarketplaceButton(pkg, currentMarketplace, altMarketplaces),
// donate
{
action: () => this.donate(pkg),
@@ -112,24 +123,54 @@ export class ToButtonsPipe implements PipeTransform {
await modal.present()
}
private viewInMarketplaceButton(pkg: PackageDataEntry): Button {
return pkg.installed?.['marketplace-url']
? {
private viewInMarketplaceButton(
pkg: PackageDataEntry,
currentMarketplace: Marketplace | null,
altMarketplaces: UIMarketplaceData | null | undefined,
): Button {
const pkgMarketplace = pkg.installed?.['marketplace-url']
// default button if package marketplace and current marketplace are the same
let button: Button = {
title: 'Marketplace',
icon: 'storefront-outline',
action: () =>
this.navCtrl.navigateForward([`marketplace/${pkg.manifest.id}`]),
title: 'Marketplace',
disabled: false,
description: 'View service in marketplace',
icon: 'storefront-outline',
}
: {
disabled: true,
action: () => {},
title: 'Marketplace',
description:
'This package has been side-loaded and is not available in the Start9 Marketplace',
icon: 'storefront-outline',
if (!pkgMarketplace) {
button.disabled = true
button.description = 'This package was not installed from a marketplace.'
button.action = () => {}
} else if (
pkgMarketplace &&
currentMarketplace &&
removeTrailingSlash(pkgMarketplace) !==
removeTrailingSlash(currentMarketplace.url)
) {
// attempt to get name for pkg marketplace
let pkgTitle = removeTrailingSlash(pkgMarketplace)
if (altMarketplaces) {
const nameOptions = Object.values(
altMarketplaces['known-hosts'],
).filter(m => m.url === pkgTitle)
if (nameOptions.length) {
// if multiple of the same url exist, they will have the same name, so fine to grab first
pkgTitle = nameOptions[0].name
}
}
let marketplaceTitle = removeTrailingSlash(currentMarketplace.url)
// if we found a name for the pkg marketplace, use the name of the currently connected marketplace
if (!isValidHttpUrl(pkgTitle)) {
marketplaceTitle = currentMarketplace.name
}
button.action = () =>
this.differentMarketplaceAction(pkgTitle, marketplaceTitle)
button.description = 'Service was installed from a different marketplace'
}
return button
}
private async donate({ manifest }: PackageDataEntry): Promise<void> {
const url = manifest['donation-url']
@@ -143,4 +184,28 @@ export class ToButtonsPipe implements PipeTransform {
await alert.present()
}
}
private async differentMarketplaceAction(pkgM: string, currentM: string) {
const alert = await this.alertCtrl.create({
header: 'Marketplace Conflict',
message: `This service was installed from:
<br><br>
<span class="courier-new color-success-shade">${pkgM}</span>
<br><br>but you are currently connected to:<br><br>
<span class="courier-new color-primary-shade">${currentM}</span>
<br><br>
To view the marketplace listing for this service, visit your Marketplace Settings and change marketplaces.`,
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Go to Settings',
handler: () => this.navCtrl.navigateForward(['embassy/marketplaces']),
cssClass: 'enter-click',
},
],
})
await alert.present()
}
}

View File

@@ -92,6 +92,10 @@ export class MarketplaceService extends AbstractMarketplaceService {
return this.marketplace$
}
getAltMarketplace(): Observable<UIMarketplaceData | undefined> {
return this.altMarketplaceData$
}
getCategories(): Observable<string[]> {
return this.categories$
}

View File

@@ -1,6 +1,7 @@
export async function copyToClipboard (str: string): Promise<boolean> {
export async function copyToClipboard(str: string): Promise<boolean> {
if (window.isSecureContext) {
return navigator.clipboard.writeText(str)
return navigator.clipboard
.writeText(str)
.then(() => {
return true
})