start9 marketplace config

shift not unshift

move eos updates to embassy tab

selected id sub

roughly working

keep name in sync in case of change

delete commented code

64 img
This commit is contained in:
Drew Ansbacher
2022-02-01 13:21:50 -07:00
committed by Aiden McClelland
parent 2d4ecd3096
commit 0c0cd9d0a0
28 changed files with 1787 additions and 1619 deletions

File diff suppressed because one or more lines are too long

View File

@@ -64,14 +64,6 @@ export module RR {
export type KillSessionsReq = WithExpire<{ ids: string[] }> // sessions.kill
export type KillSessionsRes = WithRevision<null>
// marketplace URLs
export type SetEosMarketplaceReq = WithExpire<{ url: string }> // marketplace.eos.set
export type SetEosMarketplaceRes = WithRevision<null>
export type SetPackageMarketplaceReq = WithExpire<{ url: string }> // marketplace.package.set
export type SetPackageMarketplaceRes = WithRevision<null>
// password
export type UpdatePasswordReq = { password: string } // password.set
@@ -267,15 +259,11 @@ export module RR {
query?: string
page?: string
'per-page'?: string
url?: string
}
export type GetMarketplacePackagesRes = MarketplacePkg[]
export type GetReleaseNotesReq = { id: string }
export type GetReleaseNotesRes = { [version: string]: string }
export type GetLatestVersionReq = { ids: string[] }
export type GetLatestVersionRes = { [id: string]: string }
}
export type WithExpire<T> = { 'expire-id'?: string } & T

View File

@@ -113,15 +113,6 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
params: RR.GetReleaseNotesReq,
): Promise<RR.GetReleaseNotesRes>
abstract getLatestVersion(
params: RR.GetLatestVersionReq,
): Promise<RR.GetLatestVersionRes>
// protected abstract setPackageMarketplaceRaw (params: RR.SetPackageMarketplaceReq): Promise<RR.SetPackageMarketplaceRes>
// setPackageMarketplace = (params: RR.SetPackageMarketplaceReq) => this.syncResponse(
// () => this.setPackageMarketplaceRaw(params),
// )()
// password
// abstract updatePassword (params: RR.UpdatePasswordReq): Promise<RR.UpdatePasswordRes>

View File

@@ -4,15 +4,22 @@ import { ApiService } from './embassy-api.service'
import { RR } from './api.types'
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
import { PatchDbService } from '../patch-db/patch-db.service'
import { ConfigService } from '../config.service'
@Injectable()
export class LiveApiService extends ApiService {
private marketplaceUrl: string
constructor(
private readonly http: HttpService,
private readonly patch: PatchDbService,
private readonly config: ConfigService,
) {
super()
;(window as any).rpcClient = this
this.patch.watch$('ui', 'marketplace', 'selected-id').subscribe(id => {
this.marketplaceUrl = id
})
}
async getStatic(url: string): Promise<string> {
@@ -106,10 +113,7 @@ export class LiveApiService extends ApiService {
params: {},
url?: string,
): Promise<T> {
if (!url) {
const id = this.patch.data.ui.marketplace['selected-id']
url = this.patch.data.ui.marketplace.options[id].url
}
url = url || this.marketplaceUrl
const fullURL = `${url}${path}?${new URLSearchParams(params).toString()}`
return this.http.rpcRequest({
method: 'marketplace.get',
@@ -120,25 +124,25 @@ export class LiveApiService extends ApiService {
async getEos(
params: RR.GetMarketplaceEOSReq,
): Promise<RR.GetMarketplaceEOSRes> {
return this.http.httpRequest({
method: Method.GET,
url: '/marketplace/eos/latest',
return this.marketplaceProxy(
'/eos/latest',
params,
})
this.config.eosMarketplaceUrl,
)
}
async getMarketplaceData(
params: RR.GetMarketplaceDataReq,
url?: string,
): Promise<RR.GetMarketplaceDataRes> {
return this.marketplaceProxy('/marketplace/package/data', params, url)
return this.marketplaceProxy('/package/data', params, url)
}
async getMarketplacePkgs(
params: RR.GetMarketplacePackagesReq,
): Promise<RR.GetMarketplacePackagesRes> {
if (params.query) params.category = undefined
return this.marketplaceProxy('/marketplace/package/index', {
return this.marketplaceProxy('/package/index', {
...params,
ids: JSON.stringify(params.ids),
})
@@ -147,27 +151,9 @@ export class LiveApiService extends ApiService {
async getReleaseNotes(
params: RR.GetReleaseNotesReq,
): Promise<RR.GetReleaseNotesRes> {
return this.http.httpRequest({
method: Method.GET,
url: '/marketplace/package/release-notes',
params,
})
return this.marketplaceProxy('/package/release-notes', params)
}
async getLatestVersion(
params: RR.GetLatestVersionReq,
): Promise<RR.GetLatestVersionRes> {
return this.http.httpRequest({
method: Method.GET,
url: '/marketplace/latest-version',
params,
})
}
// async setPackageMarketplaceRaw (params: RR.SetPackageMarketplaceReq): Promise<RR.SetPackageMarketplaceRes> {
// return this.http.rpcRequest({ method: 'marketplace.package.set', params })
// }
// password
// async updatePassword (params: RR.UpdatePasswordReq): Promise<RR.UpdatePasswordRes> {
// return this.http.rpcRequest({ method: 'password.set', params })

View File

@@ -228,16 +228,6 @@ export class MockApiService extends ApiService {
return Mock.ReleaseNotes
}
async getLatestVersion (
params: RR.GetLatestVersionReq,
): Promise<RR.GetLatestVersionRes> {
await pauseFor(2000)
return params.ids.reduce((obj, id) => {
obj[id] = '1.3.0'
return obj
}, {})
}
// password
// async updatePassword (params: RR.UpdatePasswordReq): Promise<RR.UpdatePasswordRes> {
// await pauseFor(2000)

View File

@@ -16,15 +16,7 @@ export const mockPatchData: DataModel = {
'pkg-order': [],
'ack-welcome': '1.0.0',
'ack-share-stats': false,
marketplace: {
'selected-id': 'asdfasdf',
options: {
asdfasdf: {
name: 'Start9',
url: 'start9marketplace.com',
},
},
},
marketplace: undefined,
},
'server-info': {
id: 'embassy-abcdefgh',
@@ -439,6 +431,8 @@ export const mockPatchData: DataModel = {
},
'current-dependencies': {},
'dependency-info': {},
'marketplace-url': 'marketplace-url.com',
'developer-key': 'developer-key',
},
},
lnd: {
@@ -644,6 +638,8 @@ export const mockPatchData: DataModel = {
icon: 'assets/img/service-icons/btc-rpc-proxy.png',
},
},
'marketplace-url': 'marketplace-url.com',
'developer-key': 'developer-key',
},
},
},

View File

@@ -9,7 +9,7 @@ import { WorkspaceConfig } from '@shared'
const {
useMocks,
ui: { gitHash, patchDb, api, mocks },
ui: { gitHash, patchDb, api, mocks, eosMarketplaceURL },
} = require('../../../../../config.json') as WorkspaceConfig
@Injectable({
@@ -25,6 +25,7 @@ export class ConfigService {
gitHash = gitHash
patchDb = patchDb
api = api
eosMarketplaceUrl = eosMarketplaceURL
skipStartupAlerts = useMocks && mocks.skipStartupAlerts
isConsulate = window['platform'] === 'ios'

View File

@@ -0,0 +1,33 @@
import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs'
import { MarketplaceEOS } from 'src/app/services/api/api.types'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { Emver } from 'src/app/services/emver.service'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
@Injectable({
providedIn: 'root',
})
export class EOSService {
eos: MarketplaceEOS
updateAvailable$ = new BehaviorSubject<boolean>(false)
constructor(
private readonly api: ApiService,
private readonly emver: Emver,
private readonly patch: PatchDbService,
) {}
async getEOS(): Promise<void> {
this.eos = await this.api.getEos({
'eos-version-compat':
this.patch.getData()['server-info']['eos-version-compat'],
})
const updateAvailable =
this.emver.compare(
this.eos.version,
this.patch.data['server-info'].version,
) === 1
this.updateAvailable$.next(updateAvailable)
}
}

View File

@@ -17,8 +17,8 @@ export interface UIData {
}
export interface UIMarketplaceData {
'selected-id': string
options: {
'selected-id': string | null
'known-hosts': {
[id: string]: {
url: string
name: string
@@ -94,6 +94,8 @@ export interface InstalledPackageDataEntry {
'interface-addresses': {
[id: string]: { 'tor-address': string; 'lan-address': string }
}
'marketplace-url': string | null
'developer-key': string
}
export interface CurrentDependencyInfo {

View File

@@ -1,26 +1,14 @@
import { Injectable } from '@angular/core'
import {
AlertController,
IonicSafeString,
ModalController,
NavController,
} from '@ionic/angular'
import { wizardModal } from '../components/install-wizard/install-wizard.component'
import { ModalController } from '@ionic/angular'
import { WizardBaker } from '../components/install-wizard/prebaked-wizards'
import { OSWelcomePage } from '../modals/os-welcome/os-welcome.page'
import { displayEmver } from '../pipes/emver.pipe'
import { RR } from './api/api.types'
import { ConfigService } from './config.service'
import { Emver } from './emver.service'
import { MarketplaceService } from '../pages/marketplace-routes/marketplace.service'
import { DataModel } from './patch-db/data-model'
import { PatchDbService } from './patch-db/patch-db.service'
import { filter, take } from 'rxjs/operators'
import { isEmptyObject } from '../util/misc.util'
import { ApiService } from './api/embassy-api.service'
import { Subscription } from 'rxjs'
import { ServerConfigService } from './server-config.service'
import { v4 } from 'uuid'
@Injectable({
providedIn: 'root',
@@ -29,13 +17,9 @@ export class StartupAlertsService {
private checks: Check<any>[]
constructor(
private readonly alertCtrl: AlertController,
private readonly navCtrl: NavController,
private readonly config: ConfigService,
private readonly modalCtrl: ModalController,
private readonly marketplaceService: MarketplaceService,
private readonly api: ApiService,
private readonly emver: Emver,
private readonly wizardBaker: WizardBaker,
private readonly patch: PatchDbService,
private readonly serverConfig: ServerConfigService,
@@ -43,22 +27,14 @@ export class StartupAlertsService {
const osWelcome: Check<boolean> = {
name: 'osWelcome',
shouldRun: () => this.shouldRunOsWelcome(),
check: async () => true,
display: () => this.displayOsWelcome(),
}
const shareStats: Check<boolean> = {
name: 'shareStats',
shouldRun: () => this.shouldRunShareStats(),
check: async () => true,
display: () => this.displayShareStats(),
}
const osUpdate: Check<RR.GetMarketplaceEOSRes | undefined> = {
name: 'osUpdate',
shouldRun: () => this.shouldRunOsUpdateCheck(),
check: () => this.osUpdateCheck(),
display: pkg => this.displayOsUpdateCheck(pkg),
}
this.checks = [osWelcome, shareStats, osUpdate]
this.checks = [osWelcome, shareStats]
}
// This takes our three checks and filters down to those that should run.
@@ -72,37 +48,14 @@ export class StartupAlertsService {
filter(data => !isEmptyObject(data)),
take(1),
)
.subscribe(async data => {
if (!data.ui.marketplace) {
const uuid = v4()
const value = {
'selected-id': uuid,
options: {
[uuid]: {
url: 'marketplaceurl.com',
name: 'Start9',
},
},
}
await this.api.setDbValue({ pointer: 'marketplace', value })
}
.subscribe(async () => {
await this.checks
.filter(c => !this.config.skipStartupAlerts && c.shouldRun())
// returning true in the below block means to continue to next modal
// returning false means to skip all subsequent modals
.reduce(async (previousDisplay, c) => {
let checkRes: any
try {
checkRes = await c.check()
} catch (e) {
console.error(`Exception in ${c.name} check:`, e)
return true
}
const displayRes = await previousDisplay
if (!checkRes) return true
if (displayRes) return c.display(checkRes)
if (displayRes) return c.display()
}, Promise.resolve(true))
})
}
@@ -120,21 +73,6 @@ export class StartupAlertsService {
return this.patch.getData().ui['auto-check-updates']
}
// ** check **
private async osUpdateCheck(): Promise<RR.GetMarketplaceEOSRes | undefined> {
const res = await this.api.getEos({
'eos-version-compat':
this.patch.getData()['server-info']['eos-version-compat'],
})
if (this.emver.compare(this.config.version, res.version) === -1) {
return res
} else {
return undefined
}
}
// ** display **
private async displayOsWelcome(): Promise<boolean> {
@@ -174,69 +112,14 @@ export class StartupAlertsService {
})
})
}
private async displayOsUpdateCheck(
eos: RR.GetMarketplaceEOSRes,
): Promise<boolean> {
const { update } = await this.presentAlertNewOS(eos.version)
if (update) {
const { cancelled } = await wizardModal(
this.modalCtrl,
this.wizardBaker.updateOS({
version: eos.version,
headline: eos.headline,
releaseNotes: eos['release-notes'],
}),
)
if (cancelled) return true
return false
}
return true
}
// more
private async presentAlertNewOS(
versionLatest: string,
): Promise<{ cancel?: true; update?: true }> {
return new Promise(async resolve => {
const alert = await this.alertCtrl.create({
header: 'New EmbassyOS Version!',
message: new IonicSafeString(
`<div style="display: flex; flex-direction: column; justify-content: space-around; min-height: 100px">
<div>Update EmbassyOS to version ${displayEmver(
versionLatest,
)}?</div>
<div style="font-size:x-small">You can disable these checks in your Embassy Config</div>
</div>
`,
),
buttons: [
{
text: 'Not now',
role: 'cancel',
handler: () => resolve({ cancel: true }),
},
{
text: 'Update',
handler: () => resolve({ update: true }),
cssClass: 'enter-click',
},
],
})
await alert.present()
})
}
}
type Check<T> = {
// validates whether a check should run based on server properties
shouldRun: () => boolean
// executes a check, often requiring api call. It should return a false-y value if there should be no display.
check: () => Promise<T>
// display an alert based on the result of the check.
// return false if subsequent modals should not be displayed
display: (a: T) => Promise<boolean>
display: () => Promise<boolean>
// for logging purposes
name: string
}