mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
More 036 Frontend changes (#2572)
* update patchDB for futuristic revisions * interfaces display updates * remove zram and move tor to settings
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
<ion-content class="ion-padding-top with-widgets">
|
||||
<ion-item-group *ngIf="serviceInterfaces$ | async as serviceInterfaces">
|
||||
<ng-container *ngIf="serviceInterfaces.ui.length">
|
||||
<ion-item-divider>User Interfaces (UI)</ion-item-divider>
|
||||
<ion-item-divider>User Interfaces</ion-item-divider>
|
||||
<app-interfaces-item
|
||||
*ngFor="let ui of serviceInterfaces.ui"
|
||||
[iFace]="ui"
|
||||
@@ -18,7 +18,7 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="serviceInterfaces.api.length">
|
||||
<ion-item-divider>Application Program Interfaces (API)</ion-item-divider>
|
||||
<ion-item-divider>Application Program Interfaces</ion-item-divider>
|
||||
<app-interfaces-item
|
||||
*ngFor="let api of serviceInterfaces.api"
|
||||
[iFace]="api"
|
||||
@@ -26,7 +26,7 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="serviceInterfaces.p2p.length">
|
||||
<ion-item-divider>Peer-To-Peer Interfaces (P2P)</ion-item-divider>
|
||||
<ion-item-divider>Peer-To-Peer Interfaces</ion-item-divider>
|
||||
<app-interfaces-item
|
||||
*ngFor="let p2p of serviceInterfaces.p2p"
|
||||
[iFace]="p2p"
|
||||
|
||||
@@ -116,49 +116,54 @@ function getAddresses(
|
||||
? [host.hostname]
|
||||
: []
|
||||
|
||||
return hostnames
|
||||
.map((h: any) => {
|
||||
const addresses: MappedAddress[] = []
|
||||
const addresses: MappedAddress[] = []
|
||||
|
||||
let name = ''
|
||||
let hostname = ''
|
||||
hostnames.forEach(h => {
|
||||
let name = ''
|
||||
let hostname = ''
|
||||
|
||||
if (h.kind === 'onion') {
|
||||
name = 'Tor'
|
||||
hostname = h.hostname.value
|
||||
if (h.kind === 'onion') {
|
||||
name = 'Tor'
|
||||
hostname = h.hostname.value
|
||||
} else {
|
||||
const hostnameKind = h.hostname.kind
|
||||
|
||||
if (hostnameKind === 'domain') {
|
||||
name = 'Domain'
|
||||
hostname = `${h.hostname.subdomain}.${h.hostname.domain}`
|
||||
} else {
|
||||
name = h.hostname.kind
|
||||
hostname =
|
||||
h.hostname.kind === 'domain'
|
||||
? `${h.hostname.subdomain}.${h.hostname.domain}`
|
||||
: h.hostname.value
|
||||
name =
|
||||
hostnameKind === 'local'
|
||||
? 'Local'
|
||||
: `${h.networkInterfaceId} (${hostnameKind})`
|
||||
hostname = h.hostname.value
|
||||
}
|
||||
}
|
||||
|
||||
if (h.hostname.sslPort) {
|
||||
const port = h.hostname.sslPort === 443 ? '' : `:${h.hostname.sslPort}`
|
||||
const scheme = addressInfo.bindOptions.addSsl?.scheme
|
||||
? `${addressInfo.bindOptions.addSsl.scheme}://`
|
||||
: ''
|
||||
if (h.hostname.sslPort) {
|
||||
const port = h.hostname.sslPort === 443 ? '' : `:${h.hostname.sslPort}`
|
||||
const scheme = addressInfo.bindOptions.addSsl?.scheme
|
||||
? `${addressInfo.bindOptions.addSsl.scheme}://`
|
||||
: ''
|
||||
|
||||
addresses.push({
|
||||
name,
|
||||
url: `${scheme}${username}${hostname}${port}${suffix}`,
|
||||
})
|
||||
}
|
||||
addresses.push({
|
||||
name: name === 'Tor' ? 'Tor (HTTPS)' : name,
|
||||
url: `${scheme}${username}${hostname}${port}${suffix}`,
|
||||
})
|
||||
}
|
||||
|
||||
if (h.hostname.port) {
|
||||
const port = h.hostname.port === 80 ? '' : `:${h.hostname.port}`
|
||||
const scheme = addressInfo.bindOptions.scheme
|
||||
? `${addressInfo.bindOptions.scheme}://`
|
||||
: ''
|
||||
if (h.hostname.port) {
|
||||
const port = h.hostname.port === 80 ? '' : `:${h.hostname.port}`
|
||||
const scheme = addressInfo.bindOptions.scheme
|
||||
? `${addressInfo.bindOptions.scheme}://`
|
||||
: ''
|
||||
|
||||
addresses.push({
|
||||
name,
|
||||
url: `${scheme}${username}${hostname}${port}${suffix}`,
|
||||
})
|
||||
}
|
||||
addresses.push({
|
||||
name: name === 'Tor' ? 'Tor (HTTP)' : name,
|
||||
url: `${scheme}${username}${hostname}${port}${suffix}`,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return addresses
|
||||
})
|
||||
.flat()
|
||||
return addresses
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { ExperimentalFeaturesPage } from './experimental-features.page'
|
||||
import { EmverPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ExperimentalFeaturesPage,
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
EmverPipesModule,
|
||||
],
|
||||
declarations: [ExperimentalFeaturesPage],
|
||||
})
|
||||
export class ExperimentalFeaturesPageModule {}
|
||||
@@ -1,36 +0,0 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button defaultHref="system"></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Experimental Features</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="with-widgets">
|
||||
<ion-item-group *ngIf="server$ | async as server">
|
||||
<ion-item button (click)="presentAlertResetTor()">
|
||||
<ion-icon slot="start" name="reload"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>Reset Tor</h2>
|
||||
<p>
|
||||
Resetting the Tor daemon on your server may resolve Tor connectivity
|
||||
issues.
|
||||
</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button (click)="presentAlertZram(server.zram)">
|
||||
<ion-icon
|
||||
slot="start"
|
||||
[name]="server.zram ? 'flash-off-outline' : 'flash-outline'"
|
||||
></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ server.zram ? 'Disable' : 'Enable' }} zram</h2>
|
||||
<p>
|
||||
Zram creates compressed swap in memory, resulting in faster I/O for
|
||||
low RAM devices
|
||||
</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
</ion-content>
|
||||
@@ -1,151 +0,0 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
||||
import {
|
||||
AlertController,
|
||||
LoadingController,
|
||||
ToastController,
|
||||
} from '@ionic/angular'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
import { ErrorToastService } from '@start9labs/shared'
|
||||
|
||||
@Component({
|
||||
selector: 'experimental-features',
|
||||
templateUrl: './experimental-features.page.html',
|
||||
styleUrls: ['./experimental-features.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ExperimentalFeaturesPage {
|
||||
readonly server$ = this.patch.watch$('server-info')
|
||||
|
||||
constructor(
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly patch: PatchDB<DataModel>,
|
||||
private readonly config: ConfigService,
|
||||
private readonly alertCtrl: AlertController,
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly api: ApiService,
|
||||
private readonly errToast: ErrorToastService,
|
||||
) {}
|
||||
|
||||
async presentAlertResetTor() {
|
||||
const isTor = this.config.isTor()
|
||||
const shared =
|
||||
'Optionally wipe state to forcibly acquire new guard nodes. It is recommended to try without wiping state first.'
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: isTor ? 'Warning' : 'Confirm',
|
||||
message: isTor
|
||||
? `You are currently connected over Tor. If you reset the Tor daemon, you will loose connectivity until it comes back online.<br/><br/>${shared}`
|
||||
: `Reset Tor?<br/><br/>${shared}`,
|
||||
inputs: [
|
||||
{
|
||||
label: 'Wipe state',
|
||||
type: 'checkbox',
|
||||
value: 'wipe',
|
||||
},
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'Reset',
|
||||
handler: (value: string[]) => {
|
||||
this.resetTor(value.some(v => v === 'wipe'))
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
cssClass: isTor ? 'alert-warning-message' : '',
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentAlertZram(enabled: boolean) {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Confirm',
|
||||
message: enabled
|
||||
? 'Are you sure you want to disable zram? It provides significant performance benefits on low RAM devices.'
|
||||
: 'Enable zram? It will only make a difference on lower RAM devices.',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
},
|
||||
{
|
||||
text: enabled ? 'Disable' : 'Enable',
|
||||
handler: () => {
|
||||
this.toggleZram(enabled)
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
private async resetTor(wipeState: boolean) {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Resetting Tor...',
|
||||
})
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.api.resetTor({
|
||||
'wipe-state': wipeState,
|
||||
reason: 'User triggered',
|
||||
})
|
||||
const toast = await this.toastCtrl.create({
|
||||
header: 'Tor reset in progress',
|
||||
position: 'bottom',
|
||||
duration: 4000,
|
||||
buttons: [
|
||||
{
|
||||
side: 'start',
|
||||
icon: 'close',
|
||||
handler: () => {
|
||||
return true
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
await toast.present()
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private async toggleZram(enabled: boolean) {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: enabled ? 'Disabling zram...' : 'Enabling zram...',
|
||||
})
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.api.toggleZram({ enable: !enabled })
|
||||
const toast = await this.toastCtrl.create({
|
||||
header: `Zram ${enabled ? 'disabled' : 'enabled'}`,
|
||||
position: 'bottom',
|
||||
duration: 4000,
|
||||
buttons: [
|
||||
{
|
||||
side: 'start',
|
||||
icon: 'close',
|
||||
handler: () => {
|
||||
return true
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
await toast.present()
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,13 +80,6 @@ const routes: Routes = [
|
||||
loadChildren: () =>
|
||||
import('./wifi/wifi.module').then(m => m.WifiPageModule),
|
||||
},
|
||||
{
|
||||
path: 'experimental-features',
|
||||
loadChildren: () =>
|
||||
import('./experimental-features/experimental-features.module').then(
|
||||
m => m.ExperimentalFeaturesPageModule,
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -54,6 +54,7 @@ export class ServerShowPage {
|
||||
private readonly ClientStorageService: ClientStorageService,
|
||||
private readonly authService: AuthService,
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly config: ConfigService,
|
||||
@Inject(WINDOW) private readonly windowRef: Window,
|
||||
) {}
|
||||
|
||||
@@ -178,6 +179,73 @@ export class ServerShowPage {
|
||||
}
|
||||
}
|
||||
|
||||
async presentAlertResetTor() {
|
||||
const isTor = this.config.isTor()
|
||||
const shared =
|
||||
'Optionally wipe state to forcibly acquire new guard nodes. It is recommended to try without wiping state first.'
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: isTor ? 'Warning' : 'Confirm',
|
||||
message: isTor
|
||||
? `You are currently connected over Tor. If you reset the Tor daemon, you will loose connectivity until it comes back online.<br/><br/>${shared}`
|
||||
: `Reset Tor?<br/><br/>${shared}`,
|
||||
inputs: [
|
||||
{
|
||||
label: 'Wipe state',
|
||||
type: 'checkbox',
|
||||
value: 'wipe',
|
||||
},
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'Reset',
|
||||
handler: (value: string[]) => {
|
||||
this.resetTor(value.some(v => v === 'wipe'))
|
||||
},
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
cssClass: isTor ? 'alert-warning-message' : '',
|
||||
})
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
private async resetTor(wipeState: boolean) {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Resetting Tor...',
|
||||
})
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.embassyApi.resetTor({
|
||||
'wipe-state': wipeState,
|
||||
reason: 'User triggered',
|
||||
})
|
||||
const toast = await this.toastCtrl.create({
|
||||
header: 'Tor reset in progress',
|
||||
position: 'bottom',
|
||||
duration: 4000,
|
||||
buttons: [
|
||||
{
|
||||
side: 'start',
|
||||
icon: 'close',
|
||||
handler: () => {
|
||||
return true
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
await toast.present()
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
async updateEos(): Promise<void> {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: OSUpdatePage,
|
||||
@@ -512,14 +580,11 @@ export class ServerShowPage {
|
||||
disabled$: of(false),
|
||||
},
|
||||
{
|
||||
title: 'Experimental Features',
|
||||
description: 'Try out new and potentially unstable new features',
|
||||
icon: 'flask-outline',
|
||||
action: () =>
|
||||
this.navCtrl.navigateForward(['experimental-features'], {
|
||||
relativeTo: this.route,
|
||||
}),
|
||||
detail: true,
|
||||
title: 'Reset Tor',
|
||||
description: 'May help resolve Tor connectivity issues.',
|
||||
icon: 'reload-circle-outline',
|
||||
action: () => this.presentAlertResetTor(),
|
||||
detail: false,
|
||||
disabled$: of(false),
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user