102 lines
3.9 KiB
Kotlin
102 lines
3.9 KiB
Kotlin
package de.waypointaudio.license
|
|
|
|
/**
|
|
* v2.5.32 — Zentrale Feature-Berechtigungsprüfung.
|
|
*
|
|
* Diese Klasse kapselt alle Regeln, welche Lizenztypen Zugriff auf
|
|
* Profi-Funktionen gewähren. Sie liest ausschließlich aus [LicenseStatus]
|
|
* und ändert NIEMALS Lizenzdaten, Import-Logik, Signaturprüfung,
|
|
* Geräte-ID, CanonicalJson oder Backup-Regeln.
|
|
*
|
|
* Lizenztypen mit professionellem Zugang:
|
|
* - "pro", "profi", "commercial" → Profi-Zugang solange status == VALID
|
|
* - "developer" → immer erlaubt wenn status == VALID
|
|
* - "trial" → Profi-Zugang solange status == VALID (valid_until-Prüfung
|
|
* erfolgt bereits in LicenseValidator; ist abgelaufen → state == EXPIRED)
|
|
*
|
|
* Ohne Lizenz (state == NONE) oder mit abgelaufener/ungültiger Lizenz:
|
|
* - Keine Profi-Funktion freigegeben.
|
|
* - Vorhandene Daten (Zusatzclips, PTT-Aufnahmen, Zählerwerte) werden
|
|
* NIEMALS gelöscht.
|
|
*
|
|
* Feature-Gates:
|
|
* - [hasProfessionalAccess]: gemeinsames Haupt-Gate
|
|
* - [canUseMultiClip]: Zusatzclips bearbeiten/hinzufügen/aktivieren
|
|
* - [canUsePtt]: PTT-Modul anzeigen/nutzen
|
|
* - [canUseTourCounter]: Tour-Zähler anzeigen/nutzen
|
|
*
|
|
* UI-Empfehlung: Prüfe den Status über [LicenseStatusProvider.status], das
|
|
* als Compose-State vorliegt. Reagiert reaktiv auf Lizenzimport ohne
|
|
* App-Neustart.
|
|
*/
|
|
object LicenseFeatureAccess {
|
|
|
|
/**
|
|
* Professionelle Lizenztypen (case-insensitive), die Profi-Zugang gewähren.
|
|
*/
|
|
private val PRO_LICENSE_TYPES = setOf("pro", "profi", "commercial", "developer", "trial")
|
|
|
|
/**
|
|
* Prüft, ob die aktuelle Lizenz professionellen Zugang gewährt.
|
|
*
|
|
* Bedingungen:
|
|
* 1. [LicenseStatus.state] muss [LicenseStatus.State.VALID] sein.
|
|
* 2. [LicenseStatus.licenseTypeRaw] muss in [PRO_LICENSE_TYPES] enthalten sein
|
|
* (case-insensitive), ODER in [LicenseStatus.permissions] ist mindestens
|
|
* eine Profi-Permission gesetzt.
|
|
* 3. Developer-Lizenzen sind immer eingeschlossen, wenn state == VALID.
|
|
*/
|
|
fun hasProfessionalAccess(status: LicenseStatus): Boolean {
|
|
if (status.state != LicenseStatus.State.VALID) return false
|
|
val typeRaw = status.licenseTypeRaw?.lowercase()?.trim() ?: ""
|
|
if (typeRaw in PRO_LICENSE_TYPES) return true
|
|
// Fallback: explizite Permissions (z. B. "commercial_use" oder "paid_tours")
|
|
return status.permissions.any { (_, v) -> v }
|
|
}
|
|
|
|
/**
|
|
* Shortcut: Liest den aktuellen Status direkt aus [LicenseStatusProvider].
|
|
* Für Compose-Code bevorzuge den Status-Parameter, damit die Rekomposition
|
|
* reaktiv funktioniert.
|
|
*/
|
|
fun hasProfessionalAccessCurrent(): Boolean =
|
|
hasProfessionalAccess(LicenseStatusProvider.current())
|
|
|
|
/**
|
|
* Multi-Clip-Waypoints: Bearbeiten, Hinzufügen, Aktivieren von Zusatzclips.
|
|
* Hauptclip (index 0 / isPrimary) bleibt immer frei.
|
|
* Bestehende Clips werden niemals gelöscht.
|
|
*/
|
|
fun canUseMultiClip(status: LicenseStatus): Boolean = hasProfessionalAccess(status)
|
|
|
|
/**
|
|
* PTT (Push-to-Talk): Live-PTT-Modul, Aufnahmen starten.
|
|
* Bestehende PTT-Aufnahmen bleiben erhalten.
|
|
*/
|
|
fun canUsePtt(status: LicenseStatus): Boolean = hasProfessionalAccess(status)
|
|
|
|
/**
|
|
* Tour-Zähler: Abspiel-Modi, Zähler-Reset, Vorgaben.
|
|
* Bestehende Zählerwerte bleiben erhalten.
|
|
*/
|
|
fun canUseTourCounter(status: LicenseStatus): Boolean = hasProfessionalAccess(status)
|
|
|
|
/**
|
|
* Freundlicher Hinweistext für das Multi-Clip-Gate.
|
|
*/
|
|
const val MSG_MULTI_CLIP =
|
|
"Multi-Clip-Waypoints sind Teil der GPS2Audio Profi-Lizenz."
|
|
|
|
/**
|
|
* Freundlicher Hinweistext für das PTT-Gate.
|
|
*/
|
|
const val MSG_PTT =
|
|
"Live-PTT ist Teil der GPS2Audio Profi-Lizenz."
|
|
|
|
/**
|
|
* Freundlicher Hinweistext für das Tour-Zähler-Gate.
|
|
*/
|
|
const val MSG_TOUR_COUNTER =
|
|
"Der Tour-Zähler ist Teil der GPS2Audio Profi-Lizenz."
|
|
}
|