197bddcd7e
CRÍTICO — enlaces del App Store rotos (adquisición viral = 0): - GoalShareService.appStoreURL apuntaba a id6744983373 (404): el QR de TODAS las imágenes compartidas llevaba a una página muerta. Corregido a id6757678318. - SettingsView enlazaba id6741412965 (una novela romántica). Ahora usa la constante. Monetización: - IAPService multi-producto: sub anual (com.portfoliojournal.premium.annual, con intro offer/trial) + lifetime como ancla. isPremium acepta cualquiera de los dos. Paywall con selector de plan (anual por defecto si existe; degrada a solo lifetime mientras el producto no esté creado en App Store Connect). - paywallBenefits: añadidos Multiple Accounts y Family Sharing (diferenciadores). - Teaser de historia bloqueada en Charts: "N meses más con Premium" en vez de truncar en silencio (FreemiumValidator.hiddenHistoryMonths + banner). - Trigger de paywall de backups ahora instrumentado (logPaywallShown "backups"). Retención / adquisición: - Rating velocity: prompt tras 2 check-ins y 30 días (antes 3 + 90 — en una app mensual eso era >3 meses sin poder pedir la primera review con ~0 ratings). - Sample data ON por defecto en onboarding (skip ya no aterriza en dashboard vacío). - Notificación de protección de streak el día 25 si el check-in del mes está pendiente. - App Intents + AppShortcutsProvider: "Update my portfolio" / "Check my portfolio" vía Siri/Shortcuts/Spotlight. - Instrumentación: onboarding_step/onboarding_skipped y content_shared (viral loop). - ScreenshotMode (--screenshots) para capturas de marketing automatizadas. ASO: - 6 locales nuevos en metadata (en-GB, en-CA, en-AU, es-MX, fr-CA, pt-PT) reusando traducciones — 6 campos de keywords extra; pt-PT adaptado (reforma). - Categoría secundaria: PRODUCTIVITY. - 17 strings nuevas localizadas en los 7 idiomas. Pendiente manual: crear la sub anual en App Store Connect (grupo de suscripción + intro offer 7 días) con el id exacto com.portfoliojournal.premium.annual. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015qUZrBusG82T37R7PeokqJ
58 lines
2.1 KiB
Swift
58 lines
2.1 KiB
Swift
import AppIntents
|
|
import Foundation
|
|
|
|
// MARK: - App Intents (Siri / Shortcuts / Spotlight)
|
|
//
|
|
// Surfaces the core monthly habit outside the app: "Update my portfolio" opens
|
|
// Quick Update directly, "Check my portfolio" opens the dashboard. Registering an
|
|
// AppShortcutsProvider also lists these actions in Spotlight and the Shortcuts app
|
|
// with zero user setup — a discovery/retention surface the app didn't have.
|
|
|
|
struct QuickUpdateIntent: AppIntent {
|
|
static let title: LocalizedStringResource = "Update Portfolio"
|
|
static let description = IntentDescription("Open Quick Update to record your latest portfolio values.")
|
|
static let openAppWhenRun = true
|
|
|
|
@MainActor
|
|
func perform() async throws -> some IntentResult {
|
|
// Same signal the widget deep link uses; ContentView routes it to the sheet.
|
|
NotificationCenter.default.post(name: .openQuickUpdate, object: nil)
|
|
return .result()
|
|
}
|
|
}
|
|
|
|
struct OpenDashboardIntent: AppIntent {
|
|
static let title: LocalizedStringResource = "Check Portfolio"
|
|
static let description = IntentDescription("Open the dashboard to see your net worth and charts.")
|
|
static let openAppWhenRun = true
|
|
|
|
@MainActor
|
|
func perform() async throws -> some IntentResult {
|
|
NotificationCenter.default.post(name: .openDashboard, object: nil)
|
|
return .result()
|
|
}
|
|
}
|
|
|
|
struct PortfolioJournalShortcuts: AppShortcutsProvider {
|
|
static var appShortcuts: [AppShortcut] {
|
|
AppShortcut(
|
|
intent: QuickUpdateIntent(),
|
|
phrases: [
|
|
"Update my portfolio in \(.applicationName)",
|
|
"Add a snapshot in \(.applicationName)"
|
|
],
|
|
shortTitle: "Update Portfolio",
|
|
systemImageName: "plus.circle.fill"
|
|
)
|
|
AppShortcut(
|
|
intent: OpenDashboardIntent(),
|
|
phrases: [
|
|
"Check my portfolio in \(.applicationName)",
|
|
"Show my net worth in \(.applicationName)"
|
|
],
|
|
shortTitle: "Check Portfolio",
|
|
systemImageName: "chart.line.uptrend.xyaxis"
|
|
)
|
|
}
|
|
}
|