mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
better interfaces abstractions
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
inject,
|
||||
} from '@angular/core'
|
||||
import { AddressItemComponent } from './address-item.component'
|
||||
import { TuiButtonModule } from '@taiga-ui/experimental'
|
||||
import { AddressDetails, AddressesService } from './interface.utils'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-address-group',
|
||||
template: `
|
||||
<div>
|
||||
@if (addresses.length) {
|
||||
<button
|
||||
class="icon-add-btn"
|
||||
tuiIconButton
|
||||
appearance="secondary"
|
||||
iconLeft="tuiIconPlus"
|
||||
(click)="service.add()"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
}
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
@for (address of addresses; track $index) {
|
||||
<app-address-item [label]="address.label" [address]="address.url" />
|
||||
} @empty {
|
||||
<button
|
||||
tuiButton
|
||||
iconLeft="tuiIconPlus"
|
||||
[style.align-self]="'flex-start'"
|
||||
(click)="service.add()"
|
||||
>
|
||||
Add Address
|
||||
</button>
|
||||
}
|
||||
`,
|
||||
imports: [AddressItemComponent, TuiButtonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
styles: `
|
||||
.icon-add-btn {
|
||||
float: right;
|
||||
margin-left: 2rem;
|
||||
}
|
||||
`,
|
||||
})
|
||||
export class AddressGroupComponent {
|
||||
readonly service = inject(AddressesService)
|
||||
|
||||
@Input({ required: true }) addresses!: AddressDetails[]
|
||||
}
|
||||
@@ -17,20 +17,24 @@ import {
|
||||
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
|
||||
import { QRComponent } from 'src/app/common/qr.component'
|
||||
import { mask } from 'src/app/util/mask'
|
||||
import { InterfaceComponent } from './interface.component'
|
||||
import { AddressesService } from './interface.utils'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-interface-address',
|
||||
selector: 'app-address-item',
|
||||
template: `
|
||||
<div tuiCell>
|
||||
<tui-badge appearance="success">
|
||||
{{ label }}
|
||||
</tui-badge>
|
||||
<h3 tuiTitle>
|
||||
<span tuiSubtitle>{{ isMasked ? mask : address }}</span>
|
||||
<span tuiSubtitle>
|
||||
{{ interface.serviceInterface.masked ? mask : address }}
|
||||
</span>
|
||||
</h3>
|
||||
<button
|
||||
*ngIf="isUi"
|
||||
*ngIf="interface.serviceInterface.type === 'ui'"
|
||||
tuiIconButton
|
||||
iconLeft="tuiIconExternalLink"
|
||||
appearance="icon"
|
||||
@@ -58,7 +62,7 @@ import { mask } from 'src/app/util/mask'
|
||||
tuiIconButton
|
||||
iconLeft="tuiIconTrash"
|
||||
appearance="icon"
|
||||
(click)="destroy()"
|
||||
(click)="service.remove()"
|
||||
>
|
||||
Destroy
|
||||
</button>
|
||||
@@ -73,15 +77,16 @@ import { mask } from 'src/app/util/mask'
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class InterfaceAddressComponent {
|
||||
export class AddressItemComponent {
|
||||
private readonly window = inject(WINDOW)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
|
||||
readonly service = inject(AddressesService)
|
||||
readonly copyService = inject(CopyService)
|
||||
readonly interface = inject(InterfaceComponent)
|
||||
|
||||
@Input() label?: string
|
||||
@Input({ required: true }) address!: string
|
||||
@Input({ required: true }) isMasked!: boolean
|
||||
@Input({ required: true }) isUi!: boolean
|
||||
|
||||
get mask(): string {
|
||||
return mask(this.address, 64)
|
||||
@@ -99,6 +104,4 @@ export class InterfaceAddressComponent {
|
||||
})
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
destroy() {}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import { Directive, Input } from '@angular/core'
|
||||
import { AddressesService } from '../interface.utils'
|
||||
import { inject } from '@angular/core'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { TuiDialogOptions } from '@taiga-ui/core'
|
||||
import {
|
||||
FormComponent,
|
||||
FormContext,
|
||||
} from 'src/app/apps/portal/components/form.component'
|
||||
import { getClearnetSpec } from 'src/app/apps/portal/components/interfaces/interface.utils'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { FormDialogService } from 'src/app/services/form-dialog.service'
|
||||
import { NetworkInfo } from 'src/app/services/patch-db/data-model'
|
||||
import { InterfaceComponent } from '../interface.component'
|
||||
|
||||
type ClearnetForm = {
|
||||
domain: string
|
||||
subdomain: string | null
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: true,
|
||||
selector: '[clearnetAddresses]',
|
||||
providers: [
|
||||
{ provide: AddressesService, useExisting: ClearnetAddressesDirective },
|
||||
],
|
||||
})
|
||||
export class ClearnetAddressesDirective implements AddressesService {
|
||||
private readonly formDialog = inject(FormDialogService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly interface = inject(InterfaceComponent)
|
||||
|
||||
@Input({ required: true }) network!: NetworkInfo
|
||||
|
||||
async add() {
|
||||
const options: Partial<TuiDialogOptions<FormContext<ClearnetForm>>> = {
|
||||
label: 'Select Domain/Subdomain',
|
||||
data: {
|
||||
spec: await getClearnetSpec(this.network),
|
||||
buttons: [
|
||||
{
|
||||
text: 'Manage domains',
|
||||
link: 'portal/system/settings/domains',
|
||||
},
|
||||
{
|
||||
text: 'Save',
|
||||
handler: async value => this.save(value),
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
this.formDialog.open(FormComponent, options)
|
||||
}
|
||||
|
||||
async remove() {}
|
||||
|
||||
private async save(domainInfo: ClearnetForm): Promise<boolean> {
|
||||
const loader = this.loader.open('Saving...').subscribe()
|
||||
|
||||
try {
|
||||
if (this.interface.packageContext) {
|
||||
await this.api.setInterfaceClearnetAddress({
|
||||
...this.interface.packageContext,
|
||||
domainInfo,
|
||||
})
|
||||
} else {
|
||||
await this.api.setServerClearnetAddress({ domainInfo })
|
||||
}
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errorService.handleError(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.unsubscribe()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Directive } from '@angular/core'
|
||||
import { AddressesService } from '../interface.utils'
|
||||
|
||||
@Directive({
|
||||
standalone: true,
|
||||
selector: '[localAddresses]',
|
||||
providers: [
|
||||
{ provide: AddressesService, useExisting: LocalAddressesDirective },
|
||||
],
|
||||
})
|
||||
export class LocalAddressesDirective implements AddressesService {
|
||||
async add() {}
|
||||
async remove() {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Directive } from '@angular/core'
|
||||
import { AddressesService } from '../interface.utils'
|
||||
|
||||
@Directive({
|
||||
standalone: true,
|
||||
selector: '[torAddresses]',
|
||||
providers: [
|
||||
{ provide: AddressesService, useExisting: TorAddressesDirective },
|
||||
],
|
||||
})
|
||||
export class TorAddressesDirective implements AddressesService {
|
||||
async add() {}
|
||||
async remove() {}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
import { NgForOf, NgIf } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
} from '@angular/core'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { TuiDialogOptions, TuiDialogService } from '@taiga-ui/core'
|
||||
import { TuiButtonModule } from '@taiga-ui/experimental'
|
||||
import { TUI_PROMPT } from '@taiga-ui/kit'
|
||||
import { filter } from 'rxjs'
|
||||
import {
|
||||
FormComponent,
|
||||
FormContext,
|
||||
} from 'src/app/apps/portal/components/form.component'
|
||||
import {
|
||||
getClearnetSpec,
|
||||
REMOVE,
|
||||
} from 'src/app/apps/portal/components/interfaces/interface.utils'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { FormDialogService } from 'src/app/services/form-dialog.service'
|
||||
import { NetworkInfo } from 'src/app/services/patch-db/data-model'
|
||||
import { InterfaceAddressComponent } from './interface-addresses.component'
|
||||
import { InterfaceComponent } from './interface.component'
|
||||
|
||||
type ClearnetForm = {
|
||||
domain: string
|
||||
subdomain: string | null
|
||||
}
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-interface-clearnet',
|
||||
template: `
|
||||
<em>
|
||||
Add clearnet to expose this interface to the public Internet.
|
||||
<a
|
||||
href="https://docs.start9.com/latest/user-manual/interface-addresses#clearnet"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<strong>View instructions</strong>
|
||||
</a>
|
||||
</em>
|
||||
@for (
|
||||
address of interface.serviceInterface.addresses.clearnet;
|
||||
track $index
|
||||
) {
|
||||
<app-interface-address
|
||||
[label]="address.label"
|
||||
[address]="address.url"
|
||||
[isMasked]="interface.serviceInterface.masked"
|
||||
[isUi]="interface.serviceInterface.type === 'ui'"
|
||||
/>
|
||||
} @empty {
|
||||
<button
|
||||
tuiButton
|
||||
iconLeft="tuiIconPlus"
|
||||
[style.align-self]="'flex-start'"
|
||||
(click)="add()"
|
||||
>
|
||||
Add Address
|
||||
</button>
|
||||
}
|
||||
`,
|
||||
imports: [NgForOf, InterfaceAddressComponent, NgIf, TuiButtonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class InterfaceClearnetComponent {
|
||||
private readonly formDialog = inject(FormDialogService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
readonly interface = inject(InterfaceComponent)
|
||||
|
||||
@Input({ required: true }) network!: NetworkInfo
|
||||
|
||||
async add() {
|
||||
const options: Partial<TuiDialogOptions<FormContext<ClearnetForm>>> = {
|
||||
label: 'Select Domain/Subdomain',
|
||||
data: {
|
||||
spec: await getClearnetSpec(this.network),
|
||||
buttons: [
|
||||
{
|
||||
text: 'Manage domains',
|
||||
link: 'portal/system/settings/domains',
|
||||
},
|
||||
{
|
||||
text: 'Save',
|
||||
handler: async value => this.save(value),
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
this.formDialog.open(FormComponent, options)
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.dialogs
|
||||
.open(TUI_PROMPT, REMOVE)
|
||||
.pipe(filter(Boolean))
|
||||
.subscribe(async () => {
|
||||
const loader = this.loader.open('Removing...').subscribe()
|
||||
|
||||
try {
|
||||
if (this.interface.packageContext) {
|
||||
await this.api.setInterfaceClearnetAddress({
|
||||
...this.interface.packageContext,
|
||||
domainInfo: null,
|
||||
})
|
||||
} else {
|
||||
await this.api.setServerClearnetAddress({ domainInfo: null })
|
||||
}
|
||||
} catch (e: any) {
|
||||
this.errorService.handleError(e)
|
||||
} finally {
|
||||
loader.unsubscribe()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private async save(domainInfo: ClearnetForm): Promise<boolean> {
|
||||
const loader = this.loader.open('Saving...').subscribe()
|
||||
|
||||
try {
|
||||
if (this.interface.packageContext) {
|
||||
await this.api.setInterfaceClearnetAddress({
|
||||
...this.interface.packageContext,
|
||||
domainInfo,
|
||||
})
|
||||
} else {
|
||||
await this.api.setServerClearnetAddress({ domainInfo })
|
||||
}
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errorService.handleError(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.unsubscribe()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import { NgForOf, NgIf } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { TuiButtonModule } from '@taiga-ui/experimental'
|
||||
import { InterfaceComponent } from './interface.component'
|
||||
import { InterfaceAddressComponent } from './interface-addresses.component'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-interface-local',
|
||||
template: `
|
||||
<em>
|
||||
Local addresses can only be accessed while connected to the same Local
|
||||
Area Network (LAN) as your server, either directly or using a VPN.
|
||||
<a
|
||||
href="https://docs.start9.com/latest/user-manual/interface-addresses#local"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<strong>View instructions</strong>
|
||||
</a>
|
||||
</em>
|
||||
|
||||
@for (address of interface.serviceInterface.addresses.local; track $index) {
|
||||
<app-interface-address
|
||||
[label]="address.label"
|
||||
[address]="address.url"
|
||||
[isMasked]="interface.serviceInterface.masked"
|
||||
[isUi]="interface.serviceInterface.type === 'ui'"
|
||||
/>
|
||||
} @empty {
|
||||
<button
|
||||
tuiButton
|
||||
iconLeft="tuiIconPlus"
|
||||
[style.align-self]="'flex-start'"
|
||||
(click)="add()"
|
||||
>
|
||||
Add Address
|
||||
</button>
|
||||
}
|
||||
`,
|
||||
imports: [NgForOf, NgIf, InterfaceAddressComponent, TuiButtonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class InterfaceLocalComponent {
|
||||
readonly interface = inject(InterfaceComponent)
|
||||
|
||||
async add() {}
|
||||
|
||||
async remove() {}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { InterfaceAddressComponent } from './interface-addresses.component'
|
||||
import { InterfaceComponent } from './interface.component'
|
||||
import { NgForOf, NgIf } from '@angular/common'
|
||||
import { TuiButtonModule } from '@taiga-ui/experimental'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-interface-tor',
|
||||
template: `
|
||||
<em>
|
||||
Use a Tor-enabled browser to access this address. Tor connections can be
|
||||
slow and unreliable.
|
||||
<a
|
||||
href="https://docs.start9.com/latest/user-manual/interface-addresses#tor"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<strong>View instructions</strong>
|
||||
</a>
|
||||
</em>
|
||||
|
||||
@for (address of interface.serviceInterface.addresses.tor; track $index) {
|
||||
<app-interface-address
|
||||
[label]="address.label"
|
||||
[address]="address.url"
|
||||
[isMasked]="interface.serviceInterface.masked"
|
||||
[isUi]="interface.serviceInterface.type === 'ui'"
|
||||
/>
|
||||
} @empty {
|
||||
<button
|
||||
tuiButton
|
||||
iconLeft="tuiIconPlus"
|
||||
[style.align-self]="'flex-start'"
|
||||
(click)="add()"
|
||||
>
|
||||
Add Address
|
||||
</button>
|
||||
}
|
||||
`,
|
||||
imports: [NgForOf, NgIf, InterfaceAddressComponent, TuiButtonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class InterfaceTorComponent {
|
||||
readonly interface = inject(InterfaceComponent)
|
||||
|
||||
async add() {}
|
||||
|
||||
async remove() {}
|
||||
}
|
||||
@@ -8,38 +8,89 @@ import {
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TuiCardModule, TuiSurfaceModule } from '@taiga-ui/experimental'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { InterfaceClearnetComponent } from 'src/app/apps/portal/components/interfaces/interface-clearnet.component'
|
||||
import { InterfaceLocalComponent } from 'src/app/apps/portal/components/interfaces/interface-local.component'
|
||||
import { InterfaceTorComponent } from 'src/app/apps/portal/components/interfaces/interface-tor.component'
|
||||
import { AddressGroupComponent } from 'src/app/apps/portal/components/interfaces/address-group.component'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
import { AddressDetails } from './interface.utils'
|
||||
import { ClearnetAddressesDirective } from './directives/clearnet.directive'
|
||||
import { LocalAddressesDirective } from './directives/local.directive'
|
||||
import { TorAddressesDirective } from './directives/tor.directive'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-interface',
|
||||
template: `
|
||||
<h3 class="g-title">Clearnet</h3>
|
||||
<app-interface-clearnet
|
||||
<app-address-group
|
||||
*ngIf="network$ | async as network"
|
||||
clearnetAddresses
|
||||
tuiCardLarge="compact"
|
||||
tuiSurface="elevated"
|
||||
[network]="network"
|
||||
/>
|
||||
[addresses]="serviceInterface.addresses.clearnet"
|
||||
>
|
||||
<em>
|
||||
Add a clearnet address to expose this interface on the Internet.
|
||||
Clearnet addresses are fully public and not anonymous.
|
||||
<a
|
||||
href="https://docs.start9.com/latest/user-manual/interface-addresses#clearnet"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<strong>Learn More</strong>
|
||||
</a>
|
||||
</em>
|
||||
</app-address-group>
|
||||
|
||||
<h3 class="g-title">Tor</h3>
|
||||
<app-interface-tor tuiCardLarge="compact" tuiSurface="elevated" />
|
||||
<app-address-group
|
||||
torAddresses
|
||||
tuiCardLarge="compact"
|
||||
tuiSurface="elevated"
|
||||
[addresses]="serviceInterface.addresses.tor"
|
||||
>
|
||||
<em>
|
||||
Add an onion address to anonymously expose this interface on the
|
||||
darknet. Onion addresses can only be reached over the Tor network.
|
||||
<a
|
||||
href="https://docs.start9.com/latest/user-manual/interface-addresses#tor"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<strong>Learn More</strong>
|
||||
</a>
|
||||
</em>
|
||||
</app-address-group>
|
||||
|
||||
<h3 class="g-title">Local</h3>
|
||||
<app-interface-local tuiCardLarge="compact" tuiSurface="elevated" />
|
||||
<app-address-group
|
||||
localAddresses
|
||||
tuiCardLarge="compact"
|
||||
tuiSurface="elevated"
|
||||
[addresses]="serviceInterface.addresses.local"
|
||||
>
|
||||
<em>
|
||||
Add a local address to expose this interface on your Local Area Network
|
||||
(LAN). Local addresses can only be accessed by devices connected to the
|
||||
same LAN as your server, either directly or using a VPN.
|
||||
<a
|
||||
href="https://docs.start9.com/latest/user-manual/interface-addresses#local"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<strong>Learn More</strong>
|
||||
</a>
|
||||
</em>
|
||||
</app-address-group>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
CommonModule,
|
||||
InterfaceTorComponent,
|
||||
InterfaceLocalComponent,
|
||||
InterfaceClearnetComponent,
|
||||
AddressGroupComponent,
|
||||
TuiCardModule,
|
||||
TuiSurfaceModule,
|
||||
ClearnetAddressesDirective,
|
||||
TorAddressesDirective,
|
||||
LocalAddressesDirective,
|
||||
],
|
||||
})
|
||||
export class InterfaceComponent {
|
||||
|
||||
@@ -4,6 +4,11 @@ import { TuiPromptData } from '@taiga-ui/kit'
|
||||
import { NetworkInfo } from 'src/app/services/patch-db/data-model'
|
||||
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
||||
|
||||
export abstract class AddressesService {
|
||||
abstract add(): Promise<void>
|
||||
abstract remove(): Promise<void>
|
||||
}
|
||||
|
||||
export const REMOVE: Partial<TuiDialogOptions<TuiPromptData>> = {
|
||||
label: 'Confirm',
|
||||
size: 's',
|
||||
|
||||
@@ -82,7 +82,7 @@ export class ControlsComponent {
|
||||
return this.errors.getPkgDepErrors$(id).pipe(
|
||||
map(errors =>
|
||||
Object.keys(this.pkg.currentDependencies)
|
||||
.map(id => !!(errors[id] as any)?.[id]) // @TODO fix
|
||||
.map(id => !!(errors[id] as any)?.[id]) // @TODO-Alex fix
|
||||
.some(Boolean),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -122,7 +122,7 @@ export class SettingsService {
|
||||
await this.proxyService.presentModalSetOutboundProxy(proxy)
|
||||
}
|
||||
|
||||
// @TODO previous this was done in experimental settings using a template ref.
|
||||
// @TODO-Alex previous this was done in experimental settings using a template ref.
|
||||
private promptResetTor() {
|
||||
this.dialogs
|
||||
.open(TUI_PROMPT, {
|
||||
|
||||
@@ -27,7 +27,7 @@ export async function parseS9pk(file: File): Promise<MarketplacePkg> {
|
||||
|
||||
const manifest = await getAsset(positions, file, 'manifest')
|
||||
const [icon] = await Promise.all([
|
||||
await getIcon(positions, file, manifest),
|
||||
await getIcon(positions, file),
|
||||
// getAsset(positions, file, 'license'),
|
||||
// getAsset(positions, file, 'instructions'),
|
||||
])
|
||||
@@ -147,11 +147,7 @@ async function getAsset(
|
||||
return cbor.decode(data, true)
|
||||
}
|
||||
|
||||
async function getIcon(
|
||||
positions: Positions,
|
||||
file: Blob,
|
||||
manifest: Manifest,
|
||||
): Promise<string> {
|
||||
async function getIcon(positions: Positions, file: Blob): Promise<string> {
|
||||
const contentType = '' // @TODO
|
||||
const data = file.slice(
|
||||
Number(positions['icon'][0]),
|
||||
|
||||
@@ -73,7 +73,7 @@ export class BadgeService {
|
||||
new Set<string>(),
|
||||
).size,
|
||||
),
|
||||
// @TODO shareReplay is preventing the badge from decrementing
|
||||
// @TODO-Alex shareReplay is preventing the badge from decrementing
|
||||
shareReplay(1),
|
||||
)
|
||||
|
||||
|
||||
@@ -1283,7 +1283,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: `/packageData/${params.packageId}/installed/interfaceInfo/${params.interfaceId}/addressInfo/domainInfo`,
|
||||
path: `/packageData/${params.packageId}/serviceInterfaces/${params.interfaceId}/addressInfo/domainInfo`,
|
||||
value: params.domainInfo,
|
||||
},
|
||||
]
|
||||
@@ -1299,7 +1299,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: `/packageData/${params.packageId}/installed/outboundProxy`,
|
||||
path: `/packageData/${params.packageId}/outboundProxy`,
|
||||
value: params.proxy,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@ import { LocalStorageBootstrap } from './patch-db/local-storage-bootstrap'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class PatchMonitorService extends Observable<any> {
|
||||
// @TODO not happy with Observable<void>
|
||||
// @TODO-Alex not happy with Observable<void>
|
||||
private readonly stream$ = this.authService.isVerified$.pipe(
|
||||
tap(verified =>
|
||||
verified ? this.patch.start(this.bootstrapper) : this.patch.stop(),
|
||||
|
||||
Reference in New Issue
Block a user