diff --git a/lib/routes/route_generator.dart b/lib/routes/route_generator.dart index 5d75759..1fb5083 100644 --- a/lib/routes/route_generator.dart +++ b/lib/routes/route_generator.dart @@ -56,7 +56,7 @@ import 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart' if (dart.library.html) 'package:didvan/views/podcasts/studio_details/studio_details.web.dart'; import 'package:didvan/views/splash/splash.dart'; import 'package:didvan/routes/routes.dart'; -import 'package:didvan/views/web/web_view.dart'; +import 'package:didvan/views/webview/web_view.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:home_widget/home_widget.dart'; diff --git a/lib/services/app_home_widget/home_widget_repository.dart b/lib/services/app_home_widget/home_widget_repository.dart index 82dc4cb..262837e 100644 --- a/lib/services/app_home_widget/home_widget_repository.dart +++ b/lib/services/app_home_widget/home_widget_repository.dart @@ -1,4 +1,5 @@ import 'package:didvan/models/notification_message.dart'; +import 'package:didvan/services/app_initalizer.dart'; import 'package:flutter/cupertino.dart'; import 'package:home_widget/home_widget.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; @@ -89,7 +90,8 @@ class HomeWidgetRepository { ); if (data.link!.startsWith('http')) { - launchUrlString( + AppInitializer.openWebLink( + navigatorKey.currentContext!, '${data.link}', mode: LaunchMode.inAppWebView, ); @@ -218,7 +220,8 @@ class HomeWidgetRepository { } } else { if (data.link!.startsWith('http')) { - launchUrlString( + AppInitializer.openWebLink( + navigatorKey.currentContext!, '${data.link}', mode: LaunchMode.inAppWebView, ); diff --git a/lib/services/app_initalizer.dart b/lib/services/app_initalizer.dart index c9aeb75..8152eb6 100644 --- a/lib/services/app_initalizer.dart +++ b/lib/services/app_initalizer.dart @@ -6,6 +6,7 @@ import 'package:didvan/models/requests/studio.dart'; import 'package:didvan/models/settings_data.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/services/media/media.dart'; +import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/storage/storage.dart'; import 'package:didvan/views/home/home_state.dart'; import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart'; @@ -13,6 +14,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher_string.dart'; class AppInitializer { static String? fcmToken; @@ -189,4 +191,16 @@ class AppInitializer { return data; } + + static openWebLink(BuildContext context, String src, + {final LaunchMode mode = LaunchMode.platformDefault}) { + if (kIsWeb) { + launchUrlString( + src, + mode: mode, + ); + } else { + Navigator.of(context).pushNamed(Routes.web, arguments: src); + } + } } diff --git a/lib/views/ai/ai.dart b/lib/views/ai/ai.dart index caa32a4..00ec18c 100644 --- a/lib/views/ai/ai.dart +++ b/lib/views/ai/ai.dart @@ -85,39 +85,46 @@ class _AiState extends State { .botsDialogSelect( context: context, state: state), child: Row( + crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - DidvanIcons.caret_down_solid, - color: Theme.of(context).colorScheme.title, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + DidvanIcons.caret_down_solid, + color: + Theme.of(context).colorScheme.title, + ), + const SizedBox( + width: 12, + ), + DidvanText(bot.name.toString(), + color: Theme.of(context) + .colorScheme + .title), + ], + ), + const SizedBox( + width: 12, + ), + ClipOval( + child: CachedNetworkImage( + width: 46, + height: 46, + imageUrl: bot.image.toString(), + ), ), - DidvanText(bot.name.toString(), - color: Theme.of(context).colorScheme.title), ], ), ), - const SizedBox( - height: 8, - ), - Container( - width: MediaQuery.sizeOf(context).height / 5, - height: MediaQuery.sizeOf(context).height / 5, - decoration: BoxDecoration( - borderRadius: DesignConfig.highBorderRadius, - color: Theme.of(context).colorScheme.focused), - padding: const EdgeInsets.all(12), - child: CachedNetworkImage( - imageUrl: bot.image.toString(), - ), - ), const SizedBox( height: 24, ), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 20.0), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0), child: Text( - "به هوشان, هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.\n دریافت پاسخ از: ${bot.name}", + "به هوشان, هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.", textAlign: TextAlign.center, ), ) diff --git a/lib/views/authentication/screens/username.dart b/lib/views/authentication/screens/username.dart index 7227e26..7e53a32 100644 --- a/lib/views/authentication/screens/username.dart +++ b/lib/views/authentication/screens/username.dart @@ -1,3 +1,4 @@ +import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/views/authentication/authentication_state.dart'; import 'package:didvan/views/authentication/widgets/authentication_layout.dart'; import 'package:didvan/views/widgets/didvan/button.dart'; @@ -79,7 +80,8 @@ class _UsernameInputState extends State { .bodySmall! .copyWith(color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer() - ..onTap = () => launchUrlString( + ..onTap = () => AppInitializer.openWebLink( + context, 'https://didvan.com/terms-of-use#conditions', ), ), @@ -91,7 +93,8 @@ class _UsernameInputState extends State { .bodySmall! .copyWith(color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer() - ..onTap = () => launchUrlString( + ..onTap = () => AppInitializer.openWebLink( + context, 'https://didvan.com/terms-of-use#privacy', ), ), diff --git a/lib/views/home/main/main_page.dart b/lib/views/home/main/main_page.dart index 834bf79..e289355 100644 --- a/lib/views/home/main/main_page.dart +++ b/lib/views/home/main/main_page.dart @@ -2,6 +2,7 @@ import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/models/home_page_content/home_page_list.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/views/home/main/main_page_state.dart'; import 'package:didvan/views/home/main/widgets/banner.dart'; import 'package:didvan/views/home/main/widgets/general_item.dart'; @@ -126,7 +127,8 @@ class _MainPageSection extends StatelessWidget { void _moreHandler(BuildContext context) { if (list.link.startsWith('http')) { - launchUrlString( + AppInitializer.openWebLink( + context, '${list.link}?accessToken=${RequestService.token}', mode: LaunchMode.inAppWebView, ); diff --git a/lib/views/home/main/main_page_state.dart b/lib/views/home/main/main_page_state.dart index 71d45fb..3582d34 100644 --- a/lib/views/home/main/main_page_state.dart +++ b/lib/views/home/main/main_page_state.dart @@ -6,6 +6,7 @@ import 'package:didvan/models/requests/news.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/providers/core.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; import 'package:flutter/material.dart'; @@ -99,7 +100,8 @@ class MainPageState extends CoreProvier { return; } if (link.startsWith('http')) { - launchUrlString( + AppInitializer.openWebLink( + navigatorKey.currentContext!, '$link?accessToken=${RequestService.token}', mode: LaunchMode.inAppWebView, ); diff --git a/lib/views/home/search/widgets/search_result_item.dart b/lib/views/home/search/widgets/search_result_item.dart index d187b9a..0a5739f 100644 --- a/lib/views/home/search/widgets/search_result_item.dart +++ b/lib/views/home/search/widgets/search_result_item.dart @@ -5,6 +5,7 @@ import 'package:didvan/models/requests/news.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/models/requests/studio.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/media/media.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart'; @@ -90,7 +91,8 @@ class SearchResultItem extends StatelessWidget { return; } if (_targetPageRouteName == null && item.link != null) { - launchUrlString( + AppInitializer.openWebLink( + context, '${item.link!}?accessToken=${RequestService.token}', mode: LaunchMode.inAppWebView, ); diff --git a/lib/views/home/widgets/categories.dart b/lib/views/home/widgets/categories.dart index c350827..26d1474 100644 --- a/lib/views/home/widgets/categories.dart +++ b/lib/views/home/widgets/categories.dart @@ -1,5 +1,6 @@ import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/theme_data.dart'; +import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/views/home/home_state.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; @@ -13,7 +14,8 @@ class MainCategories extends StatelessWidget { void _onTap(String link, BuildContext context) { if (link.startsWith('http')) { - launchUrlString( + AppInitializer.openWebLink( + context, '$link?accessToken=${RequestService.token}', mode: LaunchMode.inAppWebView, ); diff --git a/lib/views/profile/profile.dart b/lib/views/profile/profile.dart index 78596a6..6fc097c 100644 --- a/lib/views/profile/profile.dart +++ b/lib/views/profile/profile.dart @@ -7,6 +7,7 @@ import 'package:didvan/models/view/app_bar_data.dart'; import 'package:didvan/providers/theme.dart'; import 'package:didvan/providers/user.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/storage/storage.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/views/profile/general_settings/settings_state.dart'; @@ -221,8 +222,8 @@ class _ProfilePageState extends State { MenuOption( icon: DidvanIcons.info_circle_regular, title: 'معرفی دیدوان', - onTap: () => - launchUrlString('https://didvan.com/#info'), + onTap: () => AppInitializer.openWebLink( + context, 'https://didvan.com/#info'), ), const DidvanDivider(), MenuOption( @@ -338,7 +339,8 @@ class _ProfilePageState extends State { MenuOption( icon: DidvanIcons.alert_regular, title: 'حریم خصوصی', - onTap: () => launchUrlString( + onTap: () => AppInitializer.openWebLink( + context, 'https://didvan.com/terms-of-use#privacy', ), ), diff --git a/lib/views/web/web_view.dart b/lib/views/web/web_view.dart deleted file mode 100644 index d994d0e..0000000 --- a/lib/views/web/web_view.dart +++ /dev/null @@ -1,91 +0,0 @@ -// ignore_for_file: library_private_types_in_public_api, deprecated_member_use - -import 'package:didvan/constants/assets.dart'; -import 'package:didvan/views/widgets/didvan/text.dart'; -import 'package:flutter/material.dart'; -// import 'package:webview_flutter/webview_flutter.dart'; - -class WebView extends StatefulWidget { - final String src; - const WebView({Key? key, required this.src}) : super(key: key); - - @override - _WebViewState createState() => _WebViewState(); -} - -class _WebViewState extends State { - // late WebViewController controller; - bool loading = true; - int progress = 0; - - // @override - // void initState() { - // controller = WebViewController() - // ..setJavaScriptMode(JavaScriptMode.unrestricted) - // ..setNavigationDelegate( - // NavigationDelegate( - // onProgress: (int progress) { - // // Update loading bar. - // setState(() { - // this.progress = progress; - // }); - // }, - // onPageStarted: (String url) {}, - // onPageFinished: (String url) async { - // await Future.delayed(const Duration(seconds: 2)); - // setState(() { - // if (progress == 100) loading = false; - // }); - // }, - // onHttpError: (HttpResponseError error) {}, - // onWebResourceError: (WebResourceError error) { - // // navigatorKey.currentState!.pop(); - // }, - // onNavigationRequest: (NavigationRequest request) { - // // if (request.url.startsWith('https://www.youtube.com/')) { - // // return NavigationDecision.prevent; - // // } - // return NavigationDecision.navigate; - // }, - // ), - // ) - // ..loadRequest(Uri.parse(widget.src)); - // super.initState(); - // } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - // if (await controller.canGoBack()) { - // await controller.goBack(); - // return false; - // } else { - return true; - // } - }, - child: Scaffold( - appBar: AppBar( - title: const Padding( - padding: EdgeInsets.only(top: 12.0), - child: DidvanText( - 'بازگشت به دیدوان', - fontSize: 18, - ), - ), - toolbarHeight: 32, - ), - body: - // loading - // ? - Center( - child: Image.asset( - Assets.loadingAnimation, - width: 60, - height: 60, - ), - ) - // : WebViewWidget(controller: controller), - )); - } -} diff --git a/lib/views/webview/web_view.dart b/lib/views/webview/web_view.dart new file mode 100644 index 0000000..3a5ca60 --- /dev/null +++ b/lib/views/webview/web_view.dart @@ -0,0 +1,85 @@ +// ignore_for_file: library_private_types_in_public_api, deprecated_member_use + +import 'package:didvan/constants/assets.dart'; +import 'package:didvan/views/widgets/didvan/text.dart'; +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +class WebView extends StatefulWidget { + final String src; + const WebView({Key? key, required this.src}) : super(key: key); + + @override + _WebViewState createState() => _WebViewState(); +} + +class _WebViewState extends State { + late WebViewController controller; + bool loading = true; + int progress = 0; + + @override + void initState() { + controller = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setBackgroundColor(Theme.of(context).colorScheme.background) + ..setNavigationDelegate( + NavigationDelegate( + onProgress: (int progress) { + // Update loading bar. + setState(() { + this.progress = progress; + }); + }, + onPageStarted: (String url) {}, + onPageFinished: (String url) async { + await Future.delayed(const Duration(seconds: 2)); + setState(() { + if (progress == 100) loading = false; + }); + }, + onHttpError: (HttpResponseError error) {}, + onWebResourceError: (WebResourceError error) { + // navigatorKey.currentState!.pop(); + }, + onNavigationRequest: (NavigationRequest request) { + // if (request.url.startsWith('https://www.youtube.com/')) { + // return NavigationDecision.prevent; + // } + return NavigationDecision.navigate; + }, + ), + ) + ..loadRequest(Uri.parse(widget.src)); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + if (await controller.canGoBack()) { + await controller.goBack(); + return false; + } else { + return true; + } + }, + child: Scaffold( + appBar: AppBar( + title: const DidvanText( + 'بازگشت به دیدوان', + ), + ), + body: loading + ? Center( + child: Image.asset( + Assets.loadingAnimation, + width: 60, + height: 60, + ), + ) + : WebViewWidget(controller: controller), + )); + } +} diff --git a/lib/views/widgets/didvan/page_view.dart b/lib/views/widgets/didvan/page_view.dart index 6ea82f5..b3bcb25 100644 --- a/lib/views/widgets/didvan/page_view.dart +++ b/lib/views/widgets/didvan/page_view.dart @@ -9,6 +9,7 @@ import 'package:didvan/models/requests/news.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/models/studio_details_data.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/utils/date_time.dart'; import 'package:didvan/views/direct/widgets/audio_widget.dart'; @@ -310,7 +311,8 @@ class _DidvanPageViewState extends State { ), ); } else { - launchUrlString(href, mode: LaunchMode.inAppWebView); + AppInitializer.openWebLink(content, href, + mode: LaunchMode.inAppWebView); } }, style: { diff --git a/lib/views/widgets/overview/multitype.dart b/lib/views/widgets/overview/multitype.dart index fe96514..f156ffb 100644 --- a/lib/views/widgets/overview/multitype.dart +++ b/lib/views/widgets/overview/multitype.dart @@ -107,7 +107,8 @@ class MultitypeOverview extends StatelessWidget { return; } if (_targetPageRouteName == null && item.link != null) { - launchUrlString( + AppInitializer.openWebLink( + context, '${item.link!}?accessToken=${RequestService.token}', mode: LaunchMode.inAppWebView, ); diff --git a/pubspec.lock b/pubspec.lock index 13ac533..d578c26 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1314,6 +1314,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522" + url: "https://pub.dev" + source: hosted + version: "4.8.0" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "0d21cfc3bfdd2e30ab2ebeced66512b91134b39e72e97b43db2d47dda1c4e53a" + url: "https://pub.dev" + source: hosted + version: "3.16.3" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d + url: "https://pub.dev" + source: hosted + version: "2.10.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: "9c62cc46fa4f2d41e10ab81014c1de470a6c6f26051a2de32111b2ee55287feb" + url: "https://pub.dev" + source: hosted + version: "3.14.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1337d75..238d458 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,7 +62,7 @@ dependencies: image_cropper: ^1.5.0 firebase_core: ^3.1.0 firebase_messaging: ^15.0.1 - # webview_flutter: ^4.8.0 + webview_flutter: ^4.8.0 expandable_bottom_sheet: ^1.1.1+1 permission_handler: ^11.0.0 # better_player: