diff --git a/frontend/app/src/app/app.component.spec.ts b/frontend/app/src/app/app.component.spec.ts index 38250571..afa04f3f 100644 --- a/frontend/app/src/app/app.component.spec.ts +++ b/frontend/app/src/app/app.component.spec.ts @@ -33,6 +33,7 @@ import {sampleAuthConfiguration} from './_helpers/data/sample-configuration'; import {StorageProvider} from './modules/storage/storage.provider'; import {SimpleBrowser} from './util/browser.factory'; import {provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; +import {InappRatingProvider} from './modules/settings/inapp-rating/inapp-rating.provider'; describe('AppComponent', () => { let platformReadySpy: any; @@ -40,6 +41,7 @@ describe('AppComponent', () => { let translateServiceSpy: jasmine.SpyObj; let thingTranslateServiceSpy: jasmine.SpyObj; let settingsProvider: jasmine.SpyObj; + let inappRatingsProvider: jasmine.SpyObj; let configProvider: jasmine.SpyObj; let ngxLogger: jasmine.SpyObj; let scheduleSyncServiceSpy: jasmine.SpyObj; @@ -85,6 +87,7 @@ describe('AppComponent', () => { {provide: ThingTranslateService, useValue: thingTranslateServiceSpy}, {provide: ScheduleSyncService, useValue: scheduleSyncServiceSpy}, {provide: SettingsProvider, useValue: settingsProvider}, + {provide: InappRatingProvider, useValue: inappRatingsProvider}, {provide: ConfigProvider, useValue: configProvider}, {provide: NGXLogger, useValue: ngxLogger}, {provide: StorageProvider, useValue: storageProvider}, diff --git a/frontend/app/src/app/app.component.ts b/frontend/app/src/app/app.component.ts index ebaf9295..a57fc615 100644 --- a/frontend/app/src/app/app.component.ts +++ b/frontend/app/src/app/app.component.ts @@ -17,10 +17,7 @@ import {Router} from '@angular/router'; import {App, URLOpenListenerEvent} from '@capacitor/app'; import {Platform, ToastController} from '@ionic/angular/standalone'; import {SettingsProvider} from './modules/settings/settings.provider'; -import { - increaseSessionCount, - startInappRatingIfFeasible, -} from './modules/settings/inapp-rating/inapp-rating.provider.js'; +import {InappRatingProvider} from './modules/settings/inapp-rating/inapp-rating.provider'; import {AuthHelperService} from './modules/auth/auth-helper.service'; import {environment} from '../environments/environment'; import {Capacitor} from '@capacitor/core'; @@ -28,7 +25,6 @@ import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.s import {Keyboard, KeyboardResize} from '@capacitor/keyboard'; import {AppVersionService} from './modules/about/app-version.service'; import {SplashScreen} from '@capacitor/splash-screen'; -import {StorageProvider} from './modules/storage/storage.provider.js'; /** * TODO @@ -60,7 +56,7 @@ export class AppComponent implements AfterContentInit { constructor( private readonly platform: Platform, private readonly settingsProvider: SettingsProvider, - private readonly storageProvider: StorageProvider, + private readonly inappRatingProvider: InappRatingProvider, private readonly router: Router, private readonly zone: NgZone, private readonly authHelper: AuthHelperService, @@ -92,8 +88,8 @@ export class AppComponent implements AfterContentInit { async hideSplash() { if (Capacitor.isNativePlatform()) { void SplashScreen.hide(); - void increaseSessionCount(this.storageProvider); - void startInappRatingIfFeasible(this.storageProvider); + void this.inappRatingProvider.increaseSessionCount(); + void this.inappRatingProvider.startInappRatingIfFeasible(); } } diff --git a/frontend/app/src/app/modules/settings/inapp-rating/inapp-rating.provider.ts b/frontend/app/src/app/modules/settings/inapp-rating/inapp-rating.provider.ts index 25802e57..642548c2 100644 --- a/frontend/app/src/app/modules/settings/inapp-rating/inapp-rating.provider.ts +++ b/frontend/app/src/app/modules/settings/inapp-rating/inapp-rating.provider.ts @@ -1,3 +1,4 @@ +import {Injectable} from '@angular/core'; import {InAppReview} from '@capacitor-community/in-app-review'; import {StorageProvider} from '../../storage/storage.provider'; @@ -10,97 +11,107 @@ export const INAPP_RATING_LAST_RATING_KEY = 'last-rating'; export type INAPP_RATING_KEYS = typeof INAPP_RATING_SESSIONS_KEY | typeof INAPP_RATING_LAST_RATING_KEY; /** - * + * Provider for app settings */ -function inappRatingSettingStorageKey(key: string): string { - return `${INAPP_RATING_SETTINGS_KEY}.${key}`; -} +@Injectable() +export class InappRatingProvider { + /** + * @param storageProvider TODO + */ + constructor(private readonly storageProvider: StorageProvider) {} -/** - * - */ -async function getInappRatingSetting( - storageProvider: StorageProvider, - key: INAPP_RATING_KEYS, - defaultValue: T, -): Promise { - try { - return await storageProvider.get(inappRatingSettingStorageKey(key)); - } catch { - return defaultValue; + /** + * + */ + private inappRatingSettingStorageKey(key: string): string { + return `${INAPP_RATING_SETTINGS_KEY}.${key}`; } -} -/** - * - */ -async function putInappRatingSetting(storageProvider: StorageProvider, key: INAPP_RATING_KEYS, value: T) { - return storageProvider.put(inappRatingSettingStorageKey(key), value); -} - -/** - * - */ -async function putInappRatingSessions(storageProvider: StorageProvider, value: number) { - return putInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, value); -} - -/** - * - */ -async function getInappRatingSessions(storageProvider: StorageProvider): Promise { - return getInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, 0); -} - -/** - * - */ -async function putInappRatingLastRating(storageProvider: StorageProvider, value: Date) { - return putInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, value.getTime()); -} - -/** - * - */ -async function getInappRatingLastRating(storageProvider: StorageProvider): Promise { - return getInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, 0).then(timestamp => { - return new Date(timestamp); - }); -} - -/** - * - */ -export async function increaseSessionCount(storageProvider: StorageProvider, increment = 1): Promise { - try { - const currentSessions = await getInappRatingSessions(storageProvider); - await putInappRatingSessions(storageProvider, currentSessions + increment); - return currentSessions + increment; - } catch { - return -1; + /** + * + */ + private async getInappRatingSetting( + key: INAPP_RATING_KEYS, + defaultValue: T, + ): Promise { + try { + return await this.storageProvider.get(this.inappRatingSettingStorageKey(key)); + } catch { + return defaultValue; + } } -} -/** - * - */ -export async function startInappRatingIfFeasible(storageProvider: StorageProvider): Promise { - try { - const currentSessions = await getInappRatingSessions(storageProvider); - const lastRating = await getInappRatingLastRating(storageProvider); - const dateDiffMillis = Math.abs(lastRating.getTime() - Date.now()); - const diffDays = Math.ceil(dateDiffMillis / (1000 * 3600 * 24)); + /** + * + */ + private async setInappRatingSetting(key: INAPP_RATING_KEYS, value: T) { + return this.storageProvider.put(this.inappRatingSettingStorageKey(key), value); + } - if (currentSessions < INAPP_RATING_NECESSARY_SESSIONS || diffDays < INAPP_RATING_COOLDOWN_DAYS) { + /** + * + */ + private async setInappRatingSessions(value: number) { + return this.setInappRatingSetting(INAPP_RATING_SESSIONS_KEY, value); + } + + /** + * + */ + private async getInappRatingSessions(): Promise { + return this.getInappRatingSetting(INAPP_RATING_SESSIONS_KEY, 0); + } + + /** + * + */ + private async setInappRatingLastRating(value: Date) { + return this.setInappRatingSetting(INAPP_RATING_SESSIONS_KEY, value.getTime()); + } + + /** + * + */ + private async getInappRatingLastRating(): Promise { + return this.getInappRatingSetting(INAPP_RATING_SESSIONS_KEY, 0).then(timestamp => { + return new Date(timestamp); + }); + } + + /** + * + */ + public async increaseSessionCount(increment = 1): Promise { + try { + const currentSessions = await this.getInappRatingSessions(); + await this.setInappRatingSessions(currentSessions + increment); + return currentSessions + increment; + } catch { + return -1; + } + } + + /** + * + */ + public async startInappRatingIfFeasible(): Promise { + try { + const currentSessions = await this.getInappRatingSessions(); + const lastRating = await this.getInappRatingLastRating(); + const dateDiffMillis = Math.abs(lastRating.getTime() - Date.now()); + const diffDays = Math.ceil(dateDiffMillis / (1000 * 3600 * 24)); + + if (currentSessions < INAPP_RATING_NECESSARY_SESSIONS || diffDays < INAPP_RATING_COOLDOWN_DAYS) { + return false; + } + + await InAppReview.requestReview(); + + await this.setInappRatingLastRating(new Date()); + + return true; + } catch { return false; } - - await InAppReview.requestReview(); - - await putInappRatingLastRating(storageProvider, new Date()); - - return true; - } catch { - return false; } } diff --git a/frontend/app/src/app/modules/settings/settings.module.ts b/frontend/app/src/app/modules/settings/settings.module.ts index 5f11a473..f919cfd5 100644 --- a/frontend/app/src/app/modules/settings/settings.module.ts +++ b/frontend/app/src/app/modules/settings/settings.module.ts @@ -55,6 +55,7 @@ import { IonToolbar, } from '@ionic/angular/standalone'; import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; +import {InappRatingProvider} from './inapp-rating/inapp-rating.provider'; const settingsRoutes: Routes = [{path: 'settings', component: SettingsPageComponent}]; @@ -101,6 +102,13 @@ const settingsRoutes: Routes = [{path: 'settings', component: SettingsPageCompon IonInput, IonNote, ], - providers: [ScheduleSyncService, SettingsProvider, CalendarService, ScheduleProvider, ThingTranslatePipe], + providers: [ + ScheduleSyncService, + SettingsProvider, + InappRatingProvider, + CalendarService, + ScheduleProvider, + ThingTranslatePipe, + ], }) export class SettingsModule {} diff --git a/frontend/app/src/app/modules/storage/storage.provider.spec.ts b/frontend/app/src/app/modules/storage/storage.provider.spec.ts index 6e916203..6ef66c58 100644 --- a/frontend/app/src/app/modules/storage/storage.provider.spec.ts +++ b/frontend/app/src/app/modules/storage/storage.provider.spec.ts @@ -106,7 +106,6 @@ describe('StorageProvider', () => { }); it('should put multiple values into the storage', async () => { - // @ts-expect-error no need to return anything for this case spyOn(storageProvider, 'put').and.callFake(() => Promise.resolve()); await storageProvider.putMultiple(sampleEntries);