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
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ android {
applicationId "com.webreinvent.vaahflutter"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion flutter.minSdkVersion
minSdkVersion 19
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand Down
6 changes: 6 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:host="YOUR_FIREBASE_APP_DYNAMIC_LINK_PREFIX.page.link" android:scheme="https"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
Expand Down
3 changes: 3 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,8 @@ end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
end
end
end
47 changes: 47 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,40 @@ PODS:
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- Firebase/CoreOnly (10.3.0):
- FirebaseCore (= 10.3.0)
- Firebase/DynamicLinks (10.3.0):
- Firebase/CoreOnly
- FirebaseDynamicLinks (~> 10.3.0)
- firebase_core (2.7.1):
- Firebase/CoreOnly (= 10.3.0)
- Flutter
- firebase_dynamic_links (5.0.16):
- Firebase/DynamicLinks (= 10.3.0)
- firebase_core
- Flutter
- FirebaseCore (10.3.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
- FirebaseCoreInternal (10.5.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseDynamicLinks (10.3.0):
- FirebaseCore (~> 10.0)
- Flutter (1.0.0)
- fluttertoast (0.0.2):
- Flutter
- Toast
- GoogleUtilities/Environment (7.11.0):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.11.0):
- GoogleUtilities/Environment
- "GoogleUtilities/NSData+zlib (7.11.0)"
- package_info_plus (0.4.5):
- Flutter
- path_provider_ios (0.0.1):
- Flutter
- PromisesObjC (2.2.0)
- SDWebImage (5.14.2):
- SDWebImage/Core (= 5.14.2)
- SDWebImage/Core (5.14.2)
Expand All @@ -54,6 +80,8 @@ PODS:

DEPENDENCIES:
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_dynamic_links (from `.symlinks/plugins/firebase_dynamic_links/ios`)
- Flutter (from `Flutter`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
Expand All @@ -64,6 +92,12 @@ SPEC REPOS:
trunk:
- DKImagePickerController
- DKPhotoGallery
- Firebase
- FirebaseCore
- FirebaseCoreInternal
- FirebaseDynamicLinks
- GoogleUtilities
- PromisesObjC
- SDWebImage
- Sentry
- SwiftyGif
Expand All @@ -72,6 +106,10 @@ SPEC REPOS:
EXTERNAL SOURCES:
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
firebase_core:
:path: ".symlinks/plugins/firebase_core/ios"
firebase_dynamic_links:
:path: ".symlinks/plugins/firebase_dynamic_links/ios"
Flutter:
:path: Flutter
fluttertoast:
Expand All @@ -87,9 +125,18 @@ SPEC CHECKSUMS:
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
Firebase: f92fc551ead69c94168d36c2b26188263860acd9
firebase_core: 1ae9f9aa76e6e1edc14fb181637ad466fd6c6fa4
firebase_dynamic_links: 42ab4dd387b07d5c7af2e9aa63a7b5fa3518dd8b
FirebaseCore: 988754646ab3bd4bdcb740f1bfe26b9f6c0d5f2a
FirebaseCoreInternal: e463f41bb935cd049505bf7e9a5bdd7dcea90df6
FirebaseDynamicLinks: 51c81d07bd63155bb56d76b0abdda79c8a3d8d02
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
GoogleUtilities: c2bdc4cf2ce786c4d2e6b3bcfd599a25ca78f06f
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
SDWebImage: b9a731e1d6307f44ca703b3976d18c24ca561e84
Sentry: 4c9babff9034785067c896fd580b1f7de44da020
sentry_flutter: b10ae7a5ddcbc7f04648eeb2672b5747230172f1
Expand Down
10 changes: 10 additions & 0 deletions ios/Runner/Runner.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:YOUR_FIREBASE_APP_DYNAMIC_LINK_PREFIX.page.link</string>
</array>
</dict>
</plist>
4 changes: 3 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ import './vaahextendflutter/base/base_controller.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
BaseController baseController = Get.put(BaseController());
await baseController.init(const AppConfig()); // Pass main app as argument in init method
await baseController.init(
app: const AppConfig(),
); // Pass main app as argument in init method
}
28 changes: 23 additions & 5 deletions lib/vaahextendflutter/base/base_controller.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import 'dart:async';

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:sentry_flutter/sentry_flutter.dart';

import '../../controllers/root_assets_controller.dart';
import '../app_theme.dart';
import '../env.dart';
import '../services/api.dart';
import '../services/dynamic_links.dart';

class BaseController extends GetxController {
Future<void> init(Widget app) async {
Future<void> init({
required Widget app,
FirebaseOptions? firebaseOptions,
}) async {
// Storage initialization to store some properties locally
await GetStorage.init();

// Environment initialization
EnvironmentConfig.setEnvConfig();
final EnvironmentConfig config = EnvironmentConfig.getEnvConfig();

// Initialization of Firebase and Services
if (firebaseOptions != null) {
await Firebase.initializeApp(
options: firebaseOptions,
);
DynamicLinks.init();
}

// Other Local Initializations (Depends on your app)
AppTheme.init();
Api.init();
Get.put(RootAssetsController());

final EnvironmentConfig config = EnvironmentConfig.getEnvConfig();

// Sentry Initialization (And/ Or) Running main app
if (null != config.sentryConfig && config.sentryConfig!.dsn.isNotEmpty) {
await SentryFlutter.init(
(options) => options
Expand All @@ -44,8 +60,10 @@ class BaseController extends GetxController {
child: child,
);
}
// Running main app
runApp(child);
} else {
// Running main app when sentry config is not there
runApp(app);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/vaahextendflutter/env.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final EnvironmentConfig defaultConfig = EnvironmentConfig(
enableCloudLogs: true,
enableApiLogInterceptor: true,
showDebugPanel: true,
debugPanelColor: AppTheme.colors['black']!.withOpacity(0.7),
debugPanelColor: AppTheme.colors['black']!.withOpacity(0.8),
);

// To add new configuration add new key, value pair in envConfigs
Expand Down
108 changes: 108 additions & 0 deletions lib/vaahextendflutter/services/dynamic_links.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'dart:async';
import 'dart:convert';

import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
import 'package:get/get.dart';

import './logging_library/logging_library.dart';

abstract class DynamicLinks {
static void init() async {
// handle initial dynamic link
final getInitialLink = await _firebaseDynamicLinks.getInitialLink();
if (getInitialLink != null) {
_handleLink(getInitialLink);
}

// listen/ subscribe to the links which comes later and handle them
_firebaseDynamicLinks.onLink
.listen(
_handleLink,
)
.onError(
(error, stackTrace) => Log.exception(error, stackTrace: stackTrace),
);
}

static final FirebaseDynamicLinks _firebaseDynamicLinks = FirebaseDynamicLinks.instance;
static final StreamController<DeepLink> _dynamicLinksStreamController =
StreamController<DeepLink>.broadcast();
static final Stream<DeepLink> dynamicLinksStream = _dynamicLinksStreamController.stream;

static Future<ShortDynamicLink?> createLink({
required String? path,
required dynamic data,
required dynamic auth,
}) async {
try {
final String parameters = jsonEncode({"path": path, "data": data, "auth": auth});
return await _firebaseDynamicLinks.buildShortLink(
DynamicLinkParameters(
link: Uri.parse("https://your.domain?payload=$parameters"),
uriPrefix: "https://YOUR_FIREBASE_APP_DYNAMIC_LINK_PREFIX.page.link",
androidParameters: const AndroidParameters(packageName: "your.package.name"),
iosParameters: const IOSParameters(bundleId: "your.bundle.identifier"),
),
shortLinkType: ShortDynamicLinkType.unguessable,
);
} catch (error, stackTrace) {
Log.exception(error, stackTrace: stackTrace, hint: "Error creating dynamic link!");
return null;
}
}

static Future<void> _handleLink(PendingDynamicLinkData linkData) async {
try {
final Uri decodedLink = Uri.parse(Uri.decodeFull(linkData.link.toString()));
final dynamic payload = _decodePayload(decodedLink);
_dynamicLinksStreamController.add(
DeepLink(
encoded: linkData.link.toString(),
decoded: "${linkData.link.host}${linkData.link.path}?payload=$payload",
),
);
Log.success({
"encoded": linkData.link.toString(),
"decoded": "${linkData.link.host}${linkData.link.path}?payload=$payload",
});
if (payload != null && payload['path'] != null) {
Get.offAllNamed(
payload['path'],
arguments: <String, dynamic>{
'data': payload['data'],
'auth': payload['auth'],
},
);
}
} catch (error, stackTrace) {
Log.exception(
error,
stackTrace: stackTrace,
hint: "Error handling dynamic link! ${linkData.asMap()}",
);
}
}

static dynamic _decodePayload(Uri link) {
try {
return jsonDecode(link.queryParameters['payload'].toString());
} catch (error, stackTrace) {
Log.exception(
error,
stackTrace: stackTrace,
hint: "Error decoding payload! $link",
);
return null;
}
}
}

class DeepLink {
final String encoded;
final String decoded;

const DeepLink({
required this.encoded,
required this.decoded,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class Log {
bool disableCloudLogging = false,
}) {
if (_config.enableLocalLogs && !disableLocalLogging) {
Console.danger(throwable.toString(), data);
Console.danger('$throwable\n$hint', data);
}
if (_config.enableCloudLogs && !disableCloudLogging) {
final hintWithData = {
Expand Down
5 changes: 3 additions & 2 deletions lib/vaahextendflutter/widgets/atoms/app_expansion_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,16 @@ class _AppExpansionPanelState extends State<AppExpansionPanel>

@immutable
class AppExpansionPanelIcon extends StatelessWidget {
const AppExpansionPanelIcon({Key? key}) : super(key: key);
final Color? color;
const AppExpansionPanelIcon({Key? key, this.color}) : super(key: key);

@override
Widget build(BuildContext context) {
return RotationTransition(
turns: context.findAncestorStateOfType<_AppExpansionPanelState>()!._iconTurns,
child: FaIcon(
FontAwesomeIcons.angleDown,
color: AppTheme.colors['primary'],
color: color ?? AppTheme.colors['primary'],
),
);
}
Expand Down
Loading