From b4375ace1ad259c3b2242668f283329dc06cb427 Mon Sep 17 00:00:00 2001 From: Julius Caesar Date: Wed, 25 Mar 2026 05:38:28 -0700 Subject: [PATCH] file listener config added --- android/app/src/main/AndroidManifest.xml | 27 ++++-- ios/Runner/Info.plist | 77 ++++++++++------- lib/app/app.dart | 83 ++++++++++--------- lib/main.dart | 4 +- lib/modules/core/file_listener.dart | 56 +++++++++++++ lib/shared/layout/navbar/defyx_navbar.dart | 2 +- .../navbar/widgets/introduction_dialog.dart | 2 +- .../widgets/offline_flowline_widget.dart | 5 +- .../navbar/widgets/quick_menu_dialog.dart | 2 +- .../navbar/widgets/social_icon_button.dart | 1 - pubspec.lock | 36 ++++---- pubspec.yaml | 4 +- 12 files changed, 200 insertions(+), 99 deletions(-) create mode 100644 lib/modules/core/file_listener.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d557330..b054314 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -17,7 +17,7 @@ android:name="android.hardware.touchscreen" android:required="false" /> - + @@ -38,7 +38,7 @@ android:name="com.dexterous.flutterlocalnotifications.ForegroundService" android:exported="false" android:stopWithTask="false" - android:foregroundServiceType="systemExempted"/> + android:foregroundServiceType="systemExempted" /> + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> + + + + + - - - + + + + @@ -86,4 +95,4 @@ - + \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 6f41758..11c2b9a 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -3,7 +3,7 @@ CADisableMinimumFrameDurationOnPhone - + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName @@ -27,17 +27,19 @@ GADApplicationIdentifier ca-app-pub-6029472941300558~5225768298 LSRequiresIPhoneOS - + NSDocumentsFolderUsageDescription WARP needs access to store its configuration files NSVPNConfigurationUsageDescription Defyx needs access to VPN configurations to secure your connection. NSUserTrackingUsageDescription - We need permission to show you personalized ads. This helps support our free VPN service. Declining means you'll see generic ads instead. + We need permission to show you personalized ads. This helps support our free VPN + service. Declining means you'll see generic ads instead. NSPhotoLibraryUsageDescription - Defyx needs access to your photo library to let you select and share images, such as profile pictures or VPN connection QR codes. + Defyx needs access to your photo library to let you select and share images, such as + profile pictures or VPN connection QR codes. UIApplicationSupportsIndirectInputEvents - + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -64,36 +66,53 @@ NSAppTransportSecurity NSAllowsArbitraryLoads - + UIStatusBarHidden - - LSSupportsOpeningDocumentsInPlace - - UIFileSharingEnabled - - UISupportsDocumentBrowser - - UTImportedTypeDeclarations - - - UTTypeConformsTo - - public.data - public.content - - UTTypeDescription - DefyX Configuration File - UTTypeIdentifier - de.unboundtech.defyxvpn.dfx - UTTypeTagSpecification + + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + + UISupportsDocumentBrowser + + UTImportedTypeDeclarations + + + UTTypeConformsTo + + public.data + public.content + + UTTypeDescription + DefyX Configuration File + UTTypeIdentifier + de.unboundtech.defyxvpn.dfx + UTTypeTagSpecification + + public.filename-extension + + dfx + + + + + CFBundleDocumentTypes + - public.filename-extension + CFBundleTypeName + DFX File + LSHandlerRank + Alternate + CFBundleTypeExtensions dfx + LSItemContentTypes + + public.data + - - + \ No newline at end of file diff --git a/lib/app/app.dart b/lib/app/app.dart index c7f940a..c3951d4 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -4,6 +4,7 @@ import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:defyx_vpn/app/advertise_director.dart'; import 'package:defyx_vpn/app/router/app_router.dart'; import 'package:defyx_vpn/core/theme/app_theme.dart'; +import 'package:defyx_vpn/modules/core/file_listener.dart'; import 'package:defyx_vpn/modules/core/vpn.dart'; import 'package:defyx_vpn/modules/core/desktop_platform_handler.dart'; import 'package:defyx_vpn/modules/main/presentation/widgets/ump_service.dart'; @@ -35,6 +36,7 @@ class App extends ConsumerWidget { } Future _initializeApp(WidgetRef ref) async { + FileListener().init(ProviderScope.containerOf(ref.context)); await VPN(ProviderScope.containerOf(ref.context)).getVPNStatus(); await AlertService().init(); await AnimationService().init(); @@ -57,20 +59,22 @@ class App extends ConsumerWidget { if (Platform.isAndroid || Platform.isIOS) { // Request App Tracking Transparency (iOS only) if (Platform.isIOS) { - final status = await AppTrackingTransparency.trackingAuthorizationStatus; + final status = + await AppTrackingTransparency.trackingAuthorizationStatus; if (status == TrackingStatus.notDetermined) { // Small delay to ensure UI is ready await Future.delayed(const Duration(milliseconds: 500)); - final result = await AppTrackingTransparency.requestTrackingAuthorization(); + final result = + await AppTrackingTransparency.requestTrackingAuthorization(); debugPrint('📱 ATT Authorization: $result'); } else { debugPrint('📱 ATT Status: $status'); } } - + // Get UMP service with cache integration final umpService = ref.read(umpServiceProvider); - + // Request UMP consent (checks cache first) await umpService.requestConsent( onDone: () async { @@ -91,41 +95,42 @@ class App extends ConsumerWidget { final designSize = _getDesignSize(context); return ToastificationWrapper( - config: ToastificationConfig( - maxToastLimit: 1, - blockBackgroundInteraction: false, - applyMediaQueryViewInsets: true, - ), - child: ScreenUtilInit( - designSize: designSize, - minTextAdapt: true, - splitScreenMode: true, - builder: (_, __) { - return MaterialApp.router( - title: 'Defyx', - theme: AppTheme.lightTheme, - darkTheme: AppTheme.darkTheme, - themeMode: ThemeMode.light, - routerConfig: router, - builder: _appBuilder, - debugShowCheckedModeBanner: false, - // Force English locale (comment out to enable device language detection) - locale: const Locale('en'), - localizationsDelegates: const [ - AppLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: const [ - Locale('en'), - Locale('fa'), - Locale('zh'), - Locale('ru'), - ], - ); - }, - )); + config: ToastificationConfig( + maxToastLimit: 1, + blockBackgroundInteraction: false, + applyMediaQueryViewInsets: true, + ), + child: ScreenUtilInit( + designSize: designSize, + minTextAdapt: true, + splitScreenMode: true, + builder: (_, __) { + return MaterialApp.router( + title: 'Defyx', + theme: AppTheme.lightTheme, + darkTheme: AppTheme.darkTheme, + themeMode: ThemeMode.light, + routerConfig: router, + builder: _appBuilder, + debugShowCheckedModeBanner: false, + // Force English locale (comment out to enable device language detection) + locale: const Locale('en'), + localizationsDelegates: const [ + AppLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: const [ + Locale('en'), + Locale('fa'), + Locale('zh'), + Locale('ru'), + ], + ); + }, + ), + ); } Size _getDesignSize(BuildContext context) { diff --git a/lib/main.dart b/lib/main.dart index 11cda03..6d5bd26 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,7 +11,7 @@ import 'app/app.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await dotenv.load(); - + // Initialize cache directory for VPN core try { final String vpnCacheDir = await VpnBridge().getSharedDirectory(); @@ -20,7 +20,7 @@ void main() async { } catch (e) { debugPrint('Failed to set cache directory: $e'); } - + // Initialize Firebase only on supported platforms (not Windows) if (!Platform.isWindows && !Platform.isLinux) { await Firebase.initializeApp( diff --git a/lib/modules/core/file_listener.dart b/lib/modules/core/file_listener.dart new file mode 100644 index 0000000..9aa76e8 --- /dev/null +++ b/lib/modules/core/file_listener.dart @@ -0,0 +1,56 @@ +import 'dart:io'; +import 'package:defyx_vpn/core/data/local/remote/api/flowline_service.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:receive_sharing_intent/receive_sharing_intent.dart'; + +class FileListener { + ProviderContainer? _container; + + void _startListening(void Function(String dfxPath) onDfxFile) { + ReceiveSharingIntent.instance.getMediaStream().listen( + (List files) async { + if (files.isEmpty) return; + final file = files.first; + if (file.path.endsWith('.dfx')) { + final content = await _readFileAsString(file.path); + onDfxFile(content); + } + }, + onError: (err) { + debugPrint('Error receiving shared media: $err'); + }, + ); + + ReceiveSharingIntent.instance + .getInitialMedia() + .then((List files) async { + if (files.isEmpty) return; + final file = files.first; + if (file.path.endsWith('.dfx')) { + final content = await _readFileAsString(file.path); + onDfxFile(content); + } + }) + .catchError((err) { + debugPrint('Error getting initial shared media: $err'); + }); + } + + Future _readFileAsString(String path) async { + final file = File(path); + return await file.readAsString(); + } + + Future _handleFile(String content) async { + _container ??= ProviderContainer(); + await _container + ?.read(flowlineServiceProvider) + .saveFlowline(offlineMode: true, flowLine: content); + } + + void init(ProviderContainer container) { + _container = container; + _startListening(_handleFile); + } +} diff --git a/lib/shared/layout/navbar/defyx_navbar.dart b/lib/shared/layout/navbar/defyx_navbar.dart index 2dc4334..afa76fc 100644 --- a/lib/shared/layout/navbar/defyx_navbar.dart +++ b/lib/shared/layout/navbar/defyx_navbar.dart @@ -116,7 +116,7 @@ class DefyxNavBar extends ConsumerWidget { } void _showShareDialog(BuildContext context, WidgetRef ref) { - final l10n = AppLocalizations.of(context)!; + final l10n = AppLocalizations.of(context); ref.read(currentScreenProvider.notifier).state = AppScreen.share; showGeneralDialog( context: context, diff --git a/lib/shared/layout/navbar/widgets/introduction_dialog.dart b/lib/shared/layout/navbar/widgets/introduction_dialog.dart index b86bc1b..6552454 100644 --- a/lib/shared/layout/navbar/widgets/introduction_dialog.dart +++ b/lib/shared/layout/navbar/widgets/introduction_dialog.dart @@ -9,7 +9,7 @@ class IntroductionDialog extends StatelessWidget { @override Widget build(BuildContext context) { - final l10n = AppLocalizations.of(context)!; + final l10n = AppLocalizations.of(context); return Dialog( insetPadding: EdgeInsets.symmetric(horizontal: 24.w), diff --git a/lib/shared/layout/navbar/widgets/offline_flowline_widget.dart b/lib/shared/layout/navbar/widgets/offline_flowline_widget.dart index beb70e5..4f2c323 100644 --- a/lib/shared/layout/navbar/widgets/offline_flowline_widget.dart +++ b/lib/shared/layout/navbar/widgets/offline_flowline_widget.dart @@ -53,7 +53,10 @@ class _OfflineFlowlineWidgetState extends ConsumerState { backgroundColor: const Color(0xFFF2F2F2), padding: EdgeInsets.all(10.h), ), - child: Text(AppLocalizations.of(context).offlineFlowlineUndo), + child: Text( + AppLocalizations.of(context).offlineFlowlineUndo, + style: TextStyle(fontSize: 13.sp, fontWeight: FontWeight.w500), + ), ), ], ), diff --git a/lib/shared/layout/navbar/widgets/quick_menu_dialog.dart b/lib/shared/layout/navbar/widgets/quick_menu_dialog.dart index 4a57ac7..41fe957 100644 --- a/lib/shared/layout/navbar/widgets/quick_menu_dialog.dart +++ b/lib/shared/layout/navbar/widgets/quick_menu_dialog.dart @@ -34,7 +34,7 @@ class _QuickMenuDialogState extends State { @override Widget build(BuildContext context) { - final l10n = AppLocalizations.of(context)!; + final l10n = AppLocalizations.of(context); return SafeArea( child: Padding( diff --git a/lib/shared/layout/navbar/widgets/social_icon_button.dart b/lib/shared/layout/navbar/widgets/social_icon_button.dart index f7fff29..fff7c80 100644 --- a/lib/shared/layout/navbar/widgets/social_icon_button.dart +++ b/lib/shared/layout/navbar/widgets/social_icon_button.dart @@ -1,4 +1,3 @@ -import 'package:defyx_vpn/shared/layout/navbar/widgets/custom_webview_screen.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; diff --git a/pubspec.lock b/pubspec.lock index 7b15131..6095f93 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -221,10 +221,10 @@ packages: dependency: transitive description: name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.0" checked_yaml: dependency: transitive description: @@ -849,18 +849,18 @@ packages: dependency: transitive description: name: matcher - sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.18" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.13.0" + version: "0.11.1" meta: dependency: transitive description: @@ -1069,6 +1069,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.0" + receive_sharing_intent: + dependency: "direct main" + description: + name: receive_sharing_intent + sha256: ec76056e4d258ad708e76d85591d933678625318e411564dcb9059048ca3a593 + url: "https://pub.dev" + source: hosted + version: "1.8.1" retrofit: dependency: "direct main" description: @@ -1310,10 +1318,10 @@ packages: dependency: transitive description: name: test_api - sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.9" + version: "0.7.7" timing: dependency: transitive description: @@ -1531,13 +1539,13 @@ packages: source: hosted version: "4.13.0" webview_flutter_android: - dependency: transitive + dependency: "direct main" description: name: webview_flutter_android - sha256: "3fcca88ee2ae568807ebd42deed235bb8dd8e62b3e4d5caff67daa6bce062cca" + sha256: "2a03df01df2fd30b075d1e7f24c28aee593f2e5d5ac4c3c4283c5eda63717b24" url: "https://pub.dev" source: hosted - version: "4.10.9" + version: "4.10.13" webview_flutter_platform_interface: dependency: transitive description: @@ -1547,13 +1555,13 @@ packages: source: hosted version: "2.14.0" webview_flutter_wkwebview: - dependency: transitive + dependency: "direct main" description: name: webview_flutter_wkwebview - sha256: a57b76a081bed3bf3a71a486bdf83642b00f1a7342043d50367cea68f338b1af + sha256: "0d85e8bc5db9a7c49f6ff57cbeafc6cd8216ad9c9ebc70b2c4579d955698933a" url: "https://pub.dev" source: hosted - version: "3.23.4" + version: "3.24.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ed420fa..0ab97a8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -53,7 +53,9 @@ dependencies: msix: ^3.16.12 flutter_native_splash: ^2.4.7 file_picker: ^10.3.10 - + webview_flutter_android: ^4.10.13 + receive_sharing_intent: ^1.8.1 + webview_flutter_wkwebview: ^3.24.1 dev_dependencies: flutter_test: sdk: flutter