diff --git a/backend/src/s9pk/manifest.rs b/backend/src/s9pk/manifest.rs index 5f787554d..168cdc5dc 100644 --- a/backend/src/s9pk/manifest.rs +++ b/backend/src/s9pk/manifest.rs @@ -76,6 +76,9 @@ pub struct Manifest { pub dependencies: Dependencies, #[model] pub containers: Option, + + #[serde(default)] + pub replaces: Vec, } impl Manifest { diff --git a/backend/src/s9pk/reader.rs b/backend/src/s9pk/reader.rs index eefc4ae63..3d707bd93 100644 --- a/backend/src/s9pk/reader.rs +++ b/backend/src/s9pk/reader.rs @@ -24,6 +24,9 @@ use crate::s9pk::docker::DockerReader; use crate::util::Version; use crate::{Error, ResultExt}; +const MAX_REPLACES: usize = 10; +const MAX_TITLE_LEN: usize = 30; + #[pin_project::pin_project] #[derive(Debug)] pub struct ReadHandle<'a, R = File> { @@ -231,6 +234,35 @@ impl S9pkReader { &validated_image_ids, )?; + #[cfg(feature = "js_engine")] + if man.containers.is_some() + || matches!(man.main, crate::procedure::PackageProcedure::Script(_)) + { + return Err(Error::new( + eyre!("Right now we don't support the containers and the long running main"), + crate::ErrorKind::ValidateS9pk, + )); + } + + if man.replaces.len() >= MAX_REPLACES { + return Err(Error::new( + eyre!("Cannot have more than {MAX_REPLACES} replaces"), + crate::ErrorKind::ValidateS9pk, + )); + } + if let Some(too_big) = man.replaces.iter().find(|x| x.len() >= MAX_REPLACES) { + return Err(Error::new( + eyre!("We have found a replaces of ({too_big}) that exceeds the max length of {MAX_TITLE_LEN} "), + crate::ErrorKind::ValidateS9pk, + )); + } + if man.title.len() >= MAX_TITLE_LEN { + return Err(Error::new( + eyre!("Cannot have more than a length of {MAX_TITLE_LEN} for title"), + crate::ErrorKind::ValidateS9pk, + )); + } + if man.containers.is_some() && matches!(man.main, crate::procedure::PackageProcedure::Docker(_)) { diff --git a/frontend/projects/marketplace/package.json b/frontend/projects/marketplace/package.json index f7a8d21d9..15bbb2372 100644 --- a/frontend/projects/marketplace/package.json +++ b/frontend/projects/marketplace/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/marketplace", - "version": "0.3.8", + "version": "0.3.9", "peerDependencies": { "@angular/common": ">=13.2.0", "@angular/core": ">=13.2.0", diff --git a/frontend/projects/marketplace/src/pages/show/about/about.component.html b/frontend/projects/marketplace/src/pages/show/about/about.component.html index e5f4bdb48..bf5c70269 100644 --- a/frontend/projects/marketplace/src/pages/show/about/about.component.html +++ b/frontend/projects/marketplace/src/pages/show/about/about.component.html @@ -21,6 +21,6 @@ Description - {{ pkg.manifest.description.long }} +

{{ pkg.manifest.description.long }}

diff --git a/frontend/projects/marketplace/src/pages/show/additional/additional.component.html b/frontend/projects/marketplace/src/pages/show/additional/additional.component.html index c1e70f53c..3dc5c41e8 100644 --- a/frontend/projects/marketplace/src/pages/show/additional/additional.component.html +++ b/frontend/projects/marketplace/src/pages/show/additional/additional.component.html @@ -1,3 +1,24 @@ +
+ + View marketing website + + +
+ + +
+ Intended to replace +
    +
  • + {{ app }} +
  • +
+
+
+ Additional Info @@ -89,19 +110,6 @@ - - -

Marketing Site

-

{{ manifest['marketing-site'] || 'Not provided' }}

-
- -
diff --git a/frontend/projects/marketplace/src/pages/show/additional/additional.component.ts b/frontend/projects/marketplace/src/pages/show/additional/additional.component.ts index ba4c9d0d5..778ea6c54 100644 --- a/frontend/projects/marketplace/src/pages/show/additional/additional.component.ts +++ b/frontend/projects/marketplace/src/pages/show/additional/additional.component.ts @@ -18,6 +18,7 @@ import { } from '@start9labs/shared' import { MarketplacePkg } from '../../../types' import { AbstractMarketplaceService } from '../../../services/marketplace.service' +import { ActivatedRoute } from '@angular/router' @Component({ selector: 'marketplace-additional', @@ -31,12 +32,15 @@ export class AdditionalComponent { @Output() version = new EventEmitter() + readonly url = this.route.snapshot.queryParamMap.get('url') || undefined + constructor( private readonly alertCtrl: AlertController, private readonly modalCtrl: ModalController, private readonly emver: Emver, private readonly marketplaceService: AbstractMarketplaceService, private readonly toastCtrl: ToastController, + private readonly route: ActivatedRoute, ) {} async copy(address: string): Promise { @@ -84,6 +88,7 @@ export class AdditionalComponent { const content = this.marketplaceService.fetchStatic$( this.pkg.manifest.id, title, + this.url, ) const modal = await this.modalCtrl.create({ diff --git a/frontend/projects/marketplace/src/types.ts b/frontend/projects/marketplace/src/types.ts index 5ab4f2a68..91bc44495 100644 --- a/frontend/projects/marketplace/src/types.ts +++ b/frontend/projects/marketplace/src/types.ts @@ -47,6 +47,7 @@ export interface MarketplaceManifest { short: string long: string } + replaces?: string[] 'release-notes': string license: string // type of license 'wrapper-repo': Url diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html index ee60aeec0..9a055faa7 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-additional/app-show-additional.component.html @@ -36,6 +36,19 @@ + + +

Marketing Site

+

{{ manifest['marketing-site'] || 'Not provided' }}

+
+ +
@@ -77,6 +90,19 @@ + + +

Donation Link

+

{{ manifest['donation-url'] || 'Not provided' }}

+
+ +
diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts index e1317d1fe..eeb00b435 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-buttons.pipe.ts @@ -1,7 +1,6 @@ -import { Inject, Pipe, PipeTransform } from '@angular/core' +import { Pipe, PipeTransform } from '@angular/core' import { ActivatedRoute } from '@angular/router' -import { DOCUMENT } from '@angular/common' -import { AlertController, ModalController, NavController } from '@ionic/angular' +import { ModalController, NavController } from '@ionic/angular' import { MarkdownComponent } from '@start9labs/shared' import { DataModel, @@ -26,8 +25,6 @@ export interface Button { }) export class ToButtonsPipe implements PipeTransform { constructor( - @Inject(DOCUMENT) private readonly document: Document, - private readonly alertCtrl: AlertController, private readonly route: ActivatedRoute, private readonly navCtrl: NavController, private readonly modalCtrl: ModalController, @@ -97,13 +94,6 @@ export class ToButtonsPipe implements PipeTransform { }, // view in marketplace this.viewInMarketplaceButton(pkg), - // donate - { - action: () => this.donate(pkg), - title: 'Donate', - description: `Support ${pkgTitle}`, - icon: 'logo-bitcoin', - }, ] } @@ -148,17 +138,4 @@ export class ToButtonsPipe implements PipeTransform { return button } - - private async donate({ manifest }: PackageDataEntry): Promise { - const url = manifest['donation-url'] - if (url) { - this.document.defaultView?.open(url, '_blank', 'noreferrer') - } else { - const alert = await this.alertCtrl.create({ - header: 'Not Accepting Donations', - message: `The developers of ${manifest.title} have not provided a donation URL. Please contact them directly if you insist on giving them money.`, - }) - await alert.present() - } - } } diff --git a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts index 7b5463fb8..28cebe402 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts +++ b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts @@ -519,6 +519,19 @@ export class ServerShowPage { detail: true, disabled$: of(false), }, + { + title: 'Donate to Start9', + description: `Support embassyOS development`, + icon: 'logo-bitcoin', + action: () => + this.document.defaultView?.open( + 'https://donate.start9.com', + '_blank', + 'noreferrer', + ), + detail: true, + disabled$: of(false), + }, ], Power: [ { diff --git a/frontend/projects/ui/src/app/services/api/api.fixures.ts b/frontend/projects/ui/src/app/services/api/api.fixures.ts index e9a7532b2..fca5a6d6e 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -47,6 +47,7 @@ export module Mock { short: 'A Bitcoin full node by Bitcoin Core.', long: 'Bitcoin is a decentralized consensus protocol and settlement network.', }, + replaces: ['banks', 'governments'], 'release-notes': 'Taproot, Schnorr, and more.', assets: { icon: 'icon.png',