feat: Push-Hinweis nach Erstellen eines Crew-Einladungslinks
Owner sieht einen Dialog zur Aktivierung von Crew-Push-Benachrichtigungen, sofern diese noch nicht aktiv sind. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,6 +6,12 @@ import LogbookBackupPanel from './LogbookBackupPanel.tsx'
|
|||||||
import { useDialog } from './ModalDialog.tsx'
|
import { useDialog } from './ModalDialog.tsx'
|
||||||
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
|
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
|
||||||
import { apiFetch } from '../services/api.js'
|
import { apiFetch } from '../services/api.js'
|
||||||
|
import {
|
||||||
|
enableCollaboratorChangePush,
|
||||||
|
isCollaboratorPushActive,
|
||||||
|
isPushSupported
|
||||||
|
} from '../services/pushNotifications.js'
|
||||||
|
import { isIosDevice, isRunningStandalone } from '../hooks/usePwaInstall.js'
|
||||||
|
|
||||||
interface SettingsFormProps {
|
interface SettingsFormProps {
|
||||||
logbookId?: string | null
|
logbookId?: string | null
|
||||||
@@ -151,6 +157,43 @@ export default function SettingsForm({ logbookId, onLogbookRestored }: SettingsF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const promptPushAfterInviteCreated = async () => {
|
||||||
|
if (!isPushSupported()) return
|
||||||
|
if (await isCollaboratorPushActive()) return
|
||||||
|
|
||||||
|
const iosNeedsInstall = isIosDevice() && !isRunningStandalone()
|
||||||
|
|
||||||
|
if (iosNeedsInstall) {
|
||||||
|
await showAlert(
|
||||||
|
t('settings.invite_push_prompt_ios_message'),
|
||||||
|
t('settings.invite_push_prompt_title'),
|
||||||
|
t('settings.invite_push_prompt_later')
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const enable = await showConfirm(
|
||||||
|
t('settings.invite_push_prompt_message'),
|
||||||
|
t('settings.invite_push_prompt_title'),
|
||||||
|
t('settings.invite_push_prompt_enable'),
|
||||||
|
t('settings.invite_push_prompt_later')
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!enable) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
await enableCollaboratorChangePush()
|
||||||
|
await showAlert(
|
||||||
|
t('settings.invite_push_prompt_success'),
|
||||||
|
t('settings.invite_push_prompt_title')
|
||||||
|
)
|
||||||
|
trackPlausibleEvent(PlausibleEvents.PUSH_ENABLED)
|
||||||
|
} catch (err: unknown) {
|
||||||
|
console.error('Failed to enable push after invite:', err)
|
||||||
|
showAlert(err instanceof Error ? err.message : t('profile.push_error'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleGenerateInvite = async () => {
|
const handleGenerateInvite = async () => {
|
||||||
if (!logbookId) return
|
if (!logbookId) return
|
||||||
setGeneratingInvite(true)
|
setGeneratingInvite(true)
|
||||||
@@ -175,6 +218,7 @@ export default function SettingsForm({ logbookId, onLogbookRestored }: SettingsF
|
|||||||
|
|
||||||
setInviteLink(link)
|
setInviteLink(link)
|
||||||
trackPlausibleEvent(PlausibleEvents.INVITE_GENERATED)
|
trackPlausibleEvent(PlausibleEvents.INVITE_GENERATED)
|
||||||
|
await promptPushAfterInviteCreated()
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
console.error('Failed to generate invite:', err)
|
console.error('Failed to generate invite:', err)
|
||||||
showAlert(err instanceof Error ? err.message : 'Failed to generate invite link.')
|
showAlert(err instanceof Error ? err.message : 'Failed to generate invite link.')
|
||||||
|
|||||||
@@ -482,6 +482,12 @@
|
|||||||
"delete_account_failed": "Konto konnte nicht gelöscht werden. Bitte versuche es erneut.",
|
"delete_account_failed": "Konto konnte nicht gelöscht werden. Bitte versuche es erneut.",
|
||||||
"delete_backup_hint": "Tipp: Erstelle vor dem Löschen Backups deiner Logbücher (.daagbok.json) in den Einstellungen jedes Logbuchs.",
|
"delete_backup_hint": "Tipp: Erstelle vor dem Löschen Backups deiner Logbücher (.daagbok.json) in den Einstellungen jedes Logbuchs.",
|
||||||
"deleting_account": "Konto wird gelöscht…",
|
"deleting_account": "Konto wird gelöscht…",
|
||||||
|
"invite_push_prompt_title": "Push-Benachrichtigungen aktivieren?",
|
||||||
|
"invite_push_prompt_message": "Sobald eingeladene Crewmitglieder Änderungen synchronisieren, kannst du per Push informiert werden. Es werden keine Logbuch-Inhalte im Klartext gesendet.",
|
||||||
|
"invite_push_prompt_ios_message": "Sobald Crewmitglieder Änderungen synchronisieren, kannst du per Push informiert werden. Auf dem iPhone/iPad: App zum Home-Bildschirm hinzufügen (iOS 16.4+), dann Push im Benutzerprofil aktivieren.",
|
||||||
|
"invite_push_prompt_enable": "Jetzt aktivieren",
|
||||||
|
"invite_push_prompt_later": "Später",
|
||||||
|
"invite_push_prompt_success": "Push-Benachrichtigungen sind auf diesem Gerät aktiv.",
|
||||||
"backup_title": "Backup & Wiederherstellung",
|
"backup_title": "Backup & Wiederherstellung",
|
||||||
"backup_desc": "Vollständiges verschlüsseltes Backup dieses Logbuchs (Einträge, Fotos, GPS-Tracks, Crew, Schiff). Mit Backup-Passphrase geschützt — für Restore auf diesem oder einem neuen Account.",
|
"backup_desc": "Vollständiges verschlüsseltes Backup dieses Logbuchs (Einträge, Fotos, GPS-Tracks, Crew, Schiff). Mit Backup-Passphrase geschützt — für Restore auf diesem oder einem neuen Account.",
|
||||||
"backup_export_title": "Backup erstellen",
|
"backup_export_title": "Backup erstellen",
|
||||||
|
|||||||
@@ -482,6 +482,12 @@
|
|||||||
"delete_account_failed": "Failed to delete account. Please try again.",
|
"delete_account_failed": "Failed to delete account. Please try again.",
|
||||||
"delete_backup_hint": "Tip: Before deleting, create backups of your logbooks (.daagbok.json) in each logbook's settings.",
|
"delete_backup_hint": "Tip: Before deleting, create backups of your logbooks (.daagbok.json) in each logbook's settings.",
|
||||||
"deleting_account": "Deleting account…",
|
"deleting_account": "Deleting account…",
|
||||||
|
"invite_push_prompt_title": "Enable push notifications?",
|
||||||
|
"invite_push_prompt_message": "When invited crew members sync changes, you can be notified via push. No logbook content is sent in plain text.",
|
||||||
|
"invite_push_prompt_ios_message": "When crew members sync changes, you can get push notifications. On iPhone/iPad: add the app to your Home Screen (iOS 16.4+), then enable push in your user profile.",
|
||||||
|
"invite_push_prompt_enable": "Enable now",
|
||||||
|
"invite_push_prompt_later": "Later",
|
||||||
|
"invite_push_prompt_success": "Push notifications are active on this device.",
|
||||||
"backup_title": "Backup & restore",
|
"backup_title": "Backup & restore",
|
||||||
"backup_desc": "Full encrypted backup of this logbook (entries, photos, GPS tracks, crew, vessel). Protected with a backup passphrase — restore on this or a new account.",
|
"backup_desc": "Full encrypted backup of this logbook (entries, photos, GPS tracks, crew, vessel). Protected with a backup passphrase — restore on this or a new account.",
|
||||||
"backup_export_title": "Create backup",
|
"backup_export_title": "Create backup",
|
||||||
|
|||||||
@@ -43,6 +43,18 @@ async function fetchVapidPublicKey(): Promise<string | null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** True when crew-change push is enabled and notification permission is granted. */
|
||||||
|
export async function isCollaboratorPushActive(): Promise<boolean> {
|
||||||
|
if (!isPushSupported()) return false
|
||||||
|
if (getNotificationPermission() !== 'granted') return false
|
||||||
|
try {
|
||||||
|
const prefs = await fetchPushPrefs()
|
||||||
|
return prefs.collaboratorChangesEnabled
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchPushPrefs(): Promise<{ collaboratorChangesEnabled: boolean }> {
|
export async function fetchPushPrefs(): Promise<{ collaboratorChangesEnabled: boolean }> {
|
||||||
if (!localStorage.getItem('active_userid')) {
|
if (!localStorage.getItem('active_userid')) {
|
||||||
return { collaboratorChangesEnabled: false }
|
return { collaboratorChangesEnabled: false }
|
||||||
|
|||||||
Reference in New Issue
Block a user