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
185 changes: 90 additions & 95 deletions app/lib/pages/apps/app_home_web_page.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:omi/utils/browser.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:omi/backend/schema/app.dart';
import 'package:omi/backend/preferences.dart';

Expand All @@ -19,7 +16,6 @@ class AppHomeWebPage extends StatefulWidget {
}

class _AppHomeWebPageState extends State<AppHomeWebPage> with SingleTickerProviderStateMixin {
late final WebViewController _controller;
late final AnimationController _animationController;
late final Animation<Offset> _slideAnimation;
bool _isLoading = true;
Expand All @@ -39,113 +35,112 @@ class _AppHomeWebPageState extends State<AppHomeWebPage> with SingleTickerProvid
curve: Curves.easeOut,
));
_animationController.forward();
_controller = WebViewController()
..setUserAgent(topUserAgents[Random().nextInt(topUserAgents.length)])
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (String url) {
setState(() {
_isLoading = false;
});
},
onWebResourceError: (WebResourceError error) {
setState(() {
_isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Failed to load page: ${error.description}',
style: const TextStyle(color: Colors.white),
),
backgroundColor: Colors.red,
duration: const Duration(seconds: 3),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).size.height - 100,
left: 20,
right: 20,
),
),
);
},
),
)
..loadRequest(Uri.parse(
'${widget.app.externalIntegration?.appHomeUrl ?? ''}?uid=${SharedPreferencesUtil().uid}',
));

// Launch the custom tab after animation completes
var url = '${widget.app.externalIntegration?.appHomeUrl ?? ''}?uid=${SharedPreferencesUtil().uid}';
_animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_openCustomTab(url);
}
});
}

void _openCustomTab(String url) async {
setState(() {
_isLoading = false;
});

try {
await launchCustomTab(context, url);
// Close this page after the custom tab is closed
if (mounted) {
_animationController.reverse().then((_) {
Navigator.of(context).pop();
});
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Failed to load page: $e',
style: const TextStyle(color: Colors.white),
),
backgroundColor: Colors.red,
duration: const Duration(seconds: 3),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).size.height - 100,
left: 20,
right: 20,
),
),
);
}
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: SlideTransition(
position: _slideAnimation,
child: SafeArea(
child: Stack(
children: [
// Main content with top padding and rounded corners
Padding(
padding: const EdgeInsets.only(top: 16, bottom: 48),
child: ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
position: _slideAnimation,
child: SafeArea(
child: Stack(
children: [
// Loading indicator
if (_isLoading)
Container(
color: Colors.black,
child: const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
child: WebViewWidget(controller: _controller),
),
),
if (_isLoading)
Container(
color: Colors.black,
child: const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
// Bottom bar
Positioned(
left: 0,
right: 0,
bottom: 0,
child: GestureDetector(
onTap: () {
_animationController.reverse().then((_) {
Navigator.of(context).pop();
});
},
child: Container(
height: 48,
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.7),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: GestureDetector(
onTap: () {
_animationController.reverse().then((_) {
Navigator.of(context).pop();
});
},
child: Container(
height: 48,
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.7),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
const Icon(
Icons.keyboard_double_arrow_down,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
const Icon(
Icons.keyboard_double_arrow_down,
color: Colors.white,
size: 24,
),
Text(
"${widget.app.name}'s App Details",
style: const TextStyle(
color: Colors.white,
size: 24,
fontSize: 12,
),
Text(
"${widget.app.name}'s App Details",
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
],
),
),
],
),
),
),
],
),
)),
),
],
),
),
),
);
}

Expand Down
12 changes: 4 additions & 8 deletions app/lib/pages/settings/about.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:omi/pages/settings/webview.dart';
import 'package:omi/utils/analytics/intercom.dart';
import 'package:omi/utils/analytics/mixpanel.dart';
import 'package:omi/utils/browser.dart';
import 'package:omi/utils/other/temp.dart';
import 'package:url_launcher/url_launcher.dart';

Expand Down Expand Up @@ -31,10 +31,7 @@ class _AboutOmiPageState extends State<AboutOmiPage> {
trailing: const Icon(Icons.privacy_tip_outlined, size: 20),
onTap: () {
MixpanelManager().pageOpened('About Privacy Policy');
routeToPage(
context,
const PageWebView(url: 'https://www.omi.me/pages/privacy', title: 'Privacy Policy'),
);
launchCustomTab(context, 'https://www.omi.me/pages/privacy');
},
),
ListTile(
Expand All @@ -44,8 +41,7 @@ class _AboutOmiPageState extends State<AboutOmiPage> {
trailing: const Icon(Icons.language_outlined, size: 20),
onTap: () {
MixpanelManager().pageOpened('About Visit Website');
// routeToPage(context, const PageWebView(url: 'https://www.omi.me/', title: 'omi'));
launchUrl(Uri.parse('https://www.omi.me/'));
launchCustomTab(context, 'https://www.omi.me/');
},
),
ListTile(
Expand All @@ -64,7 +60,7 @@ class _AboutOmiPageState extends State<AboutOmiPage> {
trailing: const Icon(Icons.discord, color: Colors.purple, size: 20),
onTap: () {
MixpanelManager().pageOpened('About Join Discord');
launchUrl(Uri.parse('https://discord.gg/omi'));
launchCustomTab(context, 'https://discord.gg/omi');
},
),
],
Expand Down
62 changes: 40 additions & 22 deletions app/lib/utils/browser.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
// ref: https://github.com/microlinkhq/top-user-agents/blob/master/src/mobile.json
final topUserAgents = [
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/27.0 Chrome/125.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.58 Mobile Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/134.0.6998.99 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 13; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1"
];
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';

Future<void> launchCustomTab(BuildContext context, String url, {CustomTabsSession? session}) async {
final theme = Theme.of(context);
final mediaQuery = MediaQuery.of(context);
await launchUrl(
Uri.parse(url),
customTabsOptions: CustomTabsOptions.partial(
configuration: PartialCustomTabsConfiguration(
initialHeight: mediaQuery.size.height,
),
colorSchemes: CustomTabsColorSchemes.defaults(
colorScheme: theme.brightness.toColorScheme(),
toolbarColor: theme.colorScheme.primary,
),
showTitle: false,
shareState: CustomTabsShareState.off,
browser: session != null ? CustomTabsBrowserConfiguration.session(session) : null,
closeButton: CustomTabsCloseButton(icon: CustomTabsCloseButtonIcons.back),
),
safariVCOptions: SafariViewControllerOptions.pageSheet(
configuration: const SheetPresentationControllerConfiguration(
detents: {
SheetPresentationControllerDetent.large,
SheetPresentationControllerDetent.medium,
},
prefersScrollingExpandsWhenScrolledToEdge: true,
prefersGrabberVisible: true,
prefersEdgeAttachedInCompactHeight: true,
preferredCornerRadius: 48.0,
),
preferredBarTintColor: theme.colorScheme.primary,
preferredControlTintColor: theme.colorScheme.onPrimary,
entersReaderIfAvailable: true,
dismissButtonStyle: SafariViewControllerDismissButtonStyle.close,
),
);
}
5 changes: 3 additions & 2 deletions app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ dependencies:
permission_handler: ^11.3.1
share_plus: ^9.0.0
shared_preferences: ^2.2.3
url_launcher: ^6.3.0
wav: ^1.3.0
path: ^1.9.0
uuid: ^4.4.0
Expand Down Expand Up @@ -83,7 +82,8 @@ dependencies:
cached_network_image: ^3.3.1
map_launcher: ^3.3.1
internet_connection_checker_plus: ^2.5.0
geolocator:
geolocator: 12.0.0
geolocator_android: 4.6.1
version: ^3.0.2
webview_flutter: ^4.8.0
flutter_sound: ^9.10.0
Expand All @@ -100,6 +100,7 @@ dependencies:
flutter_svg: ^2.0.16
file_picker: 8.0.7
photo_view: ^0.15.0
flutter_custom_tabs: ^2.2.1

dependency_overrides:
http: ^1.2.1
Expand Down
Binary file modified docs/docs/images/checks-passed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/assembly/images/latest_assembly/9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/backend.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/dkv2_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/dkv2_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/dkv2_3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/dkv2_4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/embeddings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/memorystore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/docs/images/docs/developer/images/postprocessing.png
Binary file modified docs/docs/images/docs/get_started/images/omibanner.png
Binary file modified docs/docs/images/docs/info/images/disclaimer.png
Binary file modified docs/docs/images/hero-dark.png
Binary file modified docs/docs/images/hero-light.png
Loading