mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
show available marketplace updates in menu (#1613)
* show service updates in menu
This commit is contained in:
@@ -7,5 +7,7 @@
|
|||||||
(click)="switchCategory(cat)"
|
(click)="switchCategory(cat)"
|
||||||
>
|
>
|
||||||
{{ cat }}
|
{{ cat }}
|
||||||
<span *ngIf="cat === 'updates'"> ({{ updatesAvailable }}) </span>
|
<span *ngIf="cat === 'updates' && updatesAvailable">
|
||||||
|
({{ updatesAvailable }})
|
||||||
|
</span>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export class CategoriesComponent {
|
|||||||
category = ''
|
category = ''
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
updatesAvailable? = 0
|
updatesAvailable = 0
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
readonly categoryChange = new EventEmitter<string>()
|
readonly categoryChange = new EventEmitter<string>()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export abstract class AbstractMarketplaceService {
|
|||||||
|
|
||||||
abstract getReleaseNotes(id: string): Observable<Record<string, string>>
|
abstract getReleaseNotes(id: string): Observable<Record<string, string>>
|
||||||
|
|
||||||
abstract getCategories(): Observable<string[]>
|
abstract getCategories(): Observable<Set<string>>
|
||||||
|
|
||||||
abstract getPackages(): Observable<MarketplacePkg[]>
|
abstract getPackages(): Observable<MarketplacePkg[]>
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,12 @@ import { GlobalErrorHandler } from './services/global-error-handler.service'
|
|||||||
import { AuthService } from './services/auth.service'
|
import { AuthService } from './services/auth.service'
|
||||||
import { LocalStorageService } from './services/local-storage.service'
|
import { LocalStorageService } from './services/local-storage.service'
|
||||||
import { DataModel } from './services/patch-db/data-model'
|
import { DataModel } from './services/patch-db/data-model'
|
||||||
|
import { FilterPackagesPipe } from '../../../marketplace/src/pipes/filter-packages.pipe'
|
||||||
|
|
||||||
const { useMocks } = require('../../../../config.json') as WorkspaceConfig
|
const { useMocks } = require('../../../../config.json') as WorkspaceConfig
|
||||||
|
|
||||||
export const APP_PROVIDERS: Provider[] = [
|
export const APP_PROVIDERS: Provider[] = [
|
||||||
|
FilterPackagesPipe,
|
||||||
FormBuilder,
|
FormBuilder,
|
||||||
IonNav,
|
IonNav,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Inject, Injectable } from '@angular/core'
|
||||||
import { ModalController } from '@ionic/angular'
|
import { ModalController } from '@ionic/angular'
|
||||||
import { Observable, of } from 'rxjs'
|
import { Observable, of } from 'rxjs'
|
||||||
import { filter, share, switchMap, take, tap } from 'rxjs/operators'
|
import { filter, share, switchMap, take, tap } from 'rxjs/operators'
|
||||||
@@ -11,6 +11,8 @@ import { OSWelcomePage } from 'src/app/modals/os-welcome/os-welcome.page'
|
|||||||
import { ConfigService } from 'src/app/services/config.service'
|
import { ConfigService } from 'src/app/services/config.service'
|
||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { PatchMonitorService } from './patch-monitor.service'
|
import { PatchMonitorService } from './patch-monitor.service'
|
||||||
|
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||||
|
import { AbstractMarketplaceService } from '../../../../../../marketplace/src/services/marketplace.service'
|
||||||
|
|
||||||
// Get data from PatchDb after is starts and act upon it
|
// Get data from PatchDb after is starts and act upon it
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@@ -24,8 +26,8 @@ export class PatchDataService extends Observable<DataModel | null> {
|
|||||||
filter(obj => !isEmptyObject(obj)),
|
filter(obj => !isEmptyObject(obj)),
|
||||||
take(1),
|
take(1),
|
||||||
tap(({ ui }) => {
|
tap(({ ui }) => {
|
||||||
// check for updates to EOS
|
// check for updates to EOS and services
|
||||||
this.checkForEosUpdate(ui)
|
this.checkForUpdates(ui)
|
||||||
// show eos welcome message
|
// show eos welcome message
|
||||||
this.showEosWelcome(ui['ack-welcome'])
|
this.showEosWelcome(ui['ack-welcome'])
|
||||||
}),
|
}),
|
||||||
@@ -42,13 +44,17 @@ export class PatchDataService extends Observable<DataModel | null> {
|
|||||||
private readonly config: ConfigService,
|
private readonly config: ConfigService,
|
||||||
private readonly modalCtrl: ModalController,
|
private readonly modalCtrl: ModalController,
|
||||||
private readonly embassyApi: ApiService,
|
private readonly embassyApi: ApiService,
|
||||||
|
@Inject(AbstractMarketplaceService)
|
||||||
|
private readonly marketplaceService: MarketplaceService,
|
||||||
) {
|
) {
|
||||||
super(subscriber => this.stream$.subscribe(subscriber))
|
super(subscriber => this.stream$.subscribe(subscriber))
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkForEosUpdate(ui: UIData): void {
|
private checkForUpdates(ui: UIData): void {
|
||||||
if (ui['auto-check-updates'] !== false) {
|
if (ui['auto-check-updates'] !== false) {
|
||||||
this.eosService.getEOS()
|
this.eosService.getEOS()
|
||||||
|
this.marketplaceService.getPackages().pipe(take(1)).subscribe()
|
||||||
|
this.marketplaceService.getCategories().pipe(take(1)).subscribe()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import {
|
import { ToastController, ToastOptions } from '@ionic/angular'
|
||||||
LoadingController,
|
import { EMPTY, Observable, ObservableInput } from 'rxjs'
|
||||||
ToastController,
|
|
||||||
ToastOptions,
|
|
||||||
} from '@ionic/angular'
|
|
||||||
import { EMPTY, merge, Observable, ObservableInput } from 'rxjs'
|
|
||||||
import { filter, pairwise, switchMap, tap } from 'rxjs/operators'
|
import { filter, pairwise, switchMap, tap } from 'rxjs/operators'
|
||||||
import { ErrorToastService } from '@start9labs/shared'
|
|
||||||
|
|
||||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||||
import { ConfigService } from 'src/app/services/config.service'
|
|
||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
|
||||||
import { PatchDataService } from './patch-data.service'
|
import { PatchDataService } from './patch-data.service'
|
||||||
import { DataModel, ServerInfo } from 'src/app/services/patch-db/data-model'
|
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||||
|
|
||||||
// Watch unread notification count to display toast
|
// Watch unread notification count to display toast
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -64,8 +56,6 @@ export class UnreadToastService extends Observable<unknown> {
|
|||||||
private readonly router: Router,
|
private readonly router: Router,
|
||||||
private readonly patchData: PatchDataService,
|
private readonly patchData: PatchDataService,
|
||||||
private readonly patch: PatchDbService,
|
private readonly patch: PatchDbService,
|
||||||
private readonly config: ConfigService,
|
|
||||||
private readonly embassyApi: ApiService,
|
|
||||||
private readonly toastCtrl: ToastController,
|
private readonly toastCtrl: ToastController,
|
||||||
) {
|
) {
|
||||||
super(subscriber => this.stream$.subscribe(subscriber))
|
super(subscriber => this.stream$.subscribe(subscriber))
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
<ion-item-group class="menu">
|
<ion-item-group class="menu">
|
||||||
<ion-menu-toggle *ngFor="let page of pages; let i = index" auto-hide="false">
|
<ion-menu-toggle *ngFor="let page of pages; let i = index" auto-hide="false">
|
||||||
<ion-item
|
<ion-item
|
||||||
*ngIf="
|
*ngIf="page.url !== '/developer' || (showDevTools$ | async)"
|
||||||
page.url !== '/developer' || (localStorageService.showDevTools$ | async)
|
|
||||||
"
|
|
||||||
button
|
button
|
||||||
class="link"
|
class="link"
|
||||||
color="transparent"
|
color="transparent"
|
||||||
@@ -26,19 +24,27 @@
|
|||||||
{{ page.title }}
|
{{ page.title }}
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-icon
|
<ion-icon
|
||||||
*ngIf="page.url === '/embassy' && (eosService.showUpdate$ | async)"
|
*ngIf="page.url === '/embassy' && (showEOSUpdate$ | async)"
|
||||||
color="success"
|
color="success"
|
||||||
size="small"
|
size="small"
|
||||||
name="rocket-outline"
|
name="rocket-outline"
|
||||||
></ion-icon>
|
></ion-icon>
|
||||||
<ion-badge
|
<ion-badge
|
||||||
*ngIf="
|
*ngIf="
|
||||||
page.url === '/notifications' && (notification$ | async) as count
|
page.url === '/marketplace' && (updateCount$ | async) as updateCount
|
||||||
|
"
|
||||||
|
color="success"
|
||||||
|
>
|
||||||
|
{{ updateCount }}
|
||||||
|
</ion-badge>
|
||||||
|
<ion-badge
|
||||||
|
*ngIf="
|
||||||
|
page.url === '/notifications' &&
|
||||||
|
(notificationCount$ | async) as notificaitonCount
|
||||||
"
|
"
|
||||||
color="danger"
|
color="danger"
|
||||||
class="badge"
|
|
||||||
>
|
>
|
||||||
{{ count }}
|
{{ notificaitonCount }}
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-menu-toggle>
|
</ion-menu-toggle>
|
||||||
|
|||||||
@@ -25,10 +25,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
|
||||||
margin-right: 3%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.snek {
|
.snek {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 90px;
|
bottom: 90px;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'
|
||||||
import { AlertController } from '@ionic/angular'
|
import { AlertController } from '@ionic/angular'
|
||||||
import { ConfigService } from '../../services/config.service'
|
import { ConfigService } from '../../services/config.service'
|
||||||
import { LocalStorageService } from '../../services/local-storage.service'
|
import { LocalStorageService } from '../../services/local-storage.service'
|
||||||
@@ -6,6 +6,10 @@ import { EOSService } from '../../services/eos.service'
|
|||||||
import { ApiService } from '../../services/api/embassy-api.service'
|
import { ApiService } from '../../services/api/embassy-api.service'
|
||||||
import { AuthService } from '../../services/auth.service'
|
import { AuthService } from '../../services/auth.service'
|
||||||
import { PatchDbService } from '../../services/patch-db/patch-db.service'
|
import { PatchDbService } from '../../services/patch-db/patch-db.service'
|
||||||
|
import { Observable } from 'rxjs'
|
||||||
|
import { map } from 'rxjs/operators'
|
||||||
|
import { AbstractMarketplaceService } from '@start9labs/marketplace'
|
||||||
|
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-menu',
|
selector: 'app-menu',
|
||||||
@@ -42,19 +46,29 @@ export class MenuComponent {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
readonly notification$ = this.patch.watch$(
|
readonly notificationCount$ = this.patch.watch$(
|
||||||
'server-info',
|
'server-info',
|
||||||
'unread-notification-count',
|
'unread-notification-count',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
readonly showEOSUpdate$ = this.eosService.showUpdate$
|
||||||
|
|
||||||
|
readonly showDevTools$ = this.localStorageService.showDevTools$
|
||||||
|
|
||||||
|
readonly updateCount$: Observable<number> = this.marketplaceService
|
||||||
|
.getUpdates()
|
||||||
|
.pipe(map(pkgs => pkgs.length))
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly config: ConfigService,
|
private readonly config: ConfigService,
|
||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly embassyApi: ApiService,
|
private readonly embassyApi: ApiService,
|
||||||
private readonly authService: AuthService,
|
private readonly authService: AuthService,
|
||||||
private readonly patch: PatchDbService,
|
private readonly patch: PatchDbService,
|
||||||
public readonly localStorageService: LocalStorageService,
|
private readonly localStorageService: LocalStorageService,
|
||||||
public readonly eosService: EOSService,
|
private readonly eosService: EOSService,
|
||||||
|
@Inject(AbstractMarketplaceService)
|
||||||
|
private readonly marketplaceService: MarketplaceService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get href(): string {
|
get href(): string {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { CommonModule } from '@angular/common'
|
|||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { RouterModule } from '@angular/router'
|
import { RouterModule } from '@angular/router'
|
||||||
import { IonicModule } from '@ionic/angular'
|
import { IonicModule } from '@ionic/angular'
|
||||||
|
|
||||||
import { MenuComponent } from './menu.component'
|
import { MenuComponent } from './menu.component'
|
||||||
import { SnekModule } from '../snek/snek.module'
|
import { SnekModule } from '../snek/snek.module'
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,7 @@ export class MarketplaceListPage {
|
|||||||
startWith({}),
|
startWith({}),
|
||||||
)
|
)
|
||||||
|
|
||||||
readonly categories$ = this.marketplaceService
|
readonly categories$ = this.marketplaceService.getCategories()
|
||||||
.getCategories()
|
|
||||||
.pipe(
|
|
||||||
map(categories => new Set(['featured', 'updates', ...categories, 'all'])),
|
|
||||||
)
|
|
||||||
|
|
||||||
readonly pkgs$: Observable<MarketplacePkg[]> = this.patch
|
readonly pkgs$: Observable<MarketplacePkg[]> = this.patch
|
||||||
.watch$('server-info')
|
.watch$('server-info')
|
||||||
|
|||||||
@@ -7,23 +7,25 @@
|
|||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content *ngIf="ui$ | async as ui" class="ion-padding-top">
|
<ion-content class="ion-padding-top">
|
||||||
<ion-item-group *ngIf="server$ | async as server">
|
<ng-container *ngIf="ui$ | async as ui">
|
||||||
<ion-item-divider>General</ion-item-divider>
|
<ion-item-group *ngIf="server$ | async as server">
|
||||||
<ion-item button (click)="presentModalName('Embassy-' + server.id)">
|
<ion-item-divider>General</ion-item-divider>
|
||||||
<ion-label>Device Name</ion-label>
|
<ion-item button (click)="presentModalName('Embassy-' + server.id)">
|
||||||
<ion-note slot="end">{{ ui.name || 'Embassy-' + server.id }}</ion-note>
|
<ion-label>Device Name</ion-label>
|
||||||
</ion-item>
|
<ion-note slot="end">{{ ui.name || 'Embassy-' + server.id }}</ion-note>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
<ion-item-divider>Marketplace</ion-item-divider>
|
<ion-item-divider>Marketplace</ion-item-divider>
|
||||||
<ion-item
|
<ion-item
|
||||||
button
|
button
|
||||||
(click)="serverConfig.presentAlert('auto-check-updates', ui['auto-check-updates'] !== false)"
|
(click)="serverConfig.presentAlert('auto-check-updates', ui['auto-check-updates'] !== false)"
|
||||||
>
|
>
|
||||||
<ion-label>Auto Check for Updates</ion-label>
|
<ion-label>Auto Check for Updates</ion-label>
|
||||||
<ion-note slot="end">
|
<ion-note slot="end">
|
||||||
{{ ui['auto-check-updates'] !== false ? 'Enabled' : 'Disabled' }}
|
{{ ui['auto-check-updates'] !== false ? 'Enabled' : 'Disabled' }}
|
||||||
</ion-note>
|
</ion-note>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Component, ViewChild } from '@angular/core'
|
import { Component, ViewChild } from '@angular/core'
|
||||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||||
import {
|
import {
|
||||||
IonContent,
|
|
||||||
LoadingController,
|
LoadingController,
|
||||||
ModalController,
|
ModalController,
|
||||||
ToastController,
|
ToastController,
|
||||||
@@ -20,7 +19,6 @@ import { LocalStorageService } from '../../../services/local-storage.service'
|
|||||||
styleUrls: ['./preferences.page.scss'],
|
styleUrls: ['./preferences.page.scss'],
|
||||||
})
|
})
|
||||||
export class PreferencesPage {
|
export class PreferencesPage {
|
||||||
@ViewChild(IonContent) content: IonContent
|
|
||||||
clicks = 0
|
clicks = 0
|
||||||
|
|
||||||
readonly ui$ = this.patch.watch$('ui')
|
readonly ui$ = this.patch.watch$('ui')
|
||||||
@@ -36,10 +34,6 @@ export class PreferencesPage {
|
|||||||
readonly serverConfig: ServerConfigService,
|
readonly serverConfig: ServerConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
|
||||||
this.content.scrollToPoint(undefined, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
async presentModalName(placeholder: string): Promise<void> {
|
async presentModalName(placeholder: string): Promise<void> {
|
||||||
const options: GenericInputOptions = {
|
const options: GenericInputOptions = {
|
||||||
title: 'Edit Device Name',
|
title: 'Edit Device Name',
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ export class MockApiService extends ApiService {
|
|||||||
|
|
||||||
if (path === '/package/v0/info') {
|
if (path === '/package/v0/info') {
|
||||||
return {
|
return {
|
||||||
name: 'Dark9',
|
name: 'Dark69',
|
||||||
categories: [
|
categories: [
|
||||||
'featured',
|
'featured',
|
||||||
'bitcoin',
|
'bitcoin',
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ export const mockPatchData: DataModel = {
|
|||||||
'auto-check-updates': true,
|
'auto-check-updates': true,
|
||||||
'pkg-order': [],
|
'pkg-order': [],
|
||||||
'ack-welcome': '1.0.0',
|
'ack-welcome': '1.0.0',
|
||||||
|
marketplace: {
|
||||||
|
'selected-id': '1234',
|
||||||
|
'known-hosts': {
|
||||||
|
'1234': {
|
||||||
|
name: 'Dark9',
|
||||||
|
url: 'https://test-marketplace.com',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
'server-info': {
|
'server-info': {
|
||||||
id: 'abcdefgh',
|
id: 'abcdefgh',
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { LoadingController } from '@ionic/angular'
|
|
||||||
import { Emver, ErrorToastService } from '@start9labs/shared'
|
import { Emver, ErrorToastService } from '@start9labs/shared'
|
||||||
import {
|
import {
|
||||||
MarketplacePkg,
|
MarketplacePkg,
|
||||||
AbstractMarketplaceService,
|
AbstractMarketplaceService,
|
||||||
Marketplace,
|
Marketplace,
|
||||||
|
FilterPackagesPipe,
|
||||||
|
MarketplaceData,
|
||||||
} from '@start9labs/marketplace'
|
} from '@start9labs/marketplace'
|
||||||
import { from, Observable, of } from 'rxjs'
|
import { from, Observable, of, Subject } from 'rxjs'
|
||||||
import { RR } from 'src/app/services/api/api.types'
|
import { RR } from 'src/app/services/api/api.types'
|
||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { ConfigService } from 'src/app/services/config.service'
|
import { ConfigService } from 'src/app/services/config.service'
|
||||||
@@ -29,12 +30,13 @@ import {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class MarketplaceService extends AbstractMarketplaceService {
|
export class MarketplaceService extends AbstractMarketplaceService {
|
||||||
private readonly notes = new Map<string, Record<string, string>>()
|
private readonly notes = new Map<string, Record<string, string>>()
|
||||||
|
private readonly hasPackages$ = new Subject<boolean>()
|
||||||
|
|
||||||
private readonly altMarketplaceData$: Observable<
|
private readonly uiMarketplaceData$: Observable<
|
||||||
UIMarketplaceData | undefined
|
UIMarketplaceData | undefined
|
||||||
> = this.patch.watch$('ui', 'marketplace').pipe(shareReplay(1))
|
> = this.patch.watch$('ui', 'marketplace').pipe(shareReplay(1))
|
||||||
|
|
||||||
private readonly marketplace$ = this.altMarketplaceData$.pipe(
|
private readonly marketplace$ = this.uiMarketplaceData$.pipe(
|
||||||
map(data => this.toMarketplace(data)),
|
map(data => this.toMarketplace(data)),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,48 +44,80 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
.watch$('server-info')
|
.watch$('server-info')
|
||||||
.pipe(take(1), shareReplay())
|
.pipe(take(1), shareReplay())
|
||||||
|
|
||||||
private readonly categories$: Observable<string[]> = this.marketplace$.pipe(
|
private readonly registryData$: Observable<MarketplaceData> =
|
||||||
switchMap(({ url }) =>
|
this.uiMarketplaceData$.pipe(
|
||||||
this.serverInfo$.pipe(
|
switchMap(uiMarketplaceData =>
|
||||||
switchMap(({ id }) =>
|
|
||||||
from(this.getMarketplaceData({ 'server-id': id }, url)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
map(({ categories }) => categories),
|
|
||||||
shareReplay(1),
|
|
||||||
)
|
|
||||||
|
|
||||||
private readonly pkg$: Observable<MarketplacePkg[]> =
|
|
||||||
this.altMarketplaceData$.pipe(
|
|
||||||
switchMap(data =>
|
|
||||||
this.serverInfo$.pipe(
|
this.serverInfo$.pipe(
|
||||||
switchMap(info =>
|
switchMap(({ id }) =>
|
||||||
from(
|
from(
|
||||||
this.getMarketplacePkgs(
|
this.getMarketplaceData(
|
||||||
{ page: 1, 'per-page': 100 },
|
{ 'server-id': id },
|
||||||
this.toMarketplace(data).url,
|
this.toMarketplace(uiMarketplaceData).url,
|
||||||
info['eos-version-compat'],
|
|
||||||
),
|
),
|
||||||
).pipe(tap(() => this.onPackages(data))),
|
).pipe(tap(({ name }) => this.updateName(uiMarketplaceData, name))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
catchError(e => {
|
|
||||||
this.errToast.present(e)
|
|
||||||
|
|
||||||
return of([])
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
shareReplay(1),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private readonly categories$: Observable<Set<string>> =
|
||||||
|
this.registryData$.pipe(
|
||||||
|
map(
|
||||||
|
({ categories }) =>
|
||||||
|
new Set(['featured', 'updates', ...categories, 'all']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
private readonly pkgs$: Observable<MarketplacePkg[]> = this.marketplace$.pipe(
|
||||||
|
switchMap(({ url }) =>
|
||||||
|
this.serverInfo$.pipe(
|
||||||
|
switchMap(info =>
|
||||||
|
from(
|
||||||
|
this.getMarketplacePkgs(
|
||||||
|
{ page: 1, 'per-page': 100 },
|
||||||
|
url,
|
||||||
|
info['eos-version-compat'],
|
||||||
|
),
|
||||||
|
).pipe(tap(() => this.hasPackages$.next(true))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
catchError(e => {
|
||||||
|
this.errToast.present(e)
|
||||||
|
|
||||||
|
return of([])
|
||||||
|
}),
|
||||||
|
shareReplay(1),
|
||||||
|
)
|
||||||
|
|
||||||
|
private readonly updates$: Observable<MarketplacePkg[]> =
|
||||||
|
this.hasPackages$.pipe(
|
||||||
|
switchMap(() =>
|
||||||
|
this.patch.watch$('package-data').pipe(
|
||||||
|
switchMap(localPkgs =>
|
||||||
|
this.pkgs$.pipe(
|
||||||
|
map(pkgs => {
|
||||||
|
return this.filterPkgsPipe.transform(
|
||||||
|
pkgs,
|
||||||
|
'',
|
||||||
|
'updates',
|
||||||
|
localPkgs,
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly api: ApiService,
|
private readonly api: ApiService,
|
||||||
private readonly patch: PatchDbService,
|
private readonly patch: PatchDbService,
|
||||||
private readonly config: ConfigService,
|
private readonly config: ConfigService,
|
||||||
private readonly loadingCtrl: LoadingController,
|
|
||||||
private readonly errToast: ErrorToastService,
|
private readonly errToast: ErrorToastService,
|
||||||
private readonly emver: Emver,
|
private readonly emver: Emver,
|
||||||
|
private readonly filterPkgsPipe: FilterPackagesPipe,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
@@ -93,15 +127,15 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAltMarketplace(): Observable<UIMarketplaceData | undefined> {
|
getAltMarketplace(): Observable<UIMarketplaceData | undefined> {
|
||||||
return this.altMarketplaceData$
|
return this.uiMarketplaceData$
|
||||||
}
|
}
|
||||||
|
|
||||||
getCategories(): Observable<string[]> {
|
getCategories(): Observable<Set<string>> {
|
||||||
return this.categories$
|
return this.categories$
|
||||||
}
|
}
|
||||||
|
|
||||||
getPackages(): Observable<MarketplacePkg[]> {
|
getPackages(): Observable<MarketplacePkg[]> {
|
||||||
return this.pkg$
|
return this.pkgs$
|
||||||
}
|
}
|
||||||
|
|
||||||
getPackage(id: string, version: string): Observable<MarketplacePkg | null> {
|
getPackage(id: string, version: string): Observable<MarketplacePkg | null> {
|
||||||
@@ -133,6 +167,10 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUpdates(): Observable<MarketplacePkg[]> {
|
||||||
|
return this.updates$
|
||||||
|
}
|
||||||
|
|
||||||
getReleaseNotes(id: string): Observable<Record<string, string>> {
|
getReleaseNotes(id: string): Observable<Record<string, string>> {
|
||||||
if (this.notes.has(id)) {
|
if (this.notes.has(id)) {
|
||||||
return of(this.notes.get(id) || {})
|
return of(this.notes.get(id) || {})
|
||||||
@@ -216,15 +254,16 @@ export class MarketplaceService extends AbstractMarketplaceService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private onPackages(data?: UIMarketplaceData) {
|
private updateName(
|
||||||
const { name } = this.toMarketplace(data)
|
uiMarketplaceData: UIMarketplaceData | undefined,
|
||||||
|
name: string,
|
||||||
if (!data?.['selected-id']) {
|
) {
|
||||||
|
if (!uiMarketplaceData?.['selected-id']) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedId = data['selected-id']
|
const selectedId = uiMarketplaceData['selected-id']
|
||||||
const knownHosts = data['known-hosts']
|
const knownHosts = uiMarketplaceData['known-hosts']
|
||||||
|
|
||||||
if (knownHosts[selectedId].name !== name) {
|
if (knownHosts[selectedId].name !== name) {
|
||||||
this.api.setDbValue({
|
this.api.setDbValue({
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export const serverConfig: ConfigSpec = {
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
name: 'Auto Check for Updates',
|
name: 'Auto Check for Updates',
|
||||||
description:
|
description:
|
||||||
'If enabled, EmbassyOS will automatically check for updates of itself. Updating will still require your approval and action. Updates will never be performed automatically.',
|
'If enabled, EmbassyOS will automatically check for updates of itself and installed services. Updating will still require your approval and action. Updates will never be performed automatically.',
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user