playback reporting

This commit is contained in:
Dr-Blank 2024-06-15 23:43:08 -04:00
parent fbd789f989
commit be7f5daa88
No known key found for this signature in database
GPG key ID: 7452CC63F210A266
14 changed files with 751 additions and 10 deletions

View file

@ -0,0 +1,259 @@
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'metadata_provider.g.dart';
@Riverpod(keepAlive: true)
Future<String> deviceName(DeviceNameRef ref) async {
final data = await _getDeviceData(DeviceInfoPlugin());
// try different keys to get the device name
return
// android
data['product'] ??
// ios
data['name'] ??
// linux
data['name'] ??
// windows
data['computerName'] ??
// macos
data['model'] ??
// web
data['browserName'] ??
'Unknown name';
}
@Riverpod(keepAlive: true)
Future<String> deviceModel(DeviceModelRef ref) async {
final data = await _getDeviceData(DeviceInfoPlugin());
// try different keys to get the device model
return
// android, eg: Google Pixel 4
data['model'] ??
// ios, eg: iPhone 12 Pro
data['name'] ??
// linux, eg: Linux Mint 20.1
data['name'] ??
// windows, eg: Surface Pro 7
data['productId'] ??
// macos, eg: MacBook Pro (13-inch, M1, 2020)
data['model'] ??
// web, eg: Chrome 87.0.4280.88
data['browserName'] ??
'Unknown model';
}
@Riverpod(keepAlive: true)
Future<String> deviceSdkVersion(DeviceSdkVersionRef ref) async {
final data = await _getDeviceData(DeviceInfoPlugin());
// try different keys to get the device sdk version
return
// android, eg: 30
data['version.sdkInt'] ??
// ios, eg: 14.4
data['systemVersion'] ??
// linux, eg: 5.4.0-66-generic
data['version'] ??
// windows, eg: 10.0.19042
data['displayVersion'] ??
// macos, eg: 11.2.1
data['osRelease'] ??
// web, eg: 87.0.4280.88
data['appVersion'] ??
'Unknown sdk version';
}
@Riverpod(keepAlive: true)
Future<String> deviceManufacturer(DeviceManufacturerRef ref) async {
final data = await _getDeviceData(DeviceInfoPlugin());
// try different keys to get the device manufacturer
return
// android, eg: Google
data['manufacturer'] ??
// ios, eg: Apple
data['manufacturer'] ??
// linux, eg: Linux
data['idLike'] ??
// windows, eg: Microsoft
data['productName'] ??
// macos, eg: Apple
data['manufacturer'] ??
// web, eg: Google Inc.
data['vendor'] ??
'Unknown manufacturer';
}
// copied from https://pub.dev/packages/device_info_plus/example
Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
return <String, dynamic>{
'version.securityPatch': build.version.securityPatch,
'version.sdkInt': build.version.sdkInt,
'version.release': build.version.release,
'version.previewSdkInt': build.version.previewSdkInt,
'version.incremental': build.version.incremental,
'version.codename': build.version.codename,
'version.baseOS': build.version.baseOS,
'board': build.board,
'bootloader': build.bootloader,
'brand': build.brand,
'device': build.device,
'display': build.display,
'fingerprint': build.fingerprint,
'hardware': build.hardware,
'host': build.host,
'id': build.id,
'manufacturer': build.manufacturer,
'model': build.model,
'product': build.product,
'supported32BitAbis': build.supported32BitAbis,
'supported64BitAbis': build.supported64BitAbis,
'supportedAbis': build.supportedAbis,
'tags': build.tags,
'type': build.type,
'isPhysicalDevice': build.isPhysicalDevice,
'systemFeatures': build.systemFeatures,
'serialNumber': build.serialNumber,
'isLowRamDevice': build.isLowRamDevice,
};
}
Map<String, dynamic> _readIosDeviceInfo(IosDeviceInfo data) {
return <String, dynamic>{
'name': data.name,
'systemName': data.systemName,
'systemVersion': data.systemVersion,
'model': data.model,
'localizedModel': data.localizedModel,
'identifierForVendor': data.identifierForVendor,
'isPhysicalDevice': data.isPhysicalDevice,
'utsname.sysname:': data.utsname.sysname,
'utsname.nodename:': data.utsname.nodename,
'utsname.release:': data.utsname.release,
'utsname.version:': data.utsname.version,
'utsname.machine:': data.utsname.machine,
};
}
Map<String, dynamic> _readLinuxDeviceInfo(LinuxDeviceInfo data) {
return <String, dynamic>{
'name': data.name,
'version': data.version,
'id': data.id,
'idLike': data.idLike,
'versionCodename': data.versionCodename,
'versionId': data.versionId,
'prettyName': data.prettyName,
'buildId': data.buildId,
'variant': data.variant,
'variantId': data.variantId,
'machineId': data.machineId,
};
}
Map<String, dynamic> _readWebBrowserInfo(WebBrowserInfo data) {
return <String, dynamic>{
'browserName': data.browserName.name,
'appCodeName': data.appCodeName,
'appName': data.appName,
'appVersion': data.appVersion,
'deviceMemory': data.deviceMemory,
'language': data.language,
'languages': data.languages,
'platform': data.platform,
'product': data.product,
'productSub': data.productSub,
'userAgent': data.userAgent,
'vendor': data.vendor,
'vendorSub': data.vendorSub,
'hardwareConcurrency': data.hardwareConcurrency,
'maxTouchPoints': data.maxTouchPoints,
};
}
Map<String, dynamic> _readMacOsDeviceInfo(MacOsDeviceInfo data) {
return <String, dynamic>{
'computerName': data.computerName,
'hostName': data.hostName,
'arch': data.arch,
'model': data.model,
'kernelVersion': data.kernelVersion,
'majorVersion': data.majorVersion,
'minorVersion': data.minorVersion,
'patchVersion': data.patchVersion,
'osRelease': data.osRelease,
'activeCPUs': data.activeCPUs,
'memorySize': data.memorySize,
'cpuFrequency': data.cpuFrequency,
'systemGUID': data.systemGUID,
};
}
Map<String, dynamic> _readWindowsDeviceInfo(WindowsDeviceInfo data) {
return <String, dynamic>{
'numberOfCores': data.numberOfCores,
'computerName': data.computerName,
'systemMemoryInMegabytes': data.systemMemoryInMegabytes,
'userName': data.userName,
'majorVersion': data.majorVersion,
'minorVersion': data.minorVersion,
'buildNumber': data.buildNumber,
'platformId': data.platformId,
'csdVersion': data.csdVersion,
'servicePackMajor': data.servicePackMajor,
'servicePackMinor': data.servicePackMinor,
'suitMask': data.suitMask,
'productType': data.productType,
'reserved': data.reserved,
'buildLab': data.buildLab,
'buildLabEx': data.buildLabEx,
'digitalProductId': data.digitalProductId,
'displayVersion': data.displayVersion,
'editionId': data.editionId,
'installDate': data.installDate,
'productId': data.productId,
'productName': data.productName,
'registeredOwner': data.registeredOwner,
'releaseId': data.releaseId,
'deviceId': data.deviceId,
};
}
Future<Map<String, dynamic>> _getDeviceData(
DeviceInfoPlugin deviceInfoPlugin,
) async {
Map<String, dynamic> deviceData;
try {
if (kIsWeb) {
deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo);
} else {
deviceData = switch (defaultTargetPlatform) {
TargetPlatform.android =>
_readAndroidBuildData(await deviceInfoPlugin.androidInfo),
TargetPlatform.iOS =>
_readIosDeviceInfo(await deviceInfoPlugin.iosInfo),
TargetPlatform.linux =>
_readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo),
TargetPlatform.windows =>
_readWindowsDeviceInfo(await deviceInfoPlugin.windowsInfo),
TargetPlatform.macOS =>
_readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo),
TargetPlatform.fuchsia => <String, dynamic>{
errorKey: 'Fuchsia platform isn\'t supported',
},
};
}
} on PlatformException {
deviceData = <String, dynamic>{
errorKey: 'Failed to get platform version.',
};
}
return deviceData;
}
const errorKey = 'Error:';

View file

@ -0,0 +1,69 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'metadata_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$deviceNameHash() => r'bc206a3a8c14f3da6e257e92e1ccdc79364f4e28';
/// See also [deviceName].
@ProviderFor(deviceName)
final deviceNameProvider = FutureProvider<String>.internal(
deviceName,
name: r'deviceNameProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$deviceNameHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef DeviceNameRef = FutureProviderRef<String>;
String _$deviceModelHash() => r'3d7e8ef4a37b90f98e38dc8d5f16ca30f71e15b2';
/// See also [deviceModel].
@ProviderFor(deviceModel)
final deviceModelProvider = FutureProvider<String>.internal(
deviceModel,
name: r'deviceModelProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$deviceModelHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef DeviceModelRef = FutureProviderRef<String>;
String _$deviceSdkVersionHash() => r'0553db1a6c90a4db2841761ac2765eb1ba86a714';
/// See also [deviceSdkVersion].
@ProviderFor(deviceSdkVersion)
final deviceSdkVersionProvider = FutureProvider<String>.internal(
deviceSdkVersion,
name: r'deviceSdkVersionProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$deviceSdkVersionHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef DeviceSdkVersionRef = FutureProviderRef<String>;
String _$deviceManufacturerHash() =>
r'f0a57e6a92b551fbe266d0a6a29d35dc497882a9';
/// See also [deviceManufacturer].
@ProviderFor(deviceManufacturer)
final deviceManufacturerProvider = FutureProvider<String>.internal(
deviceManufacturer,
name: r'deviceManufacturerProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$deviceManufacturerHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef DeviceManufacturerRef = FutureProviderRef<String>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View file

@ -31,6 +31,7 @@ class PlayerSettings with _$PlayerSettings {
@Default(1) double preferredDefaultSpeed,
@Default([0.75, 1, 1.25, 1.5, 1.75, 2]) List<double> speedOptions,
@Default(SleepTimerSettings()) SleepTimerSettings sleepTimerSettings,
@Default(Duration(seconds: 10)) Duration playbackReportInterval,
}) = _PlayerSettings;
factory PlayerSettings.fromJson(Map<String, dynamic> json) =>

View file

@ -231,6 +231,7 @@ mixin _$PlayerSettings {
List<double> get speedOptions => throw _privateConstructorUsedError;
SleepTimerSettings get sleepTimerSettings =>
throw _privateConstructorUsedError;
Duration get playbackReportInterval => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
@ -250,7 +251,8 @@ abstract class $PlayerSettingsCopyWith<$Res> {
double preferredDefaultVolume,
double preferredDefaultSpeed,
List<double> speedOptions,
SleepTimerSettings sleepTimerSettings});
SleepTimerSettings sleepTimerSettings,
Duration playbackReportInterval});
$MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings;
$ExpandedPlayerSettingsCopyWith<$Res> get expandedPlayerSettings;
@ -276,6 +278,7 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
Object? preferredDefaultSpeed = null,
Object? speedOptions = null,
Object? sleepTimerSettings = null,
Object? playbackReportInterval = null,
}) {
return _then(_value.copyWith(
miniPlayerSettings: null == miniPlayerSettings
@ -302,6 +305,10 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
? _value.sleepTimerSettings
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
as SleepTimerSettings,
playbackReportInterval: null == playbackReportInterval
? _value.playbackReportInterval
: playbackReportInterval // ignore: cast_nullable_to_non_nullable
as Duration,
) as $Val);
}
@ -347,7 +354,8 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res>
double preferredDefaultVolume,
double preferredDefaultSpeed,
List<double> speedOptions,
SleepTimerSettings sleepTimerSettings});
SleepTimerSettings sleepTimerSettings,
Duration playbackReportInterval});
@override
$MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings;
@ -374,6 +382,7 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
Object? preferredDefaultSpeed = null,
Object? speedOptions = null,
Object? sleepTimerSettings = null,
Object? playbackReportInterval = null,
}) {
return _then(_$PlayerSettingsImpl(
miniPlayerSettings: null == miniPlayerSettings
@ -400,6 +409,10 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
? _value.sleepTimerSettings
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
as SleepTimerSettings,
playbackReportInterval: null == playbackReportInterval
? _value.playbackReportInterval
: playbackReportInterval // ignore: cast_nullable_to_non_nullable
as Duration,
));
}
}
@ -413,7 +426,8 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
this.preferredDefaultVolume = 1,
this.preferredDefaultSpeed = 1,
final List<double> speedOptions = const [0.75, 1, 1.25, 1.5, 1.75, 2],
this.sleepTimerSettings = const SleepTimerSettings()})
this.sleepTimerSettings = const SleepTimerSettings(),
this.playbackReportInterval = const Duration(seconds: 10)})
: _speedOptions = speedOptions;
factory _$PlayerSettingsImpl.fromJson(Map<String, dynamic> json) =>
@ -443,10 +457,13 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
@override
@JsonKey()
final SleepTimerSettings sleepTimerSettings;
@override
@JsonKey()
final Duration playbackReportInterval;
@override
String toString() {
return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings)';
return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimerSettings: $sleepTimerSettings, playbackReportInterval: $playbackReportInterval)';
}
@override
@ -465,7 +482,9 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
const DeepCollectionEquality()
.equals(other._speedOptions, _speedOptions) &&
(identical(other.sleepTimerSettings, sleepTimerSettings) ||
other.sleepTimerSettings == sleepTimerSettings));
other.sleepTimerSettings == sleepTimerSettings) &&
(identical(other.playbackReportInterval, playbackReportInterval) ||
other.playbackReportInterval == playbackReportInterval));
}
@JsonKey(ignore: true)
@ -477,7 +496,8 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
preferredDefaultVolume,
preferredDefaultSpeed,
const DeepCollectionEquality().hash(_speedOptions),
sleepTimerSettings);
sleepTimerSettings,
playbackReportInterval);
@JsonKey(ignore: true)
@override
@ -501,7 +521,8 @@ abstract class _PlayerSettings implements PlayerSettings {
final double preferredDefaultVolume,
final double preferredDefaultSpeed,
final List<double> speedOptions,
final SleepTimerSettings sleepTimerSettings}) = _$PlayerSettingsImpl;
final SleepTimerSettings sleepTimerSettings,
final Duration playbackReportInterval}) = _$PlayerSettingsImpl;
factory _PlayerSettings.fromJson(Map<String, dynamic> json) =
_$PlayerSettingsImpl.fromJson;
@ -519,6 +540,8 @@ abstract class _PlayerSettings implements PlayerSettings {
@override
SleepTimerSettings get sleepTimerSettings;
@override
Duration get playbackReportInterval;
@override
@JsonKey(ignore: true)
_$$PlayerSettingsImplCopyWith<_$PlayerSettingsImpl> get copyWith =>
throw _privateConstructorUsedError;

View file

@ -46,6 +46,10 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map<String, dynamic> json) =>
? const SleepTimerSettings()
: SleepTimerSettings.fromJson(
json['sleepTimerSettings'] as Map<String, dynamic>),
playbackReportInterval: json['playbackReportInterval'] == null
? const Duration(seconds: 10)
: Duration(
microseconds: (json['playbackReportInterval'] as num).toInt()),
);
Map<String, dynamic> _$$PlayerSettingsImplToJson(
@ -57,6 +61,7 @@ Map<String, dynamic> _$$PlayerSettingsImplToJson(
'preferredDefaultSpeed': instance.preferredDefaultSpeed,
'speedOptions': instance.speedOptions,
'sleepTimerSettings': instance.sleepTimerSettings,
'playbackReportInterval': instance.playbackReportInterval.inMicroseconds,
};
_$ExpandedPlayerSettingsImpl _$$ExpandedPlayerSettingsImplFromJson(