mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
remove share-stats, cosmetic improvements
This commit is contained in:
committed by
Keagan McClelland
parent
5326de9b84
commit
20acd8efea
@@ -15,9 +15,10 @@
|
||||
"build:setup-wizard": "ng run setup-wizard:build",
|
||||
"build:ui": "ng run ui:build && tsc projects/ui/postprocess.ts && node projects/ui/postprocess.js && git log | head -n1 > dist/ui/git-hash.txt",
|
||||
"build:all": "npm run build:deps && npm run build:diagnostic-ui && npm run build:setup-wizard && npm run build:ui",
|
||||
"start:diagnostic-ui": "ionic serve --project diagnostic-ui",
|
||||
"start:setup-wizard": "ionic serve --project setup-wizard",
|
||||
"start:ui": "ionic serve --project ui"
|
||||
"start:diagnostic-ui": "npm run copy-git-hash && ionic serve --project diagnostic-ui",
|
||||
"start:setup-wizard": "npm run copy-git-hash && ionic serve --project setup-wizard",
|
||||
"start:ui": "npm run copy-git-hash && ionic serve --project ui",
|
||||
"copy-git-hash": "./update-git-hash.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^13.2.0",
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<ion-icon
|
||||
*ngIf="eosService.updateAvailable$ | async"
|
||||
color="success"
|
||||
name="repeat"
|
||||
name="rocket-outline"
|
||||
></ion-icon>
|
||||
</ng-container>
|
||||
<ion-badge
|
||||
@@ -162,7 +162,7 @@
|
||||
<ion-icon name="reload"></ion-icon>
|
||||
<ion-icon name="remove"></ion-icon>
|
||||
<ion-icon name="remove-circle-outline"></ion-icon>
|
||||
<ion-icon name="repeat"></ion-icon>
|
||||
<ion-icon name="rocket-outline"></ion-icon>
|
||||
<ion-icon name="save-outline"></ion-icon>
|
||||
<ion-icon name="shield-checkmark-outline"></ion-icon>
|
||||
<ion-icon name="storefront-outline"></ion-icon>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
AlertController,
|
||||
IonicSafeString,
|
||||
LoadingController,
|
||||
ModalController,
|
||||
ToastController,
|
||||
} from '@ionic/angular'
|
||||
import { Emver } from './services/emver.service'
|
||||
@@ -24,7 +25,6 @@ import {
|
||||
ConnectionFailure,
|
||||
ConnectionService,
|
||||
} from './services/connection.service'
|
||||
import { StartupAlertsService } from './services/startup-alerts.service'
|
||||
import { ConfigService } from './services/config.service'
|
||||
import { debounce, isEmptyObject } from './util/misc.util'
|
||||
import { ErrorToastService } from './services/error-toast.service'
|
||||
@@ -32,6 +32,7 @@ import { Subscription } from 'rxjs'
|
||||
import { LocalStorageService } from './services/local-storage.service'
|
||||
import { EOSService } from './services/eos.service'
|
||||
import { MarketplaceService } from './pages/marketplace-routes/marketplace.service'
|
||||
import { OSWelcomePage } from './modals/os-welcome/os-welcome.page'
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -41,7 +42,7 @@ import { MarketplaceService } from './pages/marketplace-routes/marketplace.servi
|
||||
export class AppComponent {
|
||||
@HostListener('document:keydown.enter', ['$event'])
|
||||
@debounce()
|
||||
handleKeyboardEvent () {
|
||||
handleKeyboardEvent() {
|
||||
const elems = document.getElementsByClassName('enter-click')
|
||||
const elem = elems[elems.length - 1] as HTMLButtonElement
|
||||
if (!elem || elem.classList.contains('no-click') || elem.disabled) return
|
||||
@@ -86,7 +87,7 @@ export class AppComponent {
|
||||
},
|
||||
]
|
||||
|
||||
constructor (
|
||||
constructor(
|
||||
private readonly storage: Storage,
|
||||
private readonly authService: AuthService,
|
||||
private readonly router: Router,
|
||||
@@ -95,7 +96,7 @@ export class AppComponent {
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly emver: Emver,
|
||||
private readonly connectionService: ConnectionService,
|
||||
private readonly startupAlertsService: StartupAlertsService,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly marketplaceService: MarketplaceService,
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly errToast: ErrorToastService,
|
||||
@@ -109,7 +110,7 @@ export class AppComponent {
|
||||
this.init()
|
||||
}
|
||||
|
||||
async init () {
|
||||
async init() {
|
||||
await this.storage.create()
|
||||
await this.authService.init()
|
||||
await this.localStorageService.init()
|
||||
@@ -146,6 +147,8 @@ export class AppComponent {
|
||||
.subscribe(data => {
|
||||
// check for updates to EOS
|
||||
this.checkForEosUpdate(data.ui)
|
||||
// show eos welcome message
|
||||
this.showEosWelcome(data.ui['ack-welcome'])
|
||||
|
||||
this.subscriptions = this.subscriptions.concat([
|
||||
// watch status to present toast for updated state
|
||||
@@ -158,8 +161,6 @@ export class AppComponent {
|
||||
this.watchNotifications(),
|
||||
// watch marketplace URL for changes
|
||||
this.marketplaceService.init(),
|
||||
// run startup alerts
|
||||
this.startupAlertsService.runChecks(),
|
||||
])
|
||||
})
|
||||
// UNVERIFIED
|
||||
@@ -180,7 +181,7 @@ export class AppComponent {
|
||||
})
|
||||
}
|
||||
|
||||
async goToWebsite (): Promise<void> {
|
||||
async goToWebsite(): Promise<void> {
|
||||
let url: string
|
||||
if (this.config.isTor()) {
|
||||
url =
|
||||
@@ -191,7 +192,7 @@ export class AppComponent {
|
||||
window.open(url, '_blank', 'noreferrer')
|
||||
}
|
||||
|
||||
async presentAlertLogout () {
|
||||
async presentAlertLogout() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Caution',
|
||||
message:
|
||||
@@ -214,19 +215,37 @@ export class AppComponent {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
private async checkForEosUpdate (ui: UIData): Promise<void> {
|
||||
private checkForEosUpdate(ui: UIData): void {
|
||||
if (ui['auto-check-updates']) {
|
||||
await this.eosService.getEOS()
|
||||
this.eosService.getEOS()
|
||||
}
|
||||
}
|
||||
|
||||
private async showEosWelcome(ackVersion: string): Promise<void> {
|
||||
if (!this.config.skipStartupAlerts && ackVersion !== this.config.version) {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: OSWelcomePage,
|
||||
presentingElement: await this.modalCtrl.getTop(),
|
||||
componentProps: {
|
||||
version: this.config.version,
|
||||
},
|
||||
})
|
||||
modal.onWillDismiss().then(() => {
|
||||
this.embassyApi
|
||||
.setDbValue({ pointer: '/ack-welcome', value: this.config.version })
|
||||
.catch()
|
||||
})
|
||||
modal.present()
|
||||
}
|
||||
}
|
||||
|
||||
// should wipe cache independant of actual BE logout
|
||||
private async logout () {
|
||||
private async logout() {
|
||||
this.embassyApi.logout({})
|
||||
this.authService.setUnverified()
|
||||
}
|
||||
|
||||
private watchConnection (): Subscription {
|
||||
private watchConnection(): Subscription {
|
||||
return this.connectionService
|
||||
.watchFailure$()
|
||||
.pipe(distinctUntilChanged(), debounceTime(500))
|
||||
@@ -259,7 +278,7 @@ export class AppComponent {
|
||||
})
|
||||
}
|
||||
|
||||
private watchRouter (): Subscription {
|
||||
private watchRouter(): Subscription {
|
||||
return this.router.events
|
||||
.pipe(filter((e: RoutesRecognized) => !!e.urlAfterRedirects))
|
||||
.subscribe(e => {
|
||||
@@ -270,7 +289,7 @@ export class AppComponent {
|
||||
})
|
||||
}
|
||||
|
||||
private watchStatus (): Subscription {
|
||||
private watchStatus(): Subscription {
|
||||
return this.patch.watch$('server-info', 'status').subscribe(status => {
|
||||
if (status === ServerStatus.Updated && !this.updateToast) {
|
||||
this.presentToastUpdated()
|
||||
@@ -278,7 +297,7 @@ export class AppComponent {
|
||||
})
|
||||
}
|
||||
|
||||
private watchUpdateProgress (): Subscription {
|
||||
private watchUpdateProgress(): Subscription {
|
||||
return this.patch
|
||||
.watch$('server-info', 'update-progress')
|
||||
.subscribe(progress => {
|
||||
@@ -286,7 +305,7 @@ export class AppComponent {
|
||||
})
|
||||
}
|
||||
|
||||
private watchVersion (): Subscription {
|
||||
private watchVersion(): Subscription {
|
||||
return this.patch.watch$('server-info', 'version').subscribe(version => {
|
||||
if (this.emver.compare(this.config.version, version) !== 0) {
|
||||
this.presentAlertRefreshNeeded()
|
||||
@@ -294,7 +313,7 @@ export class AppComponent {
|
||||
})
|
||||
}
|
||||
|
||||
private watchNotifications (): Subscription {
|
||||
private watchNotifications(): Subscription {
|
||||
let previous: number
|
||||
return this.patch
|
||||
.watch$('server-info', 'unread-notification-count')
|
||||
@@ -306,7 +325,7 @@ export class AppComponent {
|
||||
})
|
||||
}
|
||||
|
||||
private async presentAlertRefreshNeeded () {
|
||||
private async presentAlertRefreshNeeded() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
backdropDismiss: false,
|
||||
header: 'Refresh Needed',
|
||||
@@ -325,7 +344,7 @@ export class AppComponent {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
private async presentToastUpdated () {
|
||||
private async presentToastUpdated() {
|
||||
if (this.updateToast) return
|
||||
|
||||
this.updateToast = await this.toastCtrl.create({
|
||||
@@ -355,7 +374,7 @@ export class AppComponent {
|
||||
await this.updateToast.present()
|
||||
}
|
||||
|
||||
private async presentToastNotifications () {
|
||||
private async presentToastNotifications() {
|
||||
if (this.notificationToast) return
|
||||
|
||||
this.notificationToast = await this.toastCtrl.create({
|
||||
@@ -385,7 +404,7 @@ export class AppComponent {
|
||||
await this.notificationToast.present()
|
||||
}
|
||||
|
||||
private async presentToastOffline (
|
||||
private async presentToastOffline(
|
||||
message: string | IonicSafeString,
|
||||
link?: string,
|
||||
) {
|
||||
@@ -426,7 +445,7 @@ export class AppComponent {
|
||||
await this.offlineToast.present()
|
||||
}
|
||||
|
||||
private async restart (): Promise<void> {
|
||||
private async restart(): Promise<void> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
spinner: 'lines',
|
||||
message: 'Restarting...',
|
||||
@@ -443,7 +462,7 @@ export class AppComponent {
|
||||
}
|
||||
}
|
||||
|
||||
splitPaneVisible (e: any) {
|
||||
splitPaneVisible(e: any) {
|
||||
this.splitPane.sidebarOpen$.next(e.detail.visible)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,6 @@
|
||||
<ion-note slot="end">{{ patch.data.ui.name || defaultName }}</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item
|
||||
button
|
||||
(click)="serverConfig.presentAlert('share-stats', server['share-stats'])"
|
||||
>
|
||||
<ion-label>Auto Report Bugs</ion-label>
|
||||
<ion-note slot="end"
|
||||
>{{ server['share-stats'] ? 'Enabled' : 'Disabled' }}</ion-note
|
||||
>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Marketplace</ion-item-divider>
|
||||
<ion-item
|
||||
button
|
||||
|
||||
@@ -28,9 +28,9 @@ export class PreferencesPage {
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly api: ApiService,
|
||||
public readonly serverConfig: ServerConfigService,
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly localStorageService: LocalStorageService,
|
||||
public readonly serverConfig: ServerConfigService,
|
||||
public readonly patch: PatchDbService,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -59,19 +59,21 @@
|
||||
</span>
|
||||
</ng-container>
|
||||
</p>
|
||||
|
||||
<!-- "Software Update" button only -->
|
||||
<p *ngIf="button.title === 'Software Update'">
|
||||
<ng-container
|
||||
*ngIf="eosService.updateAvailable$ | async; else check"
|
||||
>
|
||||
<ion-text class="inline" color="success">
|
||||
<ion-icon name="repeat"></ion-icon>
|
||||
<ion-icon name="rocket-outline"></ion-icon>
|
||||
Update Available
|
||||
</ion-text>
|
||||
</ng-container>
|
||||
<ng-template #check>
|
||||
<i>Check for updates</i>
|
||||
<ion-text class="inline" color="dark">
|
||||
<ion-icon name="refresh"></ion-icon>
|
||||
Check for updates
|
||||
</ion-text>
|
||||
</ng-template>
|
||||
</p>
|
||||
</ion-label>
|
||||
|
||||
@@ -204,7 +204,10 @@ export class ServerShowPage {
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.eosService.getEOS()
|
||||
const updateAvailable = await this.eosService.getEOS()
|
||||
if (updateAvailable) {
|
||||
this.updateEos()
|
||||
}
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
|
||||
@@ -28,9 +28,6 @@ export module RR {
|
||||
|
||||
// server
|
||||
|
||||
export type SetShareStatsReq = WithExpire<{ value: boolean }> // server.config.share-stats
|
||||
export type SetShareStatsRes = WithRevision<null>
|
||||
|
||||
export type GetServerLogsReq = {
|
||||
cursor?: string
|
||||
before_flag?: boolean
|
||||
|
||||
@@ -51,12 +51,6 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
|
||||
|
||||
// server
|
||||
|
||||
protected abstract setShareStatsRaw(
|
||||
params: RR.SetShareStatsReq,
|
||||
): Promise<RR.SetShareStatsRes>
|
||||
setShareStats = (params: RR.SetShareStatsReq) =>
|
||||
this.syncResponse(() => this.setShareStatsRaw(params))()
|
||||
|
||||
abstract getServerLogs(
|
||||
params: RR.GetServerLogsReq,
|
||||
): Promise<RR.GetServerLogsRes>
|
||||
|
||||
@@ -57,12 +57,6 @@ export class LiveApiService extends ApiService {
|
||||
|
||||
// server
|
||||
|
||||
async setShareStatsRaw(
|
||||
params: RR.SetShareStatsReq,
|
||||
): Promise<RR.SetShareStatsRes> {
|
||||
return this.http.rpcRequest({ method: 'server.config.share-stats', params })
|
||||
}
|
||||
|
||||
async getServerLogs(
|
||||
params: RR.GetServerLogsReq,
|
||||
): Promise<RR.GetServerLogsRes> {
|
||||
|
||||
@@ -25,22 +25,22 @@ export class MockApiService extends ApiService {
|
||||
private readonly revertTime = 4000
|
||||
sequence: number
|
||||
|
||||
constructor (private readonly bootstrapper: LocalStorageBootstrap) {
|
||||
constructor(private readonly bootstrapper: LocalStorageBootstrap) {
|
||||
super()
|
||||
}
|
||||
|
||||
async getStatic (url: string): Promise<string> {
|
||||
async getStatic(url: string): Promise<string> {
|
||||
await pauseFor(2000)
|
||||
return markdown
|
||||
}
|
||||
|
||||
// db
|
||||
|
||||
async getRevisions (since: number): Promise<RR.GetRevisionsRes> {
|
||||
async getRevisions(since: number): Promise<RR.GetRevisionsRes> {
|
||||
return this.getDump()
|
||||
}
|
||||
|
||||
async getDump (): Promise<RR.GetDumpRes> {
|
||||
async getDump(): Promise<RR.GetDumpRes> {
|
||||
const cache = await this.bootstrapper.init()
|
||||
return {
|
||||
id: cache.sequence,
|
||||
@@ -49,7 +49,7 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async setDbValueRaw (params: RR.SetDBValueReq): Promise<RR.SetDBValueRes> {
|
||||
async setDbValueRaw(params: RR.SetDBValueReq): Promise<RR.SetDBValueRes> {
|
||||
await pauseFor(2000)
|
||||
const patch = [
|
||||
{
|
||||
@@ -63,7 +63,7 @@ export class MockApiService extends ApiService {
|
||||
|
||||
// auth
|
||||
|
||||
async login (params: RR.LoginReq): Promise<RR.loginRes> {
|
||||
async login(params: RR.LoginReq): Promise<RR.loginRes> {
|
||||
await pauseFor(2000)
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -73,39 +73,24 @@ export class MockApiService extends ApiService {
|
||||
return null
|
||||
}
|
||||
|
||||
async logout (params: RR.LogoutReq): Promise<RR.LogoutRes> {
|
||||
async logout(params: RR.LogoutReq): Promise<RR.LogoutRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async getSessions (params: RR.GetSessionsReq): Promise<RR.GetSessionsRes> {
|
||||
async getSessions(params: RR.GetSessionsReq): Promise<RR.GetSessionsRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.Sessions
|
||||
}
|
||||
|
||||
async killSessions (params: RR.KillSessionsReq): Promise<RR.KillSessionsRes> {
|
||||
async killSessions(params: RR.KillSessionsReq): Promise<RR.KillSessionsRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
// server
|
||||
|
||||
async setShareStatsRaw (
|
||||
params: RR.SetShareStatsReq,
|
||||
): Promise<RR.SetShareStatsRes> {
|
||||
await pauseFor(2000)
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/share-stats',
|
||||
value: params.value,
|
||||
},
|
||||
]
|
||||
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async getServerLogs (
|
||||
async getServerLogs(
|
||||
params: RR.GetServerLogsReq,
|
||||
): Promise<RR.GetServerLogsRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -127,21 +112,21 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async getServerMetrics (
|
||||
async getServerMetrics(
|
||||
params: RR.GetServerMetricsReq,
|
||||
): Promise<RR.GetServerMetricsRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.getServerMetrics()
|
||||
}
|
||||
|
||||
async getPkgMetrics (
|
||||
async getPkgMetrics(
|
||||
params: RR.GetServerMetricsReq,
|
||||
): Promise<RR.GetPackageMetricsRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.getAppMetrics()
|
||||
}
|
||||
|
||||
async updateServerRaw (
|
||||
async updateServerRaw(
|
||||
params: RR.UpdateServerReq,
|
||||
): Promise<RR.UpdateServerRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -165,21 +150,21 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch, 'updating')
|
||||
}
|
||||
|
||||
async restartServer (
|
||||
async restartServer(
|
||||
params: RR.RestartServerReq,
|
||||
): Promise<RR.RestartServerRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async shutdownServer (
|
||||
async shutdownServer(
|
||||
params: RR.ShutdownServerReq,
|
||||
): Promise<RR.ShutdownServerRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async systemRebuild (
|
||||
async systemRebuild(
|
||||
params: RR.RestartServerReq,
|
||||
): Promise<RR.RestartServerRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -188,7 +173,7 @@ export class MockApiService extends ApiService {
|
||||
|
||||
// marketplace URLs
|
||||
|
||||
async marketplaceProxy (path: string, params: {}, url: string): Promise<any> {
|
||||
async marketplaceProxy(path: string, params: {}, url: string): Promise<any> {
|
||||
await pauseFor(2000)
|
||||
|
||||
if (path === '/package/v0/info') {
|
||||
@@ -211,7 +196,7 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async getEos (
|
||||
async getEos(
|
||||
params: RR.GetMarketplaceEOSReq,
|
||||
): Promise<RR.GetMarketplaceEOSRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -226,7 +211,7 @@ export class MockApiService extends ApiService {
|
||||
|
||||
// notification
|
||||
|
||||
async getNotificationsRaw (
|
||||
async getNotificationsRaw(
|
||||
params: RR.GetNotificationsReq,
|
||||
): Promise<RR.GetNotificationsRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -241,14 +226,14 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch, Mock.Notifications)
|
||||
}
|
||||
|
||||
async deleteNotification (
|
||||
async deleteNotification(
|
||||
params: RR.DeleteNotificationReq,
|
||||
): Promise<RR.DeleteNotificationRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async deleteAllNotifications (
|
||||
async deleteAllNotifications(
|
||||
params: RR.DeleteAllNotificationsReq,
|
||||
): Promise<RR.DeleteAllNotificationsRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -257,60 +242,60 @@ export class MockApiService extends ApiService {
|
||||
|
||||
// wifi
|
||||
|
||||
async getWifi (params: RR.GetWifiReq): Promise<RR.GetWifiRes> {
|
||||
async getWifi(params: RR.GetWifiReq): Promise<RR.GetWifiRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.Wifi
|
||||
}
|
||||
|
||||
async setWifiCountry (
|
||||
async setWifiCountry(
|
||||
params: RR.SetWifiCountryReq,
|
||||
): Promise<RR.SetWifiCountryRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async addWifi (params: RR.AddWifiReq): Promise<RR.AddWifiRes> {
|
||||
async addWifi(params: RR.AddWifiReq): Promise<RR.AddWifiRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async connectWifi (params: RR.ConnectWifiReq): Promise<RR.ConnectWifiRes> {
|
||||
async connectWifi(params: RR.ConnectWifiReq): Promise<RR.ConnectWifiRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async deleteWifi (params: RR.DeleteWifiReq): Promise<RR.DeleteWifiRes> {
|
||||
async deleteWifi(params: RR.DeleteWifiReq): Promise<RR.DeleteWifiRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
// ssh
|
||||
|
||||
async getSshKeys (params: RR.GetSSHKeysReq): Promise<RR.GetSSHKeysRes> {
|
||||
async getSshKeys(params: RR.GetSSHKeysReq): Promise<RR.GetSSHKeysRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.SshKeys
|
||||
}
|
||||
|
||||
async addSshKey (params: RR.AddSSHKeyReq): Promise<RR.AddSSHKeyRes> {
|
||||
async addSshKey(params: RR.AddSSHKeyReq): Promise<RR.AddSSHKeyRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.SshKey
|
||||
}
|
||||
|
||||
async deleteSshKey (params: RR.DeleteSSHKeyReq): Promise<RR.DeleteSSHKeyRes> {
|
||||
async deleteSshKey(params: RR.DeleteSSHKeyReq): Promise<RR.DeleteSSHKeyRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
// backup
|
||||
|
||||
async getBackupTargets (
|
||||
async getBackupTargets(
|
||||
params: RR.GetBackupTargetsReq,
|
||||
): Promise<RR.GetBackupTargetsRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.BackupTargets
|
||||
}
|
||||
|
||||
async addBackupTarget (
|
||||
async addBackupTarget(
|
||||
params: RR.AddBackupTargetReq,
|
||||
): Promise<RR.AddBackupTargetRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -327,7 +312,7 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async updateBackupTarget (
|
||||
async updateBackupTarget(
|
||||
params: RR.UpdateBackupTargetReq,
|
||||
): Promise<RR.UpdateBackupTargetRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -342,21 +327,21 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async removeBackupTarget (
|
||||
async removeBackupTarget(
|
||||
params: RR.RemoveBackupTargetReq,
|
||||
): Promise<RR.RemoveBackupTargetRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
async getBackupInfo (
|
||||
async getBackupInfo(
|
||||
params: RR.GetBackupInfoReq,
|
||||
): Promise<RR.GetBackupInfoRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.BackupInfo
|
||||
}
|
||||
|
||||
async createBackupRaw (
|
||||
async createBackupRaw(
|
||||
params: RR.CreateBackupReq,
|
||||
): Promise<RR.CreateBackupRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -407,14 +392,14 @@ export class MockApiService extends ApiService {
|
||||
|
||||
// package
|
||||
|
||||
async getPackageProperties (
|
||||
async getPackageProperties(
|
||||
params: RR.GetPackagePropertiesReq,
|
||||
): Promise<RR.GetPackagePropertiesRes<2>['data']> {
|
||||
await pauseFor(2000)
|
||||
return parsePropertiesPermissive(Mock.PackageProperties)
|
||||
}
|
||||
|
||||
async getPackageLogs (
|
||||
async getPackageLogs(
|
||||
params: RR.GetPackageLogsReq,
|
||||
): Promise<RR.GetPackageLogsRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -436,7 +421,7 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async installPackageRaw (
|
||||
async installPackageRaw(
|
||||
params: RR.InstallPackageReq,
|
||||
): Promise<RR.InstallPackageRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -471,14 +456,14 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async dryUpdatePackage (
|
||||
async dryUpdatePackage(
|
||||
params: RR.DryUpdatePackageReq,
|
||||
): Promise<RR.DryUpdatePackageRes> {
|
||||
await pauseFor(2000)
|
||||
return {}
|
||||
}
|
||||
|
||||
async getPackageConfig (
|
||||
async getPackageConfig(
|
||||
params: RR.GetPackageConfigReq,
|
||||
): Promise<RR.GetPackageConfigRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -488,14 +473,14 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async drySetPackageConfig (
|
||||
async drySetPackageConfig(
|
||||
params: RR.DrySetPackageConfigReq,
|
||||
): Promise<RR.DrySetPackageConfigRes> {
|
||||
await pauseFor(2000)
|
||||
return {}
|
||||
}
|
||||
|
||||
async setPackageConfigRaw (
|
||||
async setPackageConfigRaw(
|
||||
params: RR.SetPackageConfigReq,
|
||||
): Promise<RR.SetPackageConfigRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -509,7 +494,7 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async restorePackagesRaw (
|
||||
async restorePackagesRaw(
|
||||
params: RR.RestorePackagesReq,
|
||||
): Promise<RR.RestorePackagesRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -545,14 +530,14 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async executePackageAction (
|
||||
async executePackageAction(
|
||||
params: RR.ExecutePackageActionReq,
|
||||
): Promise<RR.ExecutePackageActionRes> {
|
||||
await pauseFor(2000)
|
||||
return Mock.ActionResponse
|
||||
}
|
||||
|
||||
async startPackageRaw (
|
||||
async startPackageRaw(
|
||||
params: RR.StartPackageReq,
|
||||
): Promise<RR.StartPackageRes> {
|
||||
const path = `/package-data/${params.id}/installed/status/main`
|
||||
@@ -631,7 +616,7 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(originalPatch)
|
||||
}
|
||||
|
||||
async dryStopPackage (
|
||||
async dryStopPackage(
|
||||
params: RR.DryStopPackageReq,
|
||||
): Promise<RR.DryStopPackageRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -645,7 +630,7 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
async stopPackageRaw (params: RR.StopPackageReq): Promise<RR.StopPackageRes> {
|
||||
async stopPackageRaw(params: RR.StopPackageReq): Promise<RR.StopPackageRes> {
|
||||
await pauseFor(2000)
|
||||
const path = `/package-data/${params.id}/installed/status/main`
|
||||
|
||||
@@ -676,14 +661,14 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async dryUninstallPackage (
|
||||
async dryUninstallPackage(
|
||||
params: RR.DryUninstallPackageReq,
|
||||
): Promise<RR.DryUninstallPackageRes> {
|
||||
await pauseFor(2000)
|
||||
return {}
|
||||
}
|
||||
|
||||
async uninstallPackageRaw (
|
||||
async uninstallPackageRaw(
|
||||
params: RR.UninstallPackageReq,
|
||||
): Promise<RR.UninstallPackageRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -709,7 +694,7 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async deleteRecoveredPackageRaw (
|
||||
async deleteRecoveredPackageRaw(
|
||||
params: RR.DeleteRecoveredPackageReq,
|
||||
): Promise<RR.DeleteRecoveredPackageRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -722,7 +707,7 @@ export class MockApiService extends ApiService {
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async dryConfigureDependency (
|
||||
async dryConfigureDependency(
|
||||
params: RR.DryConfigureDependencyReq,
|
||||
): Promise<RR.DryConfigureDependencyRes> {
|
||||
await pauseFor(2000)
|
||||
@@ -733,7 +718,7 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
private async updateProgress (
|
||||
private async updateProgress(
|
||||
id: string,
|
||||
initialProgress: InstallProgress,
|
||||
): Promise<void> {
|
||||
@@ -779,7 +764,7 @@ export class MockApiService extends ApiService {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
private async updateOSProgress (size: number) {
|
||||
private async updateOSProgress(size: number) {
|
||||
let downloaded = 0
|
||||
while (downloaded < size) {
|
||||
await pauseFor(250)
|
||||
@@ -829,7 +814,7 @@ export class MockApiService extends ApiService {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
private async updateMock (patch: Operation[]): Promise<void> {
|
||||
private async updateMock(patch: Operation[]): Promise<void> {
|
||||
if (!this.sequence) {
|
||||
const { sequence } = await this.bootstrapper.init()
|
||||
this.sequence = sequence
|
||||
@@ -842,7 +827,7 @@ export class MockApiService extends ApiService {
|
||||
this.mockPatch$.next(revision)
|
||||
}
|
||||
|
||||
private async withRevision<T> (
|
||||
private async withRevision<T>(
|
||||
patch: Operation[],
|
||||
response: T = null,
|
||||
): Promise<WithRevision<T>> {
|
||||
|
||||
@@ -15,7 +15,6 @@ export const mockPatchData: DataModel = {
|
||||
'auto-check-updates': true,
|
||||
'pkg-order': [],
|
||||
'ack-welcome': '1.0.0',
|
||||
'ack-share-stats': false,
|
||||
marketplace: undefined,
|
||||
},
|
||||
'server-info': {
|
||||
@@ -25,9 +24,6 @@ export const mockPatchData: DataModel = {
|
||||
status: ServerStatus.Running,
|
||||
'lan-address': 'https://embassy-abcdefgh.local',
|
||||
'tor-address': 'http://myveryownspecialtoraddress.onion',
|
||||
'eos-marketplace': 'https://beta-registry-0-3.start9labs.com',
|
||||
'package-marketplace': null,
|
||||
'share-stats': false,
|
||||
'unread-notification-count': 4,
|
||||
'password-hash':
|
||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||
|
||||
@@ -18,7 +18,7 @@ export class EOSService {
|
||||
private readonly patch: PatchDbService,
|
||||
) {}
|
||||
|
||||
async getEOS(): Promise<void> {
|
||||
async getEOS(): Promise<boolean> {
|
||||
this.eos = await this.api.getEos({
|
||||
'eos-version-compat':
|
||||
this.patch.getData()['server-info']['eos-version-compat'],
|
||||
@@ -29,5 +29,6 @@ export class EOSService {
|
||||
this.patch.data['server-info'].version,
|
||||
) === 1
|
||||
this.updateAvailable$.next(updateAvailable)
|
||||
return updateAvailable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ export interface UIData {
|
||||
'auto-check-updates': boolean
|
||||
'pkg-order': string[]
|
||||
'ack-welcome': string // EOS version
|
||||
'ack-share-stats': boolean
|
||||
marketplace: UIMarketplaceData
|
||||
}
|
||||
|
||||
@@ -33,9 +32,6 @@ export interface ServerInfo {
|
||||
'lan-address': URL
|
||||
'tor-address': URL
|
||||
status: ServerStatus
|
||||
'eos-marketplace': URL
|
||||
'package-marketplace': URL | null // uses EOS marketplace if null
|
||||
'share-stats': boolean
|
||||
'unread-notification-count': number
|
||||
'update-progress'?: {
|
||||
size: number
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { AlertInput, AlertButton, IonicSafeString } from '@ionic/core'
|
||||
import { AlertInput, AlertButton } from '@ionic/core'
|
||||
import { ApiService } from './api/embassy-api.service'
|
||||
import { ConfigSpec } from '../pkg-config/config-types'
|
||||
import { AlertController, LoadingController } from '@ionic/angular'
|
||||
@@ -104,9 +104,6 @@ export class ServerConfigService {
|
||||
value: enabled,
|
||||
})
|
||||
},
|
||||
'share-stats': async (enabled: boolean) => {
|
||||
return this.embassyApi.setShareStats({ value: enabled })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,15 +112,7 @@ export const serverConfig: ConfigSpec = {
|
||||
type: 'boolean',
|
||||
name: 'Auto Check for Updates',
|
||||
description:
|
||||
'If enabled, EmbassyOS will automatically check for updates of itself and any installed services. Updating will still require your approval and action. Updates will never be performed automatically.',
|
||||
'If enabled, EmbassyOS will automatically check for updates of itself. Updating will still require your approval and action. Updates will never be performed automatically.',
|
||||
default: true,
|
||||
},
|
||||
'share-stats': {
|
||||
type: 'boolean',
|
||||
name: 'Report Bugs',
|
||||
description: new IonicSafeString(
|
||||
`If enabled, generic error codes will be anonymously transmitted over Tor to the Start9 team. This helps us identify and fix bugs quickly. <a href="https://docs.start9.com/user-manual/general/user-preferences/report-bugs.html" target="_blank" rel="noreferrer">Read more</a> `,
|
||||
) as any,
|
||||
default: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ModalController } from '@ionic/angular'
|
||||
import { WizardBaker } from '../components/install-wizard/prebaked-wizards'
|
||||
import { OSWelcomePage } from '../modals/os-welcome/os-welcome.page'
|
||||
import { ConfigService } from './config.service'
|
||||
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'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class StartupAlertsService {
|
||||
private checks: Check<any>[]
|
||||
|
||||
constructor(
|
||||
private readonly config: ConfigService,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly api: ApiService,
|
||||
private readonly wizardBaker: WizardBaker,
|
||||
private readonly patch: PatchDbService,
|
||||
private readonly serverConfig: ServerConfigService,
|
||||
) {
|
||||
const osWelcome: Check<boolean> = {
|
||||
name: 'osWelcome',
|
||||
shouldRun: () => this.shouldRunOsWelcome(),
|
||||
display: () => this.displayOsWelcome(),
|
||||
}
|
||||
const shareStats: Check<boolean> = {
|
||||
name: 'shareStats',
|
||||
shouldRun: () => this.shouldRunShareStats(),
|
||||
display: () => this.displayShareStats(),
|
||||
}
|
||||
this.checks = [osWelcome, shareStats]
|
||||
}
|
||||
|
||||
// This takes our three checks and filters down to those that should run.
|
||||
// Then, the reduce fires, quickly iterating through yielding a promise (previousDisplay) to the next element
|
||||
// Each promise fires more or less concurrently, so each c.check(server) is run concurrently
|
||||
// Then, since we await previousDisplay before c.display(res), each promise executing gets hung awaiting the display of the previous run
|
||||
runChecks(): Subscription {
|
||||
return this.patch
|
||||
.watch$()
|
||||
.pipe(
|
||||
filter(data => !isEmptyObject(data)),
|
||||
take(1),
|
||||
)
|
||||
.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) => {
|
||||
const displayRes = await previousDisplay
|
||||
if (displayRes) return c.display()
|
||||
}, Promise.resolve(true))
|
||||
})
|
||||
}
|
||||
|
||||
// ** should run **
|
||||
|
||||
private shouldRunOsWelcome(): boolean {
|
||||
return this.patch.getData().ui['ack-welcome'] !== this.config.version
|
||||
}
|
||||
private shouldRunShareStats(): boolean {
|
||||
return !this.patch.getData().ui['ack-share-stats']
|
||||
}
|
||||
|
||||
private shouldRunOsUpdateCheck(): boolean {
|
||||
return this.patch.getData().ui['auto-check-updates']
|
||||
}
|
||||
|
||||
// ** display **
|
||||
|
||||
private async displayOsWelcome(): Promise<boolean> {
|
||||
return new Promise(async resolve => {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: OSWelcomePage,
|
||||
presentingElement: await this.modalCtrl.getTop(),
|
||||
componentProps: {
|
||||
version: this.config.version,
|
||||
},
|
||||
})
|
||||
modal.onWillDismiss().then(() => {
|
||||
this.api
|
||||
.setDbValue({ pointer: '/ack-welcome', value: this.config.version })
|
||||
.catch()
|
||||
return resolve(true)
|
||||
})
|
||||
await modal.present()
|
||||
})
|
||||
}
|
||||
|
||||
private async displayShareStats(): Promise<boolean> {
|
||||
return new Promise(async resolve => {
|
||||
const alert = await this.serverConfig.presentAlert(
|
||||
'share-stats',
|
||||
this.patch.getData()['server-info']['share-stats'],
|
||||
)
|
||||
|
||||
alert.onDidDismiss().then(() => {
|
||||
this.api
|
||||
.setDbValue({
|
||||
pointer: '/ack-share-stats',
|
||||
value: this.config.version,
|
||||
})
|
||||
.catch()
|
||||
return resolve(true)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type Check<T> = {
|
||||
// validates whether a check should run based on server properties
|
||||
shouldRun: () => boolean
|
||||
// display an alert based on the result of the check.
|
||||
// return false if subsequent modals should not be displayed
|
||||
display: () => Promise<boolean>
|
||||
// for logging purposes
|
||||
name: string
|
||||
}
|
||||
7
frontend/update-git-hash.sh
Executable file
7
frontend/update-git-hash.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
TMP_FILE=$(mktemp)
|
||||
|
||||
jq ".gitHash = \"$(git rev-parse HEAD)\"" config.json > $TMP_FILE && mv $TMP_FILE config.json
|
||||
Reference in New Issue
Block a user