Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 92 additions & 2 deletions app/lib/core/app_shell.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,100 @@
import 'dart:async';
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:omi/mobile/mobile_app.dart';
import 'package:omi/desktop/desktop_app.dart';
import 'package:omi/backend/preferences.dart';
import 'package:omi/pages/apps/app_detail/app_detail.dart';
import 'package:omi/providers/app_provider.dart';
import 'package:omi/providers/auth_provider.dart';
import 'package:omi/providers/home_provider.dart';
import 'package:omi/providers/message_provider.dart';
import 'package:omi/providers/people_provider.dart';
import 'package:omi/providers/usage_provider.dart';
import 'package:omi/providers/user_provider.dart';
import 'package:omi/services/notifications.dart';
import 'package:omi/utils/alerts/app_snackbar.dart';
import 'package:omi/utils/platform/platform_manager.dart';

class AppShell extends StatelessWidget {
class AppShell extends StatefulWidget {
const AppShell({super.key});

@override
State<AppShell> createState() => _AppShellState();
}

class _AppShellState extends State<AppShell> {
late AppLinks _appLinks;
StreamSubscription<Uri>? _linkSubscription;

Future<void> initDeepLinks() async {
_appLinks = AppLinks();

// Handle links
_linkSubscription = _appLinks.uriLinkStream.distinct().listen((uri) {
debugPrint('onAppLink: $uri');
openAppLink(uri);
});
}

void openAppLink(Uri uri) async {
if (uri.pathSegments.first == 'apps') {
if (mounted) {
var app = await context.read<AppProvider>().getAppFromId(uri.pathSegments[1]);
if (app != null) {
PlatformManager.instance.mixpanel.track('App Opened From DeepLink', properties: {'appId': app.id});
if (mounted) {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => AppDetailPage(app: app)));
}
} else {
debugPrint('App not found: ${uri.pathSegments[1]}');
AppSnackbar.showSnackbarError('Oops! Looks like the app you are looking for is not available.');
}
}
} else {
debugPrint('Unknown link: $uri');
}
}

@override
void initState() {
initDeepLinks();

WidgetsBinding.instance.addPostFrameCallback((_) async {
if (context.read<AuthenticationProvider>().isSignedIn()) {
context.read<HomeProvider>().setupHasSpeakerProfile();
context.read<HomeProvider>().setupUserPrimaryLanguage();
context.read<UserProvider>().initialize();
context.read<PeopleProvider>().initialize();
try {
await PlatformManager.instance.intercom.loginIdentifiedUser(SharedPreferencesUtil().uid);
} catch (e) {
debugPrint('Failed to login to Intercom: $e');
}

context.read<MessageProvider>().setMessagesFromCache();
context.read<AppProvider>().setAppsFromCache();
context.read<MessageProvider>().refreshMessages();
context.read<UsageProvider>().fetchSubscription();

NotificationService.instance.saveNotificationToken();
} else {
if (!PlatformManager.instance.isAnalyticsSupported) {
await PlatformManager.instance.intercom.loginUnidentifiedUser();
}
}
PlatformManager.instance.intercom.setUserAttributes();
});
super.initState();
}

@override
void dispose() {
_linkSubscription?.cancel();
super.dispose();
}

@override
Widget build(BuildContext context) {
return LayoutBuilder(
Expand All @@ -13,7 +103,7 @@ class AppShell extends StatelessWidget {
if (constraints.maxWidth >= 1100) {
return const DesktopApp(); // Desktop app tree
} else {
return const MobileApp(); // Mobile app tree (existing)
return const MobileApp(); // Mobile app tree
}
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ class _DesktopOnboardingWrapperState extends State<DesktopOnboardingWrapper> wit
SharedPreferencesUtil().hasOmiDevice = true;
SharedPreferencesUtil().verifiedPersonaId = null;
MixpanelManager().onboardingStepCompleted('Auth');
if(context.mounted) {
context.read<HomeProvider>().setupHasSpeakerProfile();
}
IntercomManager.instance.loginIdentifiedUser(SharedPreferencesUtil().uid);
IntercomManager.instance.updateUser(
FirebaseAuth.instance.currentUser!.email,
Expand Down
99 changes: 0 additions & 99 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'dart:async';
import 'package:app_links/app_links.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
Expand All @@ -16,13 +15,8 @@ import 'package:omi/env/prod_env.dart';
import 'package:omi/firebase_options_dev.dart' as dev;
import 'package:omi/firebase_options_prod.dart' as prod;
import 'package:omi/flavors.dart';
import 'package:omi/pages/apps/app_detail/app_detail.dart';
import 'package:omi/pages/apps/providers/add_app_provider.dart';
import 'package:omi/pages/home/page.dart';
import 'package:omi/pages/conversation_detail/conversation_detail_provider.dart';
import 'package:omi/pages/onboarding/device_selection.dart';
import 'package:omi/pages/onboarding/wrapper.dart';
import 'package:omi/pages/persona/persona_profile.dart';
import 'package:omi/core/app_shell.dart';
import 'package:omi/pages/persona/persona_provider.dart';
import 'package:omi/providers/app_provider.dart';
Expand Down Expand Up @@ -325,100 +319,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
}
}

class DeciderWidget extends StatefulWidget {
const DeciderWidget({super.key});

@override
State<DeciderWidget> createState() => _DeciderWidgetState();
}

class _DeciderWidgetState extends State<DeciderWidget> {
late AppLinks _appLinks;
StreamSubscription<Uri>? _linkSubscription;

Future<void> initDeepLinks() async {
_appLinks = AppLinks();

// Handle links
_linkSubscription = _appLinks.uriLinkStream.distinct().listen((uri) {
debugPrint('onAppLink: $uri');
openAppLink(uri);
});
}

void openAppLink(Uri uri) async {
if (uri.pathSegments.first == 'apps') {
if (mounted) {
var app = await context.read<AppProvider>().getAppFromId(uri.pathSegments[1]);
if (app != null) {
PlatformManager.instance.mixpanel.track('App Opened From DeepLink', properties: {'appId': app.id});
if (mounted) {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => AppDetailPage(app: app)));
}
} else {
debugPrint('App not found: ${uri.pathSegments[1]}');
AppSnackbar.showSnackbarError('Oops! Looks like the app you are looking for is not available.');
}
}
} else {
debugPrint('Unknown link: $uri');
}
}

@override
void initState() {
initDeepLinks();

WidgetsBinding.instance.addPostFrameCallback((_) async {

if (context.read<AuthenticationProvider>().isSignedIn()) {
context.read<HomeProvider>().setupHasSpeakerProfile();
context.read<HomeProvider>().setupUserPrimaryLanguage();
context.read<UserProvider>().initialize();
context.read<PeopleProvider>().initialize();
try {
await PlatformManager.instance.intercom.loginIdentifiedUser(SharedPreferencesUtil().uid);
} catch (e) {
debugPrint('Failed to login to Intercom: $e');
}

context.read<MessageProvider>().setMessagesFromCache();
context.read<AppProvider>().setAppsFromCache();
context.read<MessageProvider>().refreshMessages();
context.read<UsageProvider>().fetchSubscription();

NotificationService.instance.saveNotificationToken();
} else {
if (!PlatformManager.instance.isAnalyticsSupported) {
await PlatformManager.instance.intercom.loginUnidentifiedUser();
}
}
PlatformManager.instance.intercom.setUserAttributes();
});
super.initState();
}

@override
Widget build(BuildContext context) {
return Consumer<AuthenticationProvider>(
builder: (context, authProvider, child) {
if (authProvider.isSignedIn()) {
if (SharedPreferencesUtil().onboardingCompleted) {
return const HomePageWrapper();
} else {
return const OnboardingWrapper();
}
} else if (SharedPreferencesUtil().hasOmiDevice == false &&
SharedPreferencesUtil().hasPersonaCreated &&
SharedPreferencesUtil().verifiedPersonaId != null) {
return const PersonaProfilePage();
} else {
return const DeviceSelectionPage();
}
},
);
}
}

class CustomErrorWidget extends StatelessWidget {
final String errorMessage;
Expand Down
4 changes: 2 additions & 2 deletions app/lib/pages/persona/persona_profile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:omi/backend/auth.dart';
import 'package:omi/backend/preferences.dart';
import 'package:omi/backend/schema/app.dart';
import 'package:omi/core/app_shell.dart';
import 'package:omi/gen/assets.gen.dart';
import 'package:omi/main.dart';
import 'package:omi/pages/onboarding/wrapper.dart';
import 'package:omi/pages/persona/persona_provider.dart';
import 'package:omi/providers/auth_provider.dart';
Expand Down Expand Up @@ -560,7 +560,7 @@ class _PersonaProfilePageState extends State<PersonaProfilePage> {
Provider.of<PersonaProvider>(context, listen: false).setRouting(PersonaProfileRouting.no_device);
await signOut();
Navigator.of(context).pop();
routeToPage(context, const DeciderWidget(), replace: true);
routeToPage(context, const AppShell(), replace: true);
},
child: const Text('Sign Out', style: TextStyle(color: Colors.redAccent)),
),
Expand Down
4 changes: 2 additions & 2 deletions app/lib/pages/settings/delete_account.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:omi/backend/http/api/users.dart';
import 'package:omi/backend/preferences.dart';
import 'package:omi/main.dart';
import 'package:omi/core/app_shell.dart';
import 'package:omi/utils/analytics/mixpanel.dart';
import 'package:omi/utils/other/temp.dart';
import 'package:omi/widgets/dialog.dart';
Expand Down Expand Up @@ -37,7 +37,7 @@ class _DeleteAccountState extends State<DeleteAccount> {
setState(() {
isDeleteing = false;
});
routeToPage(context, const DeciderWidget(), replace: true);
routeToPage(context, const AppShell(), replace: true);
}

@override
Expand Down
6 changes: 3 additions & 3 deletions app/lib/pages/settings/page.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:omi/backend/auth.dart';
import 'package:omi/backend/preferences.dart';
import 'package:omi/main.dart';
import 'package:omi/core/app_shell.dart';
import 'package:omi/pages/persona/persona_provider.dart';
import 'package:omi/pages/settings/about.dart';
import 'package:omi/pages/settings/data_privacy_page.dart';
Expand Down Expand Up @@ -166,7 +166,7 @@ class _SettingsPageState extends State<SettingsPage> {
Provider.of<PersonaProvider>(context, listen: false).setRouting(PersonaProfileRouting.no_device);
await signOut();
Navigator.of(context).pop();
routeToPage(context, const DeciderWidget(), replace: true);
routeToPage(context, const AppShell(), replace: true);
}, "Sign Out?", "Are you sure you want to sign out?");
},
);
Expand Down Expand Up @@ -219,7 +219,7 @@ class _SettingsPageState extends State<SettingsPage> {
Provider.of<PersonaProvider>(context, listen: false).setRouting(PersonaProfileRouting.no_device);
await signOut();
Navigator.of(context).pop();
routeToPage(context, const DeciderWidget(), replace: true);
routeToPage(context, const AppShell(), replace: true);
}, "Sign Out?", "Are you sure you want to sign out?");
},
);
Expand Down
10 changes: 5 additions & 5 deletions app/lib/pages/settings/settings_drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:omi/backend/auth.dart';
import 'package:omi/backend/preferences.dart';
import 'package:omi/main.dart';
import 'package:omi/core/app_shell.dart';
import 'package:omi/pages/persona/persona_provider.dart';
import 'package:omi/pages/settings/about.dart';
import 'package:omi/pages/settings/data_privacy_page.dart';
Expand Down Expand Up @@ -291,9 +291,9 @@ class _SettingsDrawerState extends State<SettingsDrawer> {
await SharedPreferencesUtil().clearUserPreferences();
personaProvider.setRouting(PersonaProfileRouting.no_device);
await signOut();
if (context.mounted) {
routeToPage(context, const DeciderWidget(), replace: true);
}
if (context.mounted){
routeToPage(context, const AppShell(), replace: true);
}
},
"Sign Out?",
"Are you sure you want to sign out?",
Expand Down Expand Up @@ -365,7 +365,7 @@ class _SettingsDrawerState extends State<SettingsDrawer> {
personaProvider.setRouting(PersonaProfileRouting.no_device);
await signOut();
if (context.mounted) {
routeToPage(context, const DeciderWidget(), replace: true);
routeToPage(context, const AppShell(), replace: true);
}
},
"Sign Out?",
Expand Down