diff --git a/frontend/package.json b/frontend/package.json index 153ebc37f..f272dfb05 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -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", diff --git a/frontend/projects/ui/src/app/app.component.html b/frontend/projects/ui/src/app/app.component.html index d93bf13e1..3bb9f6185 100644 --- a/frontend/projects/ui/src/app/app.component.html +++ b/frontend/projects/ui/src/app/app.component.html @@ -49,7 +49,7 @@ - + diff --git a/frontend/projects/ui/src/app/app.component.ts b/frontend/projects/ui/src/app/app.component.ts index 07f6618a3..fa6a145e8 100644 --- a/frontend/projects/ui/src/app/app.component.ts +++ b/frontend/projects/ui/src/app/app.component.ts @@ -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 { + async goToWebsite(): Promise { 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 { + private checkForEosUpdate(ui: UIData): void { if (ui['auto-check-updates']) { - await this.eosService.getEOS() + this.eosService.getEOS() + } + } + + private async showEosWelcome(ackVersion: string): Promise { + 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 { + private async restart(): Promise { 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) } } diff --git a/frontend/projects/ui/src/app/pages/server-routes/preferences/preferences.page.html b/frontend/projects/ui/src/app/pages/server-routes/preferences/preferences.page.html index 2a69140d8..85af3bb34 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/preferences/preferences.page.html +++ b/frontend/projects/ui/src/app/pages/server-routes/preferences/preferences.page.html @@ -15,16 +15,6 @@ {{ patch.data.ui.name || defaultName }} - - Auto Report Bugs - {{ server['share-stats'] ? 'Enabled' : 'Disabled' }} - - Marketplace

-

- + Update Available - Check for updates + + + Check for updates +

diff --git a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts index 7c9c47589..f95b81894 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts +++ b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts @@ -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 { diff --git a/frontend/projects/ui/src/app/services/api/api.types.ts b/frontend/projects/ui/src/app/services/api/api.types.ts index f9bde39af..59ceb0032 100644 --- a/frontend/projects/ui/src/app/services/api/api.types.ts +++ b/frontend/projects/ui/src/app/services/api/api.types.ts @@ -28,9 +28,6 @@ export module RR { // server - export type SetShareStatsReq = WithExpire<{ value: boolean }> // server.config.share-stats - export type SetShareStatsRes = WithRevision - export type GetServerLogsReq = { cursor?: string before_flag?: boolean diff --git a/frontend/projects/ui/src/app/services/api/embassy-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-api.service.ts index e3f5bd604..71077bd31 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-api.service.ts @@ -51,12 +51,6 @@ export abstract class ApiService implements Source, Http { // server - protected abstract setShareStatsRaw( - params: RR.SetShareStatsReq, - ): Promise - setShareStats = (params: RR.SetShareStatsReq) => - this.syncResponse(() => this.setShareStatsRaw(params))() - abstract getServerLogs( params: RR.GetServerLogsReq, ): Promise diff --git a/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts index 6aa74bb07..f9650ae1b 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts @@ -57,12 +57,6 @@ export class LiveApiService extends ApiService { // server - async setShareStatsRaw( - params: RR.SetShareStatsReq, - ): Promise { - return this.http.rpcRequest({ method: 'server.config.share-stats', params }) - } - async getServerLogs( params: RR.GetServerLogsReq, ): Promise { diff --git a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts index eadc69eaf..16ed61a59 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts @@ -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 { + async getStatic(url: string): Promise { await pauseFor(2000) return markdown } // db - async getRevisions (since: number): Promise { + async getRevisions(since: number): Promise { return this.getDump() } - async getDump (): Promise { + async getDump(): Promise { 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 { + async setDbValueRaw(params: RR.SetDBValueReq): Promise { await pauseFor(2000) const patch = [ { @@ -63,7 +63,7 @@ export class MockApiService extends ApiService { // auth - async login (params: RR.LoginReq): Promise { + async login(params: RR.LoginReq): Promise { await pauseFor(2000) setTimeout(() => { @@ -73,39 +73,24 @@ export class MockApiService extends ApiService { return null } - async logout (params: RR.LogoutReq): Promise { + async logout(params: RR.LogoutReq): Promise { await pauseFor(2000) return null } - async getSessions (params: RR.GetSessionsReq): Promise { + async getSessions(params: RR.GetSessionsReq): Promise { await pauseFor(2000) return Mock.Sessions } - async killSessions (params: RR.KillSessionsReq): Promise { + async killSessions(params: RR.KillSessionsReq): Promise { await pauseFor(2000) return null } // server - async setShareStatsRaw ( - params: RR.SetShareStatsReq, - ): Promise { - 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 { await pauseFor(2000) @@ -127,21 +112,21 @@ export class MockApiService extends ApiService { } } - async getServerMetrics ( + async getServerMetrics( params: RR.GetServerMetricsReq, ): Promise { await pauseFor(2000) return Mock.getServerMetrics() } - async getPkgMetrics ( + async getPkgMetrics( params: RR.GetServerMetricsReq, ): Promise { await pauseFor(2000) return Mock.getAppMetrics() } - async updateServerRaw ( + async updateServerRaw( params: RR.UpdateServerReq, ): Promise { 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 { await pauseFor(2000) return null } - async shutdownServer ( + async shutdownServer( params: RR.ShutdownServerReq, ): Promise { await pauseFor(2000) return null } - async systemRebuild ( + async systemRebuild( params: RR.RestartServerReq, ): Promise { await pauseFor(2000) @@ -188,7 +173,7 @@ export class MockApiService extends ApiService { // marketplace URLs - async marketplaceProxy (path: string, params: {}, url: string): Promise { + async marketplaceProxy(path: string, params: {}, url: string): Promise { 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 { await pauseFor(2000) @@ -226,7 +211,7 @@ export class MockApiService extends ApiService { // notification - async getNotificationsRaw ( + async getNotificationsRaw( params: RR.GetNotificationsReq, ): Promise { 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 { await pauseFor(2000) return null } - async deleteAllNotifications ( + async deleteAllNotifications( params: RR.DeleteAllNotificationsReq, ): Promise { await pauseFor(2000) @@ -257,60 +242,60 @@ export class MockApiService extends ApiService { // wifi - async getWifi (params: RR.GetWifiReq): Promise { + async getWifi(params: RR.GetWifiReq): Promise { await pauseFor(2000) return Mock.Wifi } - async setWifiCountry ( + async setWifiCountry( params: RR.SetWifiCountryReq, ): Promise { await pauseFor(2000) return null } - async addWifi (params: RR.AddWifiReq): Promise { + async addWifi(params: RR.AddWifiReq): Promise { await pauseFor(2000) return null } - async connectWifi (params: RR.ConnectWifiReq): Promise { + async connectWifi(params: RR.ConnectWifiReq): Promise { await pauseFor(2000) return null } - async deleteWifi (params: RR.DeleteWifiReq): Promise { + async deleteWifi(params: RR.DeleteWifiReq): Promise { await pauseFor(2000) return null } // ssh - async getSshKeys (params: RR.GetSSHKeysReq): Promise { + async getSshKeys(params: RR.GetSSHKeysReq): Promise { await pauseFor(2000) return Mock.SshKeys } - async addSshKey (params: RR.AddSSHKeyReq): Promise { + async addSshKey(params: RR.AddSSHKeyReq): Promise { await pauseFor(2000) return Mock.SshKey } - async deleteSshKey (params: RR.DeleteSSHKeyReq): Promise { + async deleteSshKey(params: RR.DeleteSSHKeyReq): Promise { await pauseFor(2000) return null } // backup - async getBackupTargets ( + async getBackupTargets( params: RR.GetBackupTargetsReq, ): Promise { await pauseFor(2000) return Mock.BackupTargets } - async addBackupTarget ( + async addBackupTarget( params: RR.AddBackupTargetReq, ): Promise { await pauseFor(2000) @@ -327,7 +312,7 @@ export class MockApiService extends ApiService { } } - async updateBackupTarget ( + async updateBackupTarget( params: RR.UpdateBackupTargetReq, ): Promise { await pauseFor(2000) @@ -342,21 +327,21 @@ export class MockApiService extends ApiService { } } - async removeBackupTarget ( + async removeBackupTarget( params: RR.RemoveBackupTargetReq, ): Promise { await pauseFor(2000) return null } - async getBackupInfo ( + async getBackupInfo( params: RR.GetBackupInfoReq, ): Promise { await pauseFor(2000) return Mock.BackupInfo } - async createBackupRaw ( + async createBackupRaw( params: RR.CreateBackupReq, ): Promise { await pauseFor(2000) @@ -407,14 +392,14 @@ export class MockApiService extends ApiService { // package - async getPackageProperties ( + async getPackageProperties( params: RR.GetPackagePropertiesReq, ): Promise['data']> { await pauseFor(2000) return parsePropertiesPermissive(Mock.PackageProperties) } - async getPackageLogs ( + async getPackageLogs( params: RR.GetPackageLogsReq, ): Promise { await pauseFor(2000) @@ -436,7 +421,7 @@ export class MockApiService extends ApiService { } } - async installPackageRaw ( + async installPackageRaw( params: RR.InstallPackageReq, ): Promise { await pauseFor(2000) @@ -471,14 +456,14 @@ export class MockApiService extends ApiService { return this.withRevision(patch) } - async dryUpdatePackage ( + async dryUpdatePackage( params: RR.DryUpdatePackageReq, ): Promise { await pauseFor(2000) return {} } - async getPackageConfig ( + async getPackageConfig( params: RR.GetPackageConfigReq, ): Promise { await pauseFor(2000) @@ -488,14 +473,14 @@ export class MockApiService extends ApiService { } } - async drySetPackageConfig ( + async drySetPackageConfig( params: RR.DrySetPackageConfigReq, ): Promise { await pauseFor(2000) return {} } - async setPackageConfigRaw ( + async setPackageConfigRaw( params: RR.SetPackageConfigReq, ): Promise { await pauseFor(2000) @@ -509,7 +494,7 @@ export class MockApiService extends ApiService { return this.withRevision(patch) } - async restorePackagesRaw ( + async restorePackagesRaw( params: RR.RestorePackagesReq, ): Promise { await pauseFor(2000) @@ -545,14 +530,14 @@ export class MockApiService extends ApiService { return this.withRevision(patch) } - async executePackageAction ( + async executePackageAction( params: RR.ExecutePackageActionReq, ): Promise { await pauseFor(2000) return Mock.ActionResponse } - async startPackageRaw ( + async startPackageRaw( params: RR.StartPackageReq, ): Promise { 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 { await pauseFor(2000) @@ -645,7 +630,7 @@ export class MockApiService extends ApiService { } } - async stopPackageRaw (params: RR.StopPackageReq): Promise { + async stopPackageRaw(params: RR.StopPackageReq): Promise { 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 { await pauseFor(2000) return {} } - async uninstallPackageRaw ( + async uninstallPackageRaw( params: RR.UninstallPackageReq, ): Promise { await pauseFor(2000) @@ -709,7 +694,7 @@ export class MockApiService extends ApiService { return this.withRevision(patch) } - async deleteRecoveredPackageRaw ( + async deleteRecoveredPackageRaw( params: RR.DeleteRecoveredPackageReq, ): Promise { await pauseFor(2000) @@ -722,7 +707,7 @@ export class MockApiService extends ApiService { return this.withRevision(patch) } - async dryConfigureDependency ( + async dryConfigureDependency( params: RR.DryConfigureDependencyReq, ): Promise { await pauseFor(2000) @@ -733,7 +718,7 @@ export class MockApiService extends ApiService { } } - private async updateProgress ( + private async updateProgress( id: string, initialProgress: InstallProgress, ): Promise { @@ -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 { + private async updateMock(patch: Operation[]): Promise { 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 ( + private async withRevision( patch: Operation[], response: T = null, ): Promise> { diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index eea95d8ff..ff975440a 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -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', diff --git a/frontend/projects/ui/src/app/services/eos.service.ts b/frontend/projects/ui/src/app/services/eos.service.ts index 43bc8a206..bf0d9657a 100644 --- a/frontend/projects/ui/src/app/services/eos.service.ts +++ b/frontend/projects/ui/src/app/services/eos.service.ts @@ -18,7 +18,7 @@ export class EOSService { private readonly patch: PatchDbService, ) {} - async getEOS(): Promise { + async getEOS(): Promise { 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 } } diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index 99a3e82ec..92207b471 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -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 diff --git a/frontend/projects/ui/src/app/services/server-config.service.ts b/frontend/projects/ui/src/app/services/server-config.service.ts index dc1ed4477..ec850782e 100644 --- a/frontend/projects/ui/src/app/services/server-config.service.ts +++ b/frontend/projects/ui/src/app/services/server-config.service.ts @@ -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. Read more `, - ) as any, - default: false, - }, } diff --git a/frontend/projects/ui/src/app/services/startup-alerts.service.ts b/frontend/projects/ui/src/app/services/startup-alerts.service.ts deleted file mode 100644 index 7e5c8d2c2..000000000 --- a/frontend/projects/ui/src/app/services/startup-alerts.service.ts +++ /dev/null @@ -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[] - - 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 = { - name: 'osWelcome', - shouldRun: () => this.shouldRunOsWelcome(), - display: () => this.displayOsWelcome(), - } - const shareStats: Check = { - 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 { - 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 { - 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 = { - // 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 - // for logging purposes - name: string -} diff --git a/frontend/update-git-hash.sh b/frontend/update-git-hash.sh new file mode 100755 index 000000000..0ee27313d --- /dev/null +++ b/frontend/update-git-hash.sh @@ -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