mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
Fix/sideload icon type (#1577)
* add content type to icon dataURL * better handling of blob reading; remove verifying loader and reorganize html * clean up PR feedback and create validation fn instead of boolean * grpup upload state into one type * better organize validation * add server id to eos check for updates req * fix patchdb to latest Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
@@ -10,7 +10,7 @@ export interface MarketplaceManifest<T = unknown> {
|
|||||||
long: string
|
long: string
|
||||||
}
|
}
|
||||||
'release-notes': string
|
'release-notes': string
|
||||||
license: string // name
|
license: string // type of license
|
||||||
'wrapper-repo': Url
|
'wrapper-repo': Url
|
||||||
'upstream-repo': Url
|
'upstream-repo': Url
|
||||||
'support-site': Url
|
'support-site': Url
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<ion-content class="ion-text-center">
|
<ion-content class="ion-text-center">
|
||||||
<!-- file upload -->
|
<!-- file upload -->
|
||||||
<div
|
<div
|
||||||
*ngIf="!toUpload.file"
|
*ngIf="!toUpload.file; else fileUploaded"
|
||||||
class="drop-area"
|
class="drop-area"
|
||||||
[class.drop-area_mobile]="isMobile"
|
[class.drop-area_mobile]="isMobile"
|
||||||
appDnd
|
appDnd
|
||||||
@@ -39,56 +39,61 @@
|
|||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- file uploaded -->
|
<!-- file uploaded -->
|
||||||
<div class="drop-area_filled" *ngIf="toUpload.file">
|
<ng-template #fileUploaded>
|
||||||
<div class="inline" *ngIf="valid; else invalid">
|
<div class="drop-area_filled">
|
||||||
<ion-icon name="checkmark-circle-outline" color="success"></ion-icon>
|
<h4>
|
||||||
<h4>{{ message }}</h4>
|
<ion-icon
|
||||||
</div>
|
*ngIf="uploadState?.invalid"
|
||||||
<ng-template #invalid>
|
name="close-circle-outline"
|
||||||
<div class="area">
|
color="danger"
|
||||||
<div class="inline">
|
class="inline"
|
||||||
<ion-icon
|
></ion-icon>
|
||||||
*ngIf="!valid"
|
<ion-icon
|
||||||
name="close-circle-outline"
|
*ngIf="!uploadState?.invalid"
|
||||||
color="danger"
|
class="inline"
|
||||||
></ion-icon>
|
name="checkmark-circle-outline"
|
||||||
<h4><ion-text color="danger">{{ message }}</ion-text></h4>
|
color="success"
|
||||||
</div>
|
></ion-icon>
|
||||||
<ion-button color="primary" (click)="clearToUpload()">
|
{{ uploadState?.message }}
|
||||||
Try again
|
</h4>
|
||||||
</ion-button>
|
<div class="box" *ngIf="toUpload.icon && toUpload.manifest">
|
||||||
</div>
|
<div class="service-card">
|
||||||
</ng-template>
|
<div class="row row_end">
|
||||||
<br />
|
<ion-button
|
||||||
<div *ngIf="valid">
|
style="
|
||||||
<div *ngIf="toUpload.manifest " class="service-card">
|
--background-hover: transparent;
|
||||||
<div class="row row_end">
|
--padding-end: 0px;
|
||||||
<ion-button
|
--padding-start: 0px;
|
||||||
style="
|
"
|
||||||
--background-hover: transparent;
|
fill="clear"
|
||||||
--padding-end: 0px;
|
size="small"
|
||||||
--padding-start: 0px;
|
(click)="clearToUpload()"
|
||||||
"
|
>
|
||||||
fill="clear"
|
<ion-icon slot="icon-only" name="close" color="danger"></ion-icon>
|
||||||
size="small"
|
</ion-button>
|
||||||
(click)="clearToUpload()"
|
</div>
|
||||||
>
|
<div class="row">
|
||||||
<ion-icon slot="icon-only" name="close" color="danger"></ion-icon>
|
<img
|
||||||
</ion-button>
|
[alt]="toUpload.manifest.title + ' Icon'"
|
||||||
</div>
|
[src]="toUpload.icon | trustUrl"
|
||||||
<div class="row">
|
/>
|
||||||
<img
|
<h2>{{ toUpload.manifest.title }}</h2>
|
||||||
*ngIf="toUpload.icon"
|
<p>{{ toUpload.manifest.version | displayEmver }}</p>
|
||||||
[alt]="toUpload.manifest.title + ' Icon'"
|
</div>
|
||||||
[src]="toUpload.icon | trustUrl"
|
|
||||||
/>
|
|
||||||
<h2>{{ toUpload.manifest.title }}</h2>
|
|
||||||
<p>{{ toUpload.manifest.version | displayEmver }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ion-button color="primary" (click)="handleUpload()">
|
<ion-button
|
||||||
Upload & Install
|
*ngIf="!toUpload.icon && !toUpload.manifest; else uploadButton"
|
||||||
|
color="primary"
|
||||||
|
(click)="clearToUpload()"
|
||||||
|
>
|
||||||
|
Try again
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
<ng-template #uploadButton>
|
||||||
|
<ion-button color="primary" (click)="handleUpload()">
|
||||||
|
Upload & Install
|
||||||
|
</ion-button>
|
||||||
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ng-template>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
.inline {
|
.inline {
|
||||||
* {
|
vertical-align: initial;
|
||||||
vertical-align: initial;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.area {
|
.area {
|
||||||
@@ -39,7 +36,7 @@
|
|||||||
margin: 60px;
|
margin: 60px;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
|
min-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_mobile {
|
&_mobile {
|
||||||
@@ -51,10 +48,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly
|
||||||
|
}
|
||||||
|
|
||||||
.service-card {
|
.service-card {
|
||||||
background: radial-gradient(var(--ion-color-step-100), transparent);
|
background: radial-gradient(var(--ion-color-step-100), transparent);
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
max-width: 300px;
|
max-width: 200px;
|
||||||
height: auto;
|
height: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import { Manifest } from 'src/app/services/patch-db/data-model'
|
|||||||
import { ConfigService } from 'src/app/services/config.service'
|
import { ConfigService } from 'src/app/services/config.service'
|
||||||
import cbor from 'cbor'
|
import cbor from 'cbor'
|
||||||
import { ErrorToastService } from '@start9labs/shared'
|
import { ErrorToastService } from '@start9labs/shared'
|
||||||
|
|
||||||
interface Positions {
|
interface Positions {
|
||||||
[key: string]: [bigint, bigint] // [position, length]
|
[key: string]: [bigint, bigint] // [position, length]
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAGIC = new Uint8Array([59, 59])
|
const MAGIC = new Uint8Array([59, 59])
|
||||||
const VERSION = new Uint8Array([1])
|
const VERSION = new Uint8Array([1])
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'sideload',
|
selector: 'sideload',
|
||||||
templateUrl: './sideload.page.html',
|
templateUrl: './sideload.page.html',
|
||||||
@@ -28,8 +30,10 @@ export class SideloadPage {
|
|||||||
file: null,
|
file: null,
|
||||||
}
|
}
|
||||||
onTor = this.config.isTor()
|
onTor = this.config.isTor()
|
||||||
valid: boolean
|
uploadState: {
|
||||||
message: string
|
invalid: boolean
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly loadingCtrl: LoadingController,
|
private readonly loadingCtrl: LoadingController,
|
||||||
@@ -49,29 +53,27 @@ export class SideloadPage {
|
|||||||
this.setFile(files)
|
this.setFile(files)
|
||||||
}
|
}
|
||||||
async setFile(files?: File[]) {
|
async setFile(files?: File[]) {
|
||||||
const loader = await this.loadingCtrl.create({
|
|
||||||
message: 'Verifying package',
|
|
||||||
cssClass: 'loader',
|
|
||||||
})
|
|
||||||
await loader.present()
|
|
||||||
if (!files || !files.length) return
|
if (!files || !files.length) return
|
||||||
this.toUpload.file = files[0]
|
const file = files[0]
|
||||||
// verify valid s9pk
|
if (!file) return
|
||||||
const magic = new Uint8Array(
|
this.toUpload.file = file
|
||||||
await readBlobToArrayBuffer(this.toUpload.file.slice(0, 2)),
|
this.uploadState = await this.validateS9pk(file)
|
||||||
)
|
}
|
||||||
const version = new Uint8Array(
|
|
||||||
await readBlobToArrayBuffer(this.toUpload.file.slice(2, 3)),
|
async validateS9pk(file: File) {
|
||||||
)
|
const magic = new Uint8Array(await blobToBuffer(file.slice(0, 2)))
|
||||||
|
const version = new Uint8Array(await blobToBuffer(file.slice(2, 3)))
|
||||||
if (compare(magic, MAGIC) && compare(version, VERSION)) {
|
if (compare(magic, MAGIC) && compare(version, VERSION)) {
|
||||||
loader.dismiss()
|
await this.parseS9pk(file)
|
||||||
this.valid = true
|
return {
|
||||||
this.message = 'A valid package file has been detected!'
|
invalid: false,
|
||||||
await this.parseS9pk(this.toUpload.file)
|
message: 'A valid package file has been detected!',
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
loader.dismiss()
|
return {
|
||||||
this.valid = false
|
invalid: true,
|
||||||
this.message = 'Invalid package file'
|
message: 'Invalid package file',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +95,7 @@ export class SideloadPage {
|
|||||||
icon: this.toUpload.icon!,
|
icon: this.toUpload.icon!,
|
||||||
})
|
})
|
||||||
this.api
|
this.api
|
||||||
.uploadPackage(guid, await readBlobToArrayBuffer(this.toUpload.file!))
|
.uploadPackage(guid, await blobToBuffer(this.toUpload.file!))
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
this.errToast.present(e)
|
this.errToast.present(e)
|
||||||
})
|
})
|
||||||
@@ -108,15 +110,13 @@ export class SideloadPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseS9pk(file: Blob) {
|
async parseS9pk(file: File) {
|
||||||
const positions: Positions = {}
|
const positions: Positions = {}
|
||||||
// magic=2bytes, version=1bytes, pubkey=32bytes, signature=64bytes, toc_length=4bytes = 103byte is starting point
|
// magic=2bytes, version=1bytes, pubkey=32bytes, signature=64bytes, toc_length=4bytes = 103byte is starting point
|
||||||
let start = 103
|
let start = 103
|
||||||
let end = start + 1 // 104
|
let end = start + 1 // 104
|
||||||
const tocLength = new DataView(
|
const tocLength = new DataView(
|
||||||
await readBlobToArrayBuffer(
|
await blobToBuffer(file.slice(99, 103) ?? new Blob()),
|
||||||
this.toUpload.file?.slice(99, 103) ?? new Blob(),
|
|
||||||
),
|
|
||||||
).getUint32(0, false)
|
).getUint32(0, false)
|
||||||
await getPositions(start, end, file, positions, tocLength as any)
|
await getPositions(start, end, file, positions, tocLength as any)
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ export class SideloadPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getManifest(positions: Positions, file: Blob) {
|
async getManifest(positions: Positions, file: Blob) {
|
||||||
const data = await readBlobToArrayBuffer(
|
const data = await blobToBuffer(
|
||||||
file.slice(
|
file.slice(
|
||||||
Number(positions['manifest'][0]),
|
Number(positions['manifest'][0]),
|
||||||
Number(positions['manifest'][0]) + Number(positions['manifest'][1]),
|
Number(positions['manifest'][0]) + Number(positions['manifest'][1]),
|
||||||
@@ -135,11 +135,15 @@ export class SideloadPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getIcon(positions: Positions, file: Blob) {
|
async getIcon(positions: Positions, file: Blob) {
|
||||||
|
const contentType = `image/${this.toUpload.manifest?.assets.icon
|
||||||
|
.split('.')
|
||||||
|
.pop()}`
|
||||||
const data = file.slice(
|
const data = file.slice(
|
||||||
Number(positions['icon'][0]),
|
Number(positions['icon'][0]),
|
||||||
Number(positions['icon'][0]) + Number(positions['icon'][1]),
|
Number(positions['icon'][0]) + Number(positions['icon'][1]),
|
||||||
|
contentType,
|
||||||
)
|
)
|
||||||
this.toUpload.icon = await readBlobAsDataURL(data)
|
this.toUpload.icon = await blobToDataURL(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,18 +157,18 @@ async function getPositions(
|
|||||||
let start = initialStart
|
let start = initialStart
|
||||||
let end = initialEnd
|
let end = initialEnd
|
||||||
const titleLength = new Uint8Array(
|
const titleLength = new Uint8Array(
|
||||||
await readBlobToArrayBuffer(file.slice(start, end)),
|
await blobToBuffer(file.slice(start, end)),
|
||||||
)[0]
|
)[0]
|
||||||
const tocTitle = await file.slice(end, end + titleLength).text()
|
const tocTitle = await file.slice(end, end + titleLength).text()
|
||||||
start = end + titleLength
|
start = end + titleLength
|
||||||
end = start + 8
|
end = start + 8
|
||||||
const chapterPosition = new DataView(
|
const chapterPosition = new DataView(
|
||||||
await readBlobToArrayBuffer(file.slice(start, end)),
|
await blobToBuffer(file.slice(start, end)),
|
||||||
).getBigUint64(0, false)
|
).getBigUint64(0, false)
|
||||||
start = end
|
start = end
|
||||||
end = start + 8
|
end = start + 8
|
||||||
const chapterLength = new DataView(
|
const chapterLength = new DataView(
|
||||||
await readBlobToArrayBuffer(file.slice(start, end)),
|
await blobToBuffer(file.slice(start, end)),
|
||||||
).getBigUint64(0, false)
|
).getBigUint64(0, false)
|
||||||
|
|
||||||
positions[tocTitle] = [chapterPosition, chapterLength]
|
positions[tocTitle] = [chapterPosition, chapterLength]
|
||||||
@@ -175,23 +179,48 @@ async function getPositions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readBlobAsDataURL(f: Blob): Promise<string> {
|
async function readBlobAsDataURL(
|
||||||
|
f: Blob | File,
|
||||||
|
): Promise<string | ArrayBuffer | null> {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.readAsDataURL(f)
|
return new Promise((resolve, reject) => {
|
||||||
return new Promise(resolve => {
|
|
||||||
reader.onloadend = () => {
|
reader.onloadend = () => {
|
||||||
resolve(reader.result as string)
|
resolve(reader.result)
|
||||||
}
|
}
|
||||||
|
reader.readAsDataURL(f)
|
||||||
|
reader.onerror = _ => reject(new Error('error reading blob'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
async function blobToDataURL(data: Blob | File): Promise<string> {
|
||||||
|
const res = await readBlobAsDataURL(data)
|
||||||
|
if (res instanceof ArrayBuffer)
|
||||||
|
throw new Error('readBlobAsDataURL response should not be an array buffer')
|
||||||
|
if (res == null)
|
||||||
|
throw new Error('readBlobAsDataURL response should not be null')
|
||||||
|
if (typeof res === 'string') return res
|
||||||
|
throw new Error('no possible blob to data url resolution found')
|
||||||
|
}
|
||||||
|
|
||||||
async function readBlobToArrayBuffer(f: Blob): Promise<ArrayBuffer> {
|
async function blobToBuffer(data: Blob | File): Promise<ArrayBuffer> {
|
||||||
|
const res = await readBlobToArrayBuffer(data)
|
||||||
|
if (res instanceof String)
|
||||||
|
throw new Error('readBlobToArrayBuffer response should not be a string')
|
||||||
|
if (res == null)
|
||||||
|
throw new Error('readBlobToArrayBuffer response should not be null')
|
||||||
|
if (res instanceof ArrayBuffer) return res
|
||||||
|
throw new Error('no possible blob to array buffer resolution found')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readBlobToArrayBuffer(
|
||||||
|
f: Blob | File,
|
||||||
|
): Promise<string | ArrayBuffer | null> {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.readAsArrayBuffer(f)
|
return new Promise((resolve, reject) => {
|
||||||
return new Promise(resolve => {
|
|
||||||
reader.onloadend = () => {
|
reader.onloadend = () => {
|
||||||
resolve(reader.result as ArrayBuffer)
|
resolve(reader.result)
|
||||||
}
|
}
|
||||||
|
reader.readAsArrayBuffer(f)
|
||||||
|
reader.onerror = _ => reject(new Error('error reading blob'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ export module Mock {
|
|||||||
long: 'Bitcoin is a decentralized consensus protocol and settlement network.',
|
long: 'Bitcoin is a decentralized consensus protocol and settlement network.',
|
||||||
},
|
},
|
||||||
'release-notes': 'Taproot, Schnorr, and more.',
|
'release-notes': 'Taproot, Schnorr, and more.',
|
||||||
|
assets: {
|
||||||
|
icon: 'icon.png',
|
||||||
|
license: 'LICENSE.md',
|
||||||
|
instructions: 'INSTRUCTIONS.md',
|
||||||
|
docker_images: 'image.tar',
|
||||||
|
assets: './assets',
|
||||||
|
scripts: './scripts',
|
||||||
|
},
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
'wrapper-repo': 'https://github.com/start9labs/bitcoind-wrapper',
|
'wrapper-repo': 'https://github.com/start9labs/bitcoind-wrapper',
|
||||||
'upstream-repo': 'https://github.com/bitcoin/bitcoin',
|
'upstream-repo': 'https://github.com/bitcoin/bitcoin',
|
||||||
@@ -348,6 +356,14 @@ export module Mock {
|
|||||||
long: 'More info about LND. More info about LND. More info about LND.',
|
long: 'More info about LND. More info about LND. More info about LND.',
|
||||||
},
|
},
|
||||||
'release-notes': 'Dual funded channels!',
|
'release-notes': 'Dual funded channels!',
|
||||||
|
assets: {
|
||||||
|
icon: 'icon.png',
|
||||||
|
license: 'LICENSE.md',
|
||||||
|
instructions: 'INSTRUCTIONS.md',
|
||||||
|
docker_images: 'image.tar',
|
||||||
|
assets: './assets',
|
||||||
|
scripts: './scripts',
|
||||||
|
},
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
'wrapper-repo': 'https://github.com/start9labs/lnd-wrapper',
|
'wrapper-repo': 'https://github.com/start9labs/lnd-wrapper',
|
||||||
'upstream-repo': 'https://github.com/lightningnetwork/lnd',
|
'upstream-repo': 'https://github.com/lightningnetwork/lnd',
|
||||||
@@ -494,6 +510,14 @@ export module Mock {
|
|||||||
long: 'More info about Bitcoin Proxy. More info about Bitcoin Proxy. More info about Bitcoin Proxy.',
|
long: 'More info about Bitcoin Proxy. More info about Bitcoin Proxy. More info about Bitcoin Proxy.',
|
||||||
},
|
},
|
||||||
'release-notes': 'Even better support for Bitcoin and wallets!',
|
'release-notes': 'Even better support for Bitcoin and wallets!',
|
||||||
|
assets: {
|
||||||
|
icon: 'icon.png',
|
||||||
|
license: 'LICENSE.md',
|
||||||
|
instructions: 'INSTRUCTIONS.md',
|
||||||
|
docker_images: 'image.tar',
|
||||||
|
assets: './assets',
|
||||||
|
scripts: './scripts',
|
||||||
|
},
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
'wrapper-repo': 'https://github.com/start9labs/btc-rpc-proxy-wrapper',
|
'wrapper-repo': 'https://github.com/start9labs/btc-rpc-proxy-wrapper',
|
||||||
'upstream-repo': 'https://github.com/Kixunil/btc-rpc-proxy',
|
'upstream-repo': 'https://github.com/Kixunil/btc-rpc-proxy',
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ export module RR {
|
|||||||
export type GetMarketplaceDataRes = MarketplaceData
|
export type GetMarketplaceDataRes = MarketplaceData
|
||||||
|
|
||||||
export type GetMarketplaceEOSReq = {
|
export type GetMarketplaceEOSReq = {
|
||||||
|
'server-id': string
|
||||||
'eos-version': string
|
'eos-version': string
|
||||||
}
|
}
|
||||||
export type GetMarketplaceEOSRes = MarketplaceEOS
|
export type GetMarketplaceEOSRes = MarketplaceEOS
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ export const mockPatchData: DataModel = {
|
|||||||
long: 'Bitcoin is a decentralized consensus protocol and settlement network.',
|
long: 'Bitcoin is a decentralized consensus protocol and settlement network.',
|
||||||
},
|
},
|
||||||
'release-notes': 'Taproot, Schnorr, and more.',
|
'release-notes': 'Taproot, Schnorr, and more.',
|
||||||
|
assets: {
|
||||||
|
icon: 'icon.png',
|
||||||
|
license: 'LICENSE.md',
|
||||||
|
instructions: 'INSTRUCTIONS.md',
|
||||||
|
docker_images: 'image.tar',
|
||||||
|
assets: './assets',
|
||||||
|
scripts: './scripts',
|
||||||
|
},
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
'wrapper-repo': 'https://github.com/start9labs/bitcoind-wrapper',
|
'wrapper-repo': 'https://github.com/start9labs/bitcoind-wrapper',
|
||||||
'upstream-repo': 'https://github.com/bitcoin/bitcoin',
|
'upstream-repo': 'https://github.com/bitcoin/bitcoin',
|
||||||
@@ -437,6 +445,14 @@ export const mockPatchData: DataModel = {
|
|||||||
long: 'More info about LND. More info about LND. More info about LND.',
|
long: 'More info about LND. More info about LND. More info about LND.',
|
||||||
},
|
},
|
||||||
'release-notes': 'Dual funded channels!',
|
'release-notes': 'Dual funded channels!',
|
||||||
|
assets: {
|
||||||
|
icon: 'icon.png',
|
||||||
|
license: 'LICENSE.md',
|
||||||
|
instructions: 'INSTRUCTIONS.md',
|
||||||
|
docker_images: 'image.tar',
|
||||||
|
assets: './assets',
|
||||||
|
scripts: './scripts',
|
||||||
|
},
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
'wrapper-repo': 'https://github.com/start9labs/lnd-wrapper',
|
'wrapper-repo': 'https://github.com/start9labs/lnd-wrapper',
|
||||||
'upstream-repo': 'https://github.com/lightningnetwork/lnd',
|
'upstream-repo': 'https://github.com/lightningnetwork/lnd',
|
||||||
|
|||||||
@@ -50,15 +50,13 @@ export class EOSService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async getEOS(): Promise<boolean> {
|
async getEOS(): Promise<boolean> {
|
||||||
const version = this.patch.getData()['server-info'].version
|
const server = this.patch.getData()['server-info']
|
||||||
|
const version = server.version
|
||||||
this.eos = await this.api.getEos({
|
this.eos = await this.api.getEos({
|
||||||
|
'server-id': server.id,
|
||||||
'eos-version': version,
|
'eos-version': version,
|
||||||
})
|
})
|
||||||
const updateAvailable =
|
const updateAvailable = this.emver.compare(this.eos.version, version) === 1
|
||||||
this.emver.compare(
|
|
||||||
this.eos.version,
|
|
||||||
this.patch.getData()['server-info'].version,
|
|
||||||
) === 1
|
|
||||||
this.updateAvailable$.next(updateAvailable)
|
this.updateAvailable$.next(updateAvailable)
|
||||||
return updateAvailable
|
return updateAvailable
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ConfigSpec } from 'src/app/pkg-config/config-types'
|
|||||||
import { Url } from '@start9labs/shared'
|
import { Url } from '@start9labs/shared'
|
||||||
import { MarketplaceManifest } from '@start9labs/marketplace'
|
import { MarketplaceManifest } from '@start9labs/marketplace'
|
||||||
import { BasicInfo } from 'src/app/pages/developer-routes/developer-menu/form-info'
|
import { BasicInfo } from 'src/app/pages/developer-routes/developer-menu/form-info'
|
||||||
|
import { string } from 'ts-matches'
|
||||||
|
|
||||||
export interface DataModel {
|
export interface DataModel {
|
||||||
'server-info': ServerInfo
|
'server-info': ServerInfo
|
||||||
@@ -120,6 +121,14 @@ export interface CurrentDependencyInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Manifest extends MarketplaceManifest<DependencyConfig | null> {
|
export interface Manifest extends MarketplaceManifest<DependencyConfig | null> {
|
||||||
|
assets: {
|
||||||
|
license: string // filename
|
||||||
|
instructions: string // filename
|
||||||
|
icon: string // filename
|
||||||
|
docker_images: string // filename
|
||||||
|
assets: string // path to assets folder
|
||||||
|
scripts: string // path to scripts folder
|
||||||
|
}
|
||||||
main: ActionImpl
|
main: ActionImpl
|
||||||
'health-checks': Record<
|
'health-checks': Record<
|
||||||
string,
|
string,
|
||||||
|
|||||||
Reference in New Issue
Block a user