From 83e3af9a424d31832aab4d5ad892b4ed93aca96a Mon Sep 17 00:00:00 2001 From: Arseni Date: Thu, 11 Dec 2025 17:41:25 +0300 Subject: [PATCH] Fixes for PostHog --- frontend/pshared/lib/config/common.dart | 4 + frontend/pshared/lib/config/mobile.dart | 2 + frontend/pshared/lib/config/web.dart | 6 + frontend/pshared/lib/models/resources.dart | 4 + frontend/pshared/lib/provider/account.dart | 24 ++++ .../pshared/lib/provider/permissions.dart | 8 ++ frontend/pweb/lib/main.dart | 16 ++- .../lib/pages/address_book/form/page.dart | 13 +- frontend/pweb/lib/pages/loaders/account.dart | 57 +++++--- .../pweb/lib/pages/loaders/permissions.dart | 21 ++- frontend/pweb/lib/pages/login/form.dart | 4 + .../pweb/lib/pages/payment_methods/page.dart | 5 +- .../settings/profile/account/locale.dart | 4 +- frontend/pweb/lib/services/posthog.dart | 136 ++++++++++++++++++ frontend/pweb/lib/utils/logout.dart | 2 + .../pweb/lib/widgets/sidebar/side_menu.dart | 6 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 + frontend/pweb/pubspec.yaml | 1 + 18 files changed, 276 insertions(+), 39 deletions(-) create mode 100644 frontend/pweb/lib/services/posthog.dart diff --git a/frontend/pshared/lib/config/common.dart b/frontend/pshared/lib/config/common.dart index c2240f9..8f2702b 100644 --- a/frontend/pshared/lib/config/common.dart +++ b/frontend/pshared/lib/config/common.dart @@ -11,6 +11,8 @@ class CommonConstants { static String apiEndpoint = '/api/v1'; static String amplitudeSecret = 'c3d75b3e2520d708440acbb16b923e79'; static String amplitudeServerZone = 'EU'; + static String posthogApiKey = ''; + static String posthogHost = 'https://eu.i.posthog.com'; static Locale defaultLocale = const Locale('en'); static String defaultCurrency = 'EUR'; static int defaultDimensionLength = 500; @@ -36,6 +38,8 @@ class CommonConstants { apiEndpoint = configJson['apiEndpoint'] ?? apiEndpoint; amplitudeSecret = configJson['amplitudeSecret'] ?? amplitudeSecret; amplitudeServerZone = configJson['amplitudeServerZone'] ?? amplitudeServerZone; + posthogApiKey = configJson['posthogApiKey'] ?? posthogApiKey; + posthogHost = configJson['posthogHost'] ?? posthogHost; defaultLocale = Locale(configJson['defaultLocale'] ?? defaultLocale.languageCode); defaultCurrency = configJson['defaultCurrency'] ?? defaultCurrency; wsProto = configJson['wsProto'] ?? wsProto; diff --git a/frontend/pshared/lib/config/mobile.dart b/frontend/pshared/lib/config/mobile.dart index ec5f56d..d340010 100644 --- a/frontend/pshared/lib/config/mobile.dart +++ b/frontend/pshared/lib/config/mobile.dart @@ -15,6 +15,8 @@ class Constants extends CommonConstants { static String get currentOrgKey => CommonConstants.currentOrgKey; static String get apiUrl => CommonConstants.apiUrl; static String get serviceUrl => CommonConstants.serviceUrl; + static String get posthogApiKey => CommonConstants.posthogApiKey; + static String get posthogHost => CommonConstants.posthogHost; static int get defaultDimensionLength => CommonConstants.defaultDimensionLength; static String get deviceIdStorageKey => CommonConstants.deviceIdStorageKey; static String get nilObjectRef => CommonConstants.nilObjectRef; diff --git a/frontend/pshared/lib/config/web.dart b/frontend/pshared/lib/config/web.dart index cc49d85..8339cf5 100644 --- a/frontend/pshared/lib/config/web.dart +++ b/frontend/pshared/lib/config/web.dart @@ -21,6 +21,8 @@ extension AppConfigExtension on AppConfig { external String? get apiEndpoint; external String? get amplitudeSecret; external String? get amplitudeServerZone; + external String? get posthogApiKey; + external String? get posthogHost; external String? get defaultLocale; external String? get wsProto; external String? get wsEndpoint; @@ -40,6 +42,8 @@ class Constants extends CommonConstants { static String get currentOrgKey => CommonConstants.currentOrgKey; static String get apiUrl => CommonConstants.apiUrl; static String get serviceUrl => CommonConstants.serviceUrl; + static String get posthogApiKey => CommonConstants.posthogApiKey; + static String get posthogHost => CommonConstants.posthogHost; static int get defaultDimensionLength => CommonConstants.defaultDimensionLength; static String get deviceIdStorageKey => CommonConstants.deviceIdStorageKey; static String get nilObjectRef => CommonConstants.nilObjectRef; @@ -57,6 +61,8 @@ class Constants extends CommonConstants { 'apiEndpoint': config.apiEndpoint, 'amplitudeSecret': config.amplitudeSecret, 'amplitudeServerZone': config.amplitudeServerZone, + 'posthogApiKey': config.posthogApiKey, + 'posthogHost': config.posthogHost, 'defaultLocale': config.defaultLocale, 'wsProto': config.wsProto, 'wsEndpoint': config.wsEndpoint, diff --git a/frontend/pshared/lib/models/resources.dart b/frontend/pshared/lib/models/resources.dart index 41cdedf..662f9ab 100644 --- a/frontend/pshared/lib/models/resources.dart +++ b/frontend/pshared/lib/models/resources.dart @@ -79,6 +79,10 @@ enum ResourceType { @JsonValue('payments') payments, + /// Represents payment orchestration service + @JsonValue('payment_orchestrator') + paymentOrchestrator, + @JsonValue('payment_methods') paymentMethods, diff --git a/frontend/pshared/lib/provider/account.dart b/frontend/pshared/lib/provider/account.dart index 9413913..4140d54 100644 --- a/frontend/pshared/lib/provider/account.dart +++ b/frontend/pshared/lib/provider/account.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:share_plus/share_plus.dart'; @@ -20,6 +22,9 @@ import 'package:pshared/utils/exception.dart'; class AccountProvider extends ChangeNotifier { + AccountProvider({Future Function(Account?)? onAccountChanged}) + : _onAccountChanged = onAccountChanged; + static String get currentUserRef => Constants.nilObjectRef; // The resource now wraps our Account? state along with its loading/error state. @@ -27,6 +32,8 @@ class AccountProvider extends ChangeNotifier { Resource get resource => _resource; late LocaleProvider _localeProvider; PendingLogin? _pendingLogin; + Future? _restoreFuture; + Future Function(Account?)? _onAccountChanged; Account? get account => _resource.data; PendingLogin? get pendingLogin => _pendingLogin; @@ -53,11 +60,21 @@ class AccountProvider extends ChangeNotifier { } // Private helper to update the resource and notify listeners. + void setAccountChangedListener(Future Function(Account?)? listener) => _onAccountChanged = listener; + void _setResource(Resource newResource) { + final previousAccount = _resource.data; _resource = newResource; + _notifyAccountChanged(previousAccount, newResource.data); notifyListeners(); } + void _notifyAccountChanged(Account? previous, Account? current) { + if (previous == current) return; + final handler = _onAccountChanged; + if (handler != null) unawaited(handler(current)); + } + void updateProvider(LocaleProvider localeProvider) => _localeProvider = localeProvider; void _pickupLocale(String locale) => _localeProvider.setLocale(Locale(locale)); @@ -220,4 +237,11 @@ class AccountProvider extends ChangeNotifier { rethrow; } } + + Future restoreIfPossible() { + return _restoreFuture ??= AuthorizationService.isAuthorizationStored().then((hasAuth) async { + if (!hasAuth) return; + await restore(); + }); + } } diff --git a/frontend/pshared/lib/provider/permissions.dart b/frontend/pshared/lib/provider/permissions.dart index 7b6e0d5..06fd019 100644 --- a/frontend/pshared/lib/provider/permissions.dart +++ b/frontend/pshared/lib/provider/permissions.dart @@ -21,6 +21,7 @@ class PermissionsProvider extends ChangeNotifier { Resource _userAccess = Resource(data: null, isLoading: false, error: null); late OrganizationsProvider _organizations; bool _isLoaded = false; + bool _errorHandled = false; void update(OrganizationsProvider venue) { _organizations = venue; @@ -44,6 +45,7 @@ class PermissionsProvider extends ChangeNotifier { /// Load the [UserAccess] for the current venue. Future load() async { _userAccess = _userAccess.copyWith(isLoading: true, error: null); + _errorHandled = false; notifyListeners(); try { @@ -67,6 +69,12 @@ class PermissionsProvider extends ChangeNotifier { return _userAccess.data; } + bool get hasUnhandledError => error != null && !_errorHandled; + + void markErrorHandled() { + _errorHandled = true; + } + Future changeRole(String accountRef, String newRoleDescRef) async { final currentRole = roles.firstWhereOrNull((r) => r.accountRef == accountRef); final currentDesc = currentRole != null diff --git a/frontend/pweb/lib/main.dart b/frontend/pweb/lib/main.dart index 696d989..347b85d 100644 --- a/frontend/pweb/lib/main.dart +++ b/frontend/pweb/lib/main.dart @@ -27,6 +27,7 @@ import 'package:pweb/providers/wallets.dart'; import 'package:pweb/providers/wallet_transactions.dart'; import 'package:pweb/services/operations.dart'; import 'package:pweb/services/payments/history.dart'; +import 'package:pweb/services/posthog.dart'; import 'package:pweb/services/wallet_transactions.dart'; import 'package:pweb/services/wallets.dart'; @@ -40,11 +41,9 @@ void _setupLogging() { } void main() async { - await Constants.initialize(); - WidgetsFlutterBinding.ensureInitialized(); - - // await AmplitudeService.initialize(); + await Constants.initialize(); + await PosthogService.initialize(); _setupLogging(); @@ -57,7 +56,12 @@ void main() async { providers: [ ChangeNotifierProvider(create: (_) => LocaleProvider(null)), ChangeNotifierProxyProvider( - create: (_) => AccountProvider(), + create: (_) => AccountProvider( + onAccountChanged: (account) { + if (account == null) return Future.value(); + return PosthogService.identify(account); + }, + ), update: (context, localeProvider, provider) => provider!..updateProvider(localeProvider), ), ChangeNotifierProxyProvider( @@ -70,6 +74,7 @@ void main() async { update: (context, orgnization, provider) => provider!..update(orgnization), ), ChangeNotifierProvider(create: (_) => CarouselIndexProvider()), + ChangeNotifierProvider( create: (_) => UploadHistoryProvider(service: MockUploadHistoryService())..load(), ), @@ -91,6 +96,7 @@ void main() async { ChangeNotifierProvider( create: (_) => MockPaymentProvider(), ), + ChangeNotifierProvider( create: (_) => OperationProvider(OperationService())..loadOperations(), ), diff --git a/frontend/pweb/lib/pages/address_book/form/page.dart b/frontend/pweb/lib/pages/address_book/form/page.dart index 0404025..00186f5 100644 --- a/frontend/pweb/lib/pages/address_book/form/page.dart +++ b/frontend/pweb/lib/pages/address_book/form/page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; @@ -14,6 +16,7 @@ import 'package:pshared/provider/recipient/pmethods.dart'; import 'package:pshared/provider/recipient/provider.dart'; import 'package:pweb/pages/address_book/form/view.dart'; +import 'package:pweb/services/posthog.dart'; import 'package:pweb/utils/error/snackbar.dart'; import 'package:pweb/utils/payment/label.dart'; import 'package:pweb/utils/snackbar.dart'; @@ -106,11 +109,11 @@ class _AdressBookRecipientFormState extends State { return; } - // AmplitudeService.recipientAddCompleted( - // _type, - // _status, - // _methods.keys.toSet(), - // ); + unawaited(PosthogService.recipientAddCompleted( + _type, + _status, + _methods.keys.toSet(), + )); final recipient = await executeActionWithNotification( context: context, action: _doSave, diff --git a/frontend/pweb/lib/pages/loaders/account.dart b/frontend/pweb/lib/pages/loaders/account.dart index d891e1c..9bd6fcc 100644 --- a/frontend/pweb/lib/pages/loaders/account.dart +++ b/frontend/pweb/lib/pages/loaders/account.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; @@ -10,26 +11,50 @@ import 'package:pweb/widgets/error/snackbar.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; -class AccountLoader extends StatelessWidget { +class AccountLoader extends StatefulWidget { final Widget child; - const AccountLoader({super.key, required this.child}); @override - Widget build(BuildContext context) => Consumer(builder: (context, provider, _) { - if (provider.isLoading) return const Center(child: CircularProgressIndicator()); - if (provider.error != null) { - postNotifyUserOfErrorX( - context: context, - errorSituation: AppLocalizations.of(context)!.errorLogin, - exception: provider.error!, - ); - navigateAndReplace(context, Pages.login); - } - if (provider.account == null) { + State createState() => _AccountLoaderState(); +} + +class _AccountLoaderState extends State { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + final provider = Provider.of(context, listen: false); + if (provider.account == null) { + provider.restoreIfPossible().catchError((error, stack) { + Logger('Account restore failed: $error'); + }); + } + }); + } + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, provider, _) { + if (provider.account != null) { + return widget.child; + } + + if (provider.error != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + postNotifyUserOfErrorX( + context: context, + errorSituation: AppLocalizations.of(context)!.errorLogin, + exception: provider.error!, + ); + navigateAndReplace(context, Pages.login); + }); + return const Center(child: CircularProgressIndicator()); + } + + if (provider.isLoading) return const Center(child: CircularProgressIndicator()); WidgetsBinding.instance.addPostFrameCallback((_) => navigateAndReplace(context, Pages.login)); return const Center(child: CircularProgressIndicator()); - } - return child; - }); + }); + } } diff --git a/frontend/pweb/lib/pages/loaders/permissions.dart b/frontend/pweb/lib/pages/loaders/permissions.dart index b77a7de..6d93ddb 100644 --- a/frontend/pweb/lib/pages/loaders/permissions.dart +++ b/frontend/pweb/lib/pages/loaders/permissions.dart @@ -21,20 +21,29 @@ class PermissionsLoader extends StatelessWidget { if (provider.isLoading) { return const Center(child: CircularProgressIndicator()); } + if (provider.error != null) { - postNotifyUserOfErrorX( - context: context, - errorSituation: AppLocalizations.of(context)!.errorLogin, - exception: provider.error!, - ); - navigateAndReplace(context, Pages.login); + if (provider.hasUnhandledError) { + provider.markErrorHandled(); + WidgetsBinding.instance.addPostFrameCallback((_) { + postNotifyUserOfErrorX( + context: context, + errorSituation: AppLocalizations.of(context)!.errorLogin, + exception: provider.error!, + ); + navigateAndReplace(context, Pages.login); + }); + } + return const Center(child: CircularProgressIndicator()); } + if (provider.error == null && !provider.isReady && accountProvider.account != null) { WidgetsBinding.instance.addPostFrameCallback((_) { provider.load(); }); return const Center(child: CircularProgressIndicator()); } + return child; }); } diff --git a/frontend/pweb/lib/pages/login/form.dart b/frontend/pweb/lib/pages/login/form.dart index 1eb3bcc..29b1dce 100644 --- a/frontend/pweb/lib/pages/login/form.dart +++ b/frontend/pweb/lib/pages/login/form.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -14,6 +16,7 @@ import 'package:pweb/widgets/password/password.dart'; import 'package:pweb/widgets/username.dart'; import 'package:pweb/widgets/vspacer.dart'; import 'package:pweb/widgets/error/snackbar.dart'; +import 'package:pweb/services/posthog.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; @@ -43,6 +46,7 @@ class _LoginFormState extends State { password: _passwordController.text, locale: context.read().locale.languageCode, ); + unawaited(PosthogService.login(pending: outcome.isPending)); if (outcome.isPending) { // TODO: fix context usage navigateAndReplace(context, Pages.sfactor); diff --git a/frontend/pweb/lib/pages/payment_methods/page.dart b/frontend/pweb/lib/pages/payment_methods/page.dart index 44d3dd9..ccf4b7a 100644 --- a/frontend/pweb/lib/pages/payment_methods/page.dart +++ b/frontend/pweb/lib/pages/payment_methods/page.dart @@ -16,6 +16,7 @@ import 'package:pweb/providers/payment_flow.dart'; import 'package:pweb/pages/payment_methods/payment_page/body.dart'; import 'package:pweb/providers/wallets.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; +import 'package:pweb/services/posthog.dart'; class PaymentPage extends StatefulWidget { @@ -109,7 +110,7 @@ class _PaymentPageState extends State { void _handleSendPayment() { // TODO: Handle Payment logic - // AmplitudeService.paymentInitiated(); + PosthogService.paymentInitiated(method: _flowProvider.selectedType); } @override @@ -195,4 +196,4 @@ class _PaymentPageState extends State { (method.description?.contains(wallet.walletUserID) ?? false), ); } -} \ No newline at end of file +} diff --git a/frontend/pweb/lib/pages/settings/profile/account/locale.dart b/frontend/pweb/lib/pages/settings/profile/account/locale.dart index 4c11cc5..2208197 100644 --- a/frontend/pweb/lib/pages/settings/profile/account/locale.dart +++ b/frontend/pweb/lib/pages/settings/profile/account/locale.dart @@ -4,7 +4,7 @@ import 'package:provider/provider.dart'; import 'package:pshared/provider/locale.dart'; -// import 'package:pweb/services/amplitude.dart'; +import 'package:pweb/services/posthog.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; @@ -58,7 +58,7 @@ class LocalePicker extends StatelessWidget { onChanged: (locale) { if (locale != null) { localeProvider.setLocale(locale); - // AmplitudeService.localeChanged(locale); + PosthogService.localeChanged(locale); } }, decoration: const InputDecoration( diff --git a/frontend/pweb/lib/services/posthog.dart b/frontend/pweb/lib/services/posthog.dart new file mode 100644 index 0000000..15ceaf2 --- /dev/null +++ b/frontend/pweb/lib/services/posthog.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; + +import 'package:logging/logging.dart'; + +import 'package:posthog_flutter/posthog_flutter.dart'; + +import 'package:pshared/config/constants.dart'; +import 'package:pshared/models/account/account.dart'; +import 'package:pshared/models/payment/type.dart'; +import 'package:pshared/models/recipient/status.dart'; +import 'package:pshared/models/recipient/type.dart'; + +import 'package:pweb/widgets/sidebar/destinations.dart'; + + +class PosthogService { + static final _logger = Logger('service.posthog'); + static String? _identifiedUserId; + static bool _initialized = false; + + static bool get isEnabled => _initialized; + + static Future initialize() async { + final apiKey = Constants.posthogApiKey; + if (apiKey.isEmpty) { + _logger.warning('PostHog API key is not configured, analytics disabled.'); + return; + } + + try { + final config = PostHogConfig(apiKey) + ..host = Constants.posthogHost + ..captureApplicationLifecycleEvents = true; + await Posthog().setup(config); + await Posthog().register('client_id', Constants.clientId); + _initialized = true; + _logger.info('PostHog initialized with host ${Constants.posthogHost}'); + } catch (e, st) { + _initialized = false; + _logger.warning('Failed to initialize PostHog: $e', e, st); + } + } + + static Future identify(Account account) async { + if (!_initialized) return; + if (_identifiedUserId == account.id) return; + + await Posthog().identify( + userId: account.id, + userProperties: { + 'email': account.login, + 'name': account.name, + 'locale': account.locale, + 'created_at': account.createdAt.toIso8601String(), + }, + ); + _identifiedUserId = account.id; + } + + static Future reset() async { + if (!_initialized) return; + _identifiedUserId = null; + await Posthog().reset(); + } + + static Future login({required bool pending}) async { + if (!_initialized) return; + await _capture( + 'login', + properties: { + 'result': pending ? 'pending' : 'success', + }, + ); + } + + static Future pageOpened(PayoutDestination page, {String? path, String? uiSource}) async { + if (!_initialized) return; + return _capture( + 'pageOpened', + properties: { + 'page': page.name, + if (path != null) 'path': path, + if (uiSource != null) 'uiSource': uiSource, + }, + ); + } + + static Future localeChanged(Locale locale) async { + if (!_initialized) return; + return _capture( + 'localeChanged', + properties: {'locale': locale.toLanguageTag()}, + ); + } + + static Future recipientAddCompleted( + RecipientType type, + RecipientStatus status, + Set methods, + ) async { + if (!_initialized) return; + return _capture( + 'recipientAddCompleted', + properties: { + 'methods': methods.map((m) => m.name).toList(), + 'type': type.name, + 'status': status.name, + }, + ); + } + + static Future paymentInitiated({PaymentType? method}) async { + if (!_initialized) return; + return _capture( + 'paymentInitiated', + properties: { + if (method != null) 'method': method.name, + }, + ); + } + + static Future _capture( + String eventName, { + Map? properties, + }) async { + if (!_initialized) return; + final filtered = {}; + if (properties != null) { + for (final entry in properties.entries) { + final value = entry.value; + if (value != null) filtered[entry.key] = value; + } + } + await Posthog().capture(eventName: eventName, properties: filtered.isEmpty ? null : filtered); + } +} diff --git a/frontend/pweb/lib/utils/logout.dart b/frontend/pweb/lib/utils/logout.dart index 97e030e..6881022 100644 --- a/frontend/pweb/lib/utils/logout.dart +++ b/frontend/pweb/lib/utils/logout.dart @@ -6,10 +6,12 @@ import 'package:pshared/provider/account.dart'; import 'package:pshared/provider/permissions.dart'; import 'package:pweb/app/router/pages.dart'; +import 'package:pweb/services/posthog.dart'; void logoutUtil(BuildContext context) { context.read().logout(); context.read().reset(); + PosthogService.reset(); navigateAndReplace(context, Pages.login); } diff --git a/frontend/pweb/lib/widgets/sidebar/side_menu.dart b/frontend/pweb/lib/widgets/sidebar/side_menu.dart index 5e9cc13..026483a 100644 --- a/frontend/pweb/lib/widgets/sidebar/side_menu.dart +++ b/frontend/pweb/lib/widgets/sidebar/side_menu.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -// import 'package:pweb/services/amplitude.dart'; +import 'package:pweb/services/posthog.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; @@ -49,7 +49,7 @@ class SideMenuColumn extends StatelessWidget { child: InkWell( onTap: () { onSelected(item); - // AmplitudeService.pageOpened(item, uiSource: 'sidebar'); + PosthogService.pageOpened(item, uiSource: 'sidebar'); }, borderRadius: BorderRadius.circular(12), hoverColor: theme.colorScheme.primaryContainer, @@ -76,4 +76,4 @@ class SideMenuColumn extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/frontend/pweb/macos/Flutter/GeneratedPluginRegistrant.swift b/frontend/pweb/macos/Flutter/GeneratedPluginRegistrant.swift index 79f5652..6f6fb74 100644 --- a/frontend/pweb/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/frontend/pweb/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,6 +9,7 @@ import amplitude_flutter import file_selector_macos import flutter_timezone import path_provider_foundation +import posthog_flutter import share_plus import shared_preferences_foundation import sqflite_darwin @@ -19,6 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterTimezonePlugin.register(with: registry.registrar(forPlugin: "FlutterTimezonePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + PosthogFlutterPlugin.register(with: registry.registrar(forPlugin: "PosthogFlutterPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/frontend/pweb/pubspec.yaml b/frontend/pweb/pubspec.yaml index aeb7e35..610e043 100644 --- a/frontend/pweb/pubspec.yaml +++ b/frontend/pweb/pubspec.yaml @@ -35,6 +35,7 @@ dependencies: sdk: flutter pshared: path: ../pshared + posthog_flutter: ^5.9.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.