Last active
June 28, 2023 00:49
-
-
Save lukepighetti/dfd9ebe73a3860c90d14d44020f3e58c to your computer and use it in GitHub Desktop.
All the basic data you need to roll your own analytics payloads
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:convert'; | |
import 'dart:io'; | |
import 'package:app/extensions.dart'; | |
import 'package:device_info_plus/device_info_plus.dart'; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter_timezone/flutter_timezone.dart'; | |
import 'package:get_it/get_it.dart'; | |
import 'package:package_info_plus/package_info_plus.dart'; | |
Future<void> setupDeviceService() async { | |
final x = DeviceService(); | |
await x.init(); | |
GetIt.instance.registerSingleton(x); | |
} | |
class DeviceService { | |
static final _dip = DeviceInfoPlugin(); | |
Future<void> init() async { | |
// Platform | |
platform = defaultTargetPlatform.name; | |
localeName = Platform.localeName; | |
timezone = await FlutterTimezone.getLocalTimezone(); | |
// Device info | |
if (Platform.isIOS) { | |
final d = await _dip.iosInfo; | |
platform = 'ios'; | |
deviceId = d.identifierForVendor; | |
isPhysicalDevice = d.isPhysicalDevice; | |
_deviceData = d.data.toSerializableMap(); | |
} else if (Platform.isAndroid) { | |
final d = await _dip.androidInfo; | |
deviceId = d.fingerprint; | |
isPhysicalDevice = d.isPhysicalDevice; | |
_deviceData = d.data.toSerializableMap(); | |
} else { | |
final d = await _dip.deviceInfo; | |
_deviceData = d.data.toSerializableMap(); | |
} | |
// Package info | |
final pi = await PackageInfo.fromPlatform(); | |
version = pi.version; | |
buildNumber = pi.buildNumber; | |
_packageData = { | |
'app_name': pi.appName, | |
'build_number': pi.buildNumber, | |
'build_signature': pi.buildSignature, | |
'installer_store': pi.installerStore, | |
'package_name': pi.packageName, | |
'version': pi.version, | |
}; | |
} | |
// Platform | |
String? platform; | |
String? localeName; | |
String? timezone; | |
// Device info | |
String? deviceId; | |
bool? isPhysicalDevice; | |
Map<String, dynamic> _deviceData = {}; | |
// Package info | |
String? version; | |
String? buildNumber; | |
Map<String, dynamic> _packageData = {}; | |
Map<String, dynamic>? get analyticsData => { | |
...{ | |
"platform": platform, | |
"localeName": localeName, | |
"timezone": timezone, | |
}.prefixedWith('platform.'), | |
..._deviceData.prefixedWith("device."), | |
..._packageData.prefixedWith("package."), | |
}; | |
} | |
extension on Map<String, dynamic> { | |
Map<String, dynamic> toSerializableMap() { | |
return jsonDecode( | |
jsonEncode(this, toEncodable: (foo) => foo.toString()), | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ApiResponse<void> userEvent(UserEvent payload) async { | |
try { | |
await _dio.post<void>( | |
"/events/user", | |
data: [ | |
{ | |
"type": payload.toJson()['type'], | |
"payload": payload.toJson(), | |
} | |
], | |
); | |
debugPrint('EVENT: ${payload.toString()}'); | |
return Result.success(null); | |
} on Object { | |
return Result.failure(ApiError.serverUnreachable); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension StringMapExtensions<V> on Map<String, V> { | |
Map<String, dynamic> prefixedWith(String prefix) { | |
return {for (final MapEntry(:key, :value) in entries) '$prefix$key': value}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Freezed(unionKey: "type", unionValueCase: FreezedUnionCase.snake) | |
class UserEvent with _$UserEvent { | |
const factory UserEvent.launchApp() = _UserEventLaunchApp; | |
const factory UserEvent.interest(String name, bool interested) = | |
_UserEventInterest; | |
const factory UserEvent.requestTopic({ | |
required String topic, | |
required String category, | |
required String reason, | |
}) = _UserEventRequestTopic; | |
const factory UserEvent.invalidTopic({ | |
required String topicId, | |
}) = _UserEventInvalidTopic; | |
const factory UserEvent.giveFeedback({ | |
required String feedback, | |
}) = _UserEventGiveFeedback; | |
const factory UserEvent.appLaunched({ | |
required String? platform, | |
required String? localeName, | |
required String? timezone, | |
required Environment? environment, | |
required bool? kDebugMode, | |
required String? deviceId, | |
required bool? isPhysicalDevice, | |
required String? buildNumber, | |
required String? version, | |
required Map<String, dynamic>? extra, | |
}) = _UserEventAppLaunched; | |
factory UserEvent.fromJson(Map<String, Object?> json) => | |
_$UserEventFromJson(json); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment