feat: add in app rating

This commit is contained in:
Rainer Killinger
2025-08-12 18:08:09 +02:00
parent 1c39483e9d
commit 4a48e330bc
3 changed files with 116 additions and 1 deletions

View File

@@ -17,6 +17,10 @@ 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 {AuthHelperService} from './modules/auth/auth-helper.service';
import {environment} from '../environments/environment';
import {Capacitor} from '@capacitor/core';
@@ -24,6 +28,7 @@ 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
@@ -55,6 +60,7 @@ export class AppComponent implements AfterContentInit {
constructor(
private readonly platform: Platform,
private readonly settingsProvider: SettingsProvider,
private readonly storageProvider: StorageProvider,
private readonly router: Router,
private readonly zone: NgZone,
private readonly authHelper: AuthHelperService,
@@ -86,6 +92,8 @@ export class AppComponent implements AfterContentInit {
async hideSplash() {
if (Capacitor.isNativePlatform()) {
void SplashScreen.hide();
void increaseSessionCount(this.storageProvider);
void startInappRatingIfFeasible(this.storageProvider);
}
}

View File

@@ -0,0 +1,106 @@
import {InAppReview} from '@capacitor-community/in-app-review';
import {StorageProvider} from '../../storage/storage.provider';
export const INAPP_RATING_COOLDOWN_DAYS = 365;
export const INAPP_RATING_NECESSARY_SESSIONS = 2;
export const INAPP_RATING_SETTINGS_KEY = 'inapp-rating';
export const INAPP_RATING_SESSIONS_KEY = 'sessions';
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;
/**
*
*/
function inappRatingSettingStorageKey(key: string): string {
return `${INAPP_RATING_SETTINGS_KEY}.${key}`;
}
/**
*
*/
async function getInappRatingSetting<T>(
storageProvider: StorageProvider,
key: INAPP_RATING_KEYS,
defaultValue: T,
): Promise<typeof defaultValue> {
try {
return await storageProvider.get<typeof defaultValue>(inappRatingSettingStorageKey(key));
} catch {
return defaultValue;
}
}
/**
*
*/
async function putInappRatingSetting<T>(storageProvider: StorageProvider, key: INAPP_RATING_KEYS, value: T) {
return storageProvider.put<typeof value>(inappRatingSettingStorageKey(key), value);
}
/**
*
*/
async function putInappRatingSessions(storageProvider: StorageProvider, value: number) {
return putInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, value);
}
/**
*
*/
async function getInappRatingSessions(storageProvider: StorageProvider): Promise<number> {
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<Date> {
return getInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, 0).then(timestamp => {
return new Date(timestamp);
});
}
/**
*
*/
export async function increaseSessionCount(storageProvider: StorageProvider, increment = 1): Promise<number> {
try {
const currentSessions = await getInappRatingSessions(storageProvider);
await putInappRatingSessions(storageProvider, currentSessions + increment);
return currentSessions + increment;
} catch {
return -1;
}
}
/**
*
*/
export async function startInappRatingIfFeasible(storageProvider: StorageProvider): Promise<boolean> {
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));
if (currentSessions < INAPP_RATING_NECESSARY_SESSIONS || diffDays < INAPP_RATING_COOLDOWN_DAYS) {
return false;
}
await InAppReview.requestReview();
await putInappRatingLastRating(storageProvider, new Date());
return true;
} catch {
return false;
}
}

View File

@@ -120,8 +120,9 @@ export class StorageProvider {
* Puts a value of type T into the storage using provided key
* @param key Unique identifier
* @param value Resource to store under the key
* @returns Returns a promise that resolves when the key and value are set
*/
async put<T>(key: string, value: T): Promise<T> {
async put<T>(key: string, value: T) {
return this.storage.set(key, value);
}