Fix audiocomplete

This commit is contained in:
Michael Speed 2024-02-02 14:47:52 +01:00
parent fae795e902
commit 46e3faa5a7
10 changed files with 76 additions and 28 deletions

View File

@ -75,6 +75,7 @@ class StringConstants {
static const String search = 'Search';
static const String share = 'Share';
static const String id = 'id';
static const String env = 'env';
static const String email = 'email';
static const String appVersion = 'appVersion';
static const String deviceModel = 'deviceModel';

View File

@ -34,11 +34,13 @@ import 'constants/environments/environment_constants.dart';
import 'services/notifications/notifications_service.dart';
var audioStateNotifier = AudioStateNotifier();
var currentEnvironment =
kDebugMode ? EnvironmentConstants.stagingEnv : EnvironmentConstants.prodEnv;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: EnvironmentConstants.stagingEnv);
await dotenv.load(fileName: currentEnvironment);
MeditoAudioServiceCallbackApi.setup(AudioStateProvider(audioStateNotifier));
@ -69,7 +71,6 @@ Future<void> main() async {
),
),
);
}
// ignore: prefer-match-file-name

View File

@ -1,6 +1,8 @@
import 'package:Medito/constants/constants.dart';
import 'package:Medito/main.dart';
import 'package:Medito/models/models.dart';
import 'package:Medito/repositories/repositories.dart';
import 'package:flutter/foundation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../me/me_provider.dart';
@ -27,6 +29,7 @@ String _formatString(
MeModel? me,
DeviceAndAppInfoModel? deviceInfo,
) {
var env = StringConstants.env + ': ${currentEnvironment ?? ''}';
var id = StringConstants.id + ': ${me?.id ?? ''}';
var email = StringConstants.email + ': ${me?.email ?? ''}';
var appVersion =
@ -40,7 +43,7 @@ String _formatString(
'${StringConstants.buildNumber}: ${deviceInfo?.buildNumber ?? ''}';
var formattedString =
'$id\n$email\n$appVersion\n$deviceModel\n$deviceOs\n$devicePlatform\n$buildNumber';
'$env\n$id\n$email\n$appVersion\n$deviceModel\n$deviceOs\n$devicePlatform\n$buildNumber';
return formattedString;
}

View File

@ -1,15 +1,19 @@
import 'dart:async';
import 'dart:convert';
import 'package:Medito/models/models.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:workmanager/workmanager.dart';
import '../../constants/strings/shared_preference_constants.dart';
import '../../constants/types/type_constants.dart';
import '../../src/audio_pigeon.g.dart';
import '../../utils/utils.dart';
import '../../utils/workmanager.dart';
import '../../utils/workmanager_constants.dart';
import '../events/events_provider.dart';
import '../shared_preference/shared_preference_provider.dart';
import 'download/audio_downloader_provider.dart';
final _api = MeditoAudioServiceApi();
@ -103,11 +107,25 @@ class PlayerProvider extends StateNotifier<TrackModel?> {
inputData: {
TypeConstants.fileIdKey: fileId,
TypeConstants.trackIdKey: trackModelId,
WorkManagerConstants.userTokenKey: getUserToken(),
},
);
}
void _cancelBackgroundThreadForAudioCompleteEvent() async {
String? getUserToken() {
var user = ref.read(sharedPreferencesProvider).getString(
SharedPreferenceConstants.userToken,
);
var userModel =
user != null ? UserTokenModel.fromJson(json.decode(user)) : null;
if (userModel != null) {
return userModel.token;
}
return null;
}
void cancelBackgroundThreadForAudioCompleteEvent() async {
await Workmanager().cancelAll();
}
@ -131,7 +149,6 @@ class PlayerProvider extends StateNotifier<TrackModel?> {
}
void stop() {
_cancelBackgroundThreadForAudioCompleteEvent();
_api.stopAudio();
}

View File

@ -16,9 +16,10 @@ class EventsRepositoryImpl extends EventsRepository {
EventsRepositoryImpl({required this.client});
@override
Future<void> trackEvent(Map<String, dynamic> event) async {
Future<void> trackEvent(Map<String, dynamic> event, {String? userToken}) async {
await client.postRequest(
HTTPConstants.EVENTS,
userToken: userToken,
data: event,
);
}

View File

@ -5,8 +5,6 @@ import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import '../../constants/http/http_constants.dart';
// ignore: avoid_dynamic_calls
class DioApiService {
static final DioApiService _instance = DioApiService._internal();
@ -16,13 +14,24 @@ class DioApiService {
return _instance;
}
// Only pass the userToken if you know the headers have not been set in
// assignDioHeadersProvider (for example in workManager)
void _setToken(String? userToken) {
if (userToken != null && userToken.isNotEmpty) {
dio.options.headers[HttpHeaders.authorizationHeader] =
'Bearer $userToken';
}
}
// Private constructor
DioApiService._internal() {
dio = Dio();
dio.options = BaseOptions(
connectTimeout: Duration(milliseconds: 30000),
baseUrl: HTTPConstants.BASE_URL,
headers: {
);
dio.options.headers.addAll(
{
HttpHeaders.accessControlAllowOriginHeader: '*',
HttpHeaders.accessControlAllowHeadersHeader:
'Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale',
@ -94,6 +103,7 @@ class DioApiService {
// ignore: avoid-dynamic
Future<dynamic> postRequest(
String uri, {
String? userToken,
data,
Map<String, dynamic>? queryParameters,
Options? options,
@ -101,6 +111,7 @@ class DioApiService {
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
_setToken(userToken);
try {
var response = await dio.post(
uri,

View File

@ -1,9 +1,12 @@
import 'dart:async';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/utils/workmanager_constants.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:workmanager/workmanager.dart';
import '../constants/types/type_constants.dart';
import '../main.dart';
import '../models/events/audio_completed/audio_completed_model.dart';
import '../models/events/events_model.dart';
import '../repositories/events/events_repository.dart';
@ -13,7 +16,9 @@ const audioCompletedTaskKey = 'com.AVFoundation.medito.audioCompletedTask';
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
Workmanager().executeTask((task, inputData) async {
await dotenv.load(fileName: currentEnvironment);
try {
switch (task) {
case audioCompletedTaskKey:
@ -26,17 +31,25 @@ void callbackDispatcher() {
name: EventTypes.audioCompleted,
payload: audio.toJson(),
);
var eventsRpo = EventsRepositoryImpl(client: DioApiService());
if (inputData != null) eventsRpo.trackEvent(event.toJson());
var eventsRpo = EventsRepositoryImpl(
client: DioApiService(),
);
if (inputData != null) {
await eventsRpo.trackEvent(
event.toJson(),
userToken: inputData[WorkManagerConstants.userTokenKey],
);
}
break;
}
} catch (err) {
unawaited(Sentry.captureException(
err,
hint: Hint()..addAll(
{'task': task, 'inputData': inputData?.toString() ?? ''},
),
hint: Hint()
..addAll(
{'task': task, 'inputData': inputData?.toString() ?? ''},
),
stackTrace: err,
));
@ -45,4 +58,4 @@ void callbackDispatcher() {
return Future.value(true);
});
}
}

View File

@ -0,0 +1,4 @@
class WorkManagerConstants {
static const userTokenKey = 'userToken';
}

View File

@ -56,7 +56,7 @@ class _PlayerViewState extends ConsumerState<PlayerView> {
extendBodyBehindAppBar: true,
appBar: MeditoAppBarSmall(
hasCloseButton: true,
closePressed: () => _handleClose(),
closePressed: () => _handleClose,
isTransparent: true,
),
body: SafeArea(
@ -123,14 +123,19 @@ class _PlayerViewState extends ConsumerState<PlayerView> {
Future<bool> _handleClose() async {
_resetState();
ref
.read(playerProvider.notifier)
.cancelBackgroundThreadForAudioCompleteEvent();
context.pop();
return true;
}
void _resetState() {
ref.read(audioStateProvider.notifier).resetState();
ref.read(playerProvider.notifier).stop();
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.read(playerProvider.notifier).stop();
ref.read(audioStateProvider.notifier).resetState();
});
}
void _openEndScreen() {

View File

@ -1493,14 +1493,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vibration:
dependency: "direct main"
description:
name: vibration
sha256: "778ace40e84852e6cf6017cdbaf6790a837d73ff3dd50b27da9ac232a19de8fc"
url: "https://pub.dev"
source: hosted
version: "1.8.4"
vm_service:
dependency: transitive
description: