Fixed warnings

This commit is contained in:
Michael Speed 2023-03-22 19:31:21 +01:00
parent 482b73f374
commit bead831986
35 changed files with 649 additions and 458 deletions

View File

@ -11,4 +11,19 @@ dart_code_metrics:
metrics-exclude:
- test/**
rules:
- avoid-dynamic
- avoid-dynamic
- avoid-passing-async-when-sync-expected
- avoid-redundant-async
- avoid-unnecessary-type-assertions
- avoid-unnecessary-type-casts
- avoid-unrelated-type-assertions
- avoid-unused-parameters
- avoid-nested-conditional-expressions
- newline-before-return
- no-boolean-literal-compare
- no-empty-block
- prefer-trailing-comma
- prefer-conditional-expressions
- no-equal-then-else
- prefer-moving-to-variable
- prefer-match-file-name

View File

@ -85,7 +85,7 @@ class _Download {
}
}
// ignore: unnecessary_cast
downloadAmountListener.value = progress as double;
downloadAmountListener.value = progress as double; // it is necessary
}).onDone(() async {
try {
await file.writeAsBytes(_bytes);
@ -103,6 +103,7 @@ class _Download {
),
);
}
return;
});
}
@ -115,11 +116,8 @@ class _Download {
.then((value) => _throwResponse = value);
_total = _throwResponse?.contentLength ?? 0;
}
if (_received != null && _total != null) {
return _received! / _total!;
} else {
return 0;
}
return (_received != null && _total != null) ? (_received! / _total!) : 0;
}
}
@ -148,20 +146,23 @@ class DownloadSingleton {
double getProgress(AudioFile file) {
if (_download == null) return -1;
if (isDownloadingMe(file)) return _download?.getProgress() ?? 0.0;
return -1;
}
bool start(BuildContext context, AudioFile file, MediaItem mediaItem) {
bool start(AudioFile file, MediaItem mediaItem) {
if (_download == null) return false;
if (_download?.isDownloadingMe(file) ?? false) return true;
if (isDownloadingSomething()) return false;
if (_download?.isThisFile(file) ?? false) {
_download?.startDownloading(file, mediaItem);
return true;
}
_download = _Download(file);
_download?.startDownloading(file, mediaItem);
return true;
}

View File

@ -1,19 +1,20 @@
import 'package:audio_service/audio_service.dart';
class MediaLibrary {
static MediaItem getMediaLibrary(
{String? description,
String? title,
String? illustrationUrl,
String? secondaryColor,
String? primaryColor,
int? durationAsMilliseconds,
String? fileId,
String? attributions,
String? voice,
String? length,
bool? hasBgSound,
int? sessionId}) {
static MediaItem getMediaLibrary({
String? description,
String? title,
String? illustrationUrl,
String? secondaryColor,
String? primaryColor,
int? durationAsMilliseconds,
String? fileId,
String? attributions,
String? voice,
String? length,
bool? hasBgSound,
int? sessionId,
}) {
return MediaItem(
id: fileId ?? '',
extras: {
@ -25,10 +26,12 @@ class MediaLibrary {
ATTR: attributions,
LENGTH: length,
DURATION: durationAsMilliseconds,
HAS_BG_SOUND : hasBgSound,
HAS_BG_SOUND: hasBgSound,
},
artist: voice,
album: '', //empty to remove it from the notification
displayDescription: description,
album: '',
//empty to remove it from the notification
title: title ?? '',
artUri: Uri.parse(illustrationUrl ?? ''),
);
@ -45,4 +48,4 @@ const String PRIMARY_COLOUR = 'primaryColor';
const String ID = 'id';
const String SESSION_ID = 'sessionId';
const String SESSION_TITLE = 'sessionTitle';
const String LOCATION = 'location';
const String LOCATION = 'location';

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/utils/utils.dart';
import 'package:audio_service/audio_service.dart';
import 'package:audio_session/audio_session.dart';
@ -11,7 +10,7 @@ import 'package:just_audio/just_audio.dart';
import '../network/auth.dart';
import '../network/cache.dart';
import '../utils/bgvolume_utils.dart';
import 'media_lib.dart';
import 'media_library.dart';
import 'player_utils.dart';
//This is the duration of bgSound fade towards the end.
@ -170,7 +169,7 @@ class MeditoAudioHandler extends BaseAudioHandler
unawaited(_bgPlayer.setVolume(_bgVolume));
break;
case PLAY_BG_SOUND:
await _playBgSound(extras);
_playBgSound(extras);
break;
case INIT_BG_SOUND:
_bgVolume = extras?[SET_BG_SOUND_VOL] ?? DEFAULT_VOLUME;
@ -186,7 +185,7 @@ class MeditoAudioHandler extends BaseAudioHandler
return super.customAction(name, extras);
}
Future<void> _playBgSound(Map<String, dynamic>? extras) async {
void _playBgSound(Map<String, dynamic>? extras) {
var bgSound = extras?[PLAY_BG_SOUND];
if (bgSound != null) {
unawaited(_bgPlayer.setFilePath(extras?[PLAY_BG_SOUND]));
@ -212,13 +211,16 @@ class MeditoAudioHandler extends BaseAudioHandler
print(_bgPlayer.volume - (_bgVolume / FADE_DURATION));
if (_bgPlayer.volume > 0) {
unawaited(
_bgPlayer.setVolume(_bgPlayer.volume - (_bgVolume / FADE_DURATION)));
_bgPlayer.setVolume(_bgPlayer.volume - (_bgVolume / FADE_DURATION)),
);
}
}
void skipForward30Secs() {
var seekDuration = min(_duration?.inMilliseconds ?? 0,
_player.position.inMilliseconds + Duration(seconds: 30).inMilliseconds);
var seekDuration = min(
_duration?.inMilliseconds ?? 0,
_player.position.inMilliseconds + Duration(seconds: 30).inMilliseconds,
);
_player.seek(Duration(milliseconds: seekDuration));
}

View File

@ -40,6 +40,7 @@ Future<bool?> checkBgSoundExists(String name) async {
var filePath = (await getFilePath(name));
var file = File(filePath);
var exists = await file.exists();
return exists;
}

View File

@ -12,8 +12,8 @@ Affero GNU General Public License for more details.
You should have received a copy of the Affero GNU General Public License
along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'package:flutter_web_plugins/url_strategy.dart';
import 'dart:async';
import 'package:Medito/audioplayer/medito_audio_handler.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/routes/routes.dart';
@ -22,10 +22,12 @@ import 'package:audio_service/audio_service.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'audioplayer/audio_inherited_widget.dart';
import 'network/auth.dart';
@ -106,14 +108,15 @@ class _ParentWidgetState extends State<ParentWidget>
return MaterialApp.router(
routerConfig: router,
theme: ThemeData(
splashColor: ColorConstants.moonlight,
canvasColor: ColorConstants.greyIsTheNewBlack,
pageTransitionsTheme: PageTransitionsTheme(builders: {
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
TargetPlatform.android: SlideTransitionBuilder(),
}),
colorScheme: ColorScheme.dark(secondary: ColorConstants.walterWhite),
textTheme: meditoTextTheme(context)),
splashColor: ColorConstants.moonlight,
canvasColor: ColorConstants.greyIsTheNewBlack,
pageTransitionsTheme: PageTransitionsTheme(builders: {
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
TargetPlatform.android: SlideTransitionBuilder(),
}),
colorScheme: ColorScheme.dark(secondary: ColorConstants.walterWhite),
textTheme: meditoTextTheme(context),
),
title: ParentWidget._title,
);
}

View File

@ -2,11 +2,10 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:Medito/audioplayer/media_lib.dart';
import 'package:Medito/audioplayer/media_library.dart';
import 'package:Medito/audioplayer/player_utils.dart';
import 'package:Medito/network/session_options/session_opts.dart';
import 'package:audio_service/audio_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:package_info/package_info.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -15,16 +14,19 @@ class DownloadsBloc {
static Future<bool> seenTip() async {
var prefs = await SharedPreferences.getInstance();
return prefs.getBool('seenDownloadsToolTip') ?? false;
}
static Future<bool> setSeenTip() async {
var prefs = await SharedPreferences.getInstance();
return prefs.setBool('seenDownloadsToolTip', true);
}
static Future<void> saveFileToDownloadedFilesList(
MediaItem _mediaItem) async {
MediaItem _mediaItem,
) async {
var prefs = await SharedPreferences.getInstance();
var list = prefs.getStringList(savedFilesKey) ?? [];
@ -42,7 +44,7 @@ class DownloadsBloc {
'artist': _mediaItem.artist,
'duration': _mediaItem.duration?.inMilliseconds,
'artUri': _mediaItem.artUri.toString(),
'extras': _mediaItem.extras
'extras': _mediaItem.extras,
});
}
@ -66,12 +68,13 @@ class DownloadsBloc {
static MediaItem _getMediaItemFromMap(json) {
return MediaItem(
id: json['id'],
title: json['title'],
artist: json['artist'],
duration: Duration(milliseconds: json['duration'] ?? 0),
artUri: Uri.parse(json['artUri']),
extras: json['extras']);
id: json['id'],
title: json['title'],
artist: json['artist'],
duration: Duration(milliseconds: json['duration'] ?? 0),
artUri: Uri.parse(json['artUri']),
extras: json['extras'],
);
}
static Future<bool> isAudioFileDownloaded(AudioFile? file) async {
@ -87,7 +90,8 @@ class DownloadsBloc {
}
static Future<void> removeSessionFromDownloads(
BuildContext context, MediaItem mediaFile) async {
MediaItem mediaFile,
) async {
// Delete the download file from disk for this session
var filePath = (await getFilePath(mediaFile.id));
var file = File(filePath);
@ -99,7 +103,8 @@ class DownloadsBloc {
// Remove the session from all downloads list
var prefs = await SharedPreferences.getInstance();
var list = prefs.getStringList(savedFilesKey) ?? [];
list.removeWhere((element) => _getMediaItemFromMap(jsonDecode(element)).id == mediaFile.id);
list.removeWhere((element) =>
_getMediaItemFromMap(jsonDecode(element)).id == mediaFile.id);
await prefs.setStringList(savedFilesKey, list);
}
@ -107,8 +112,9 @@ class DownloadsBloc {
/// Saves a given `List` of `MediaItem` elements (downloaded sessions)
static Future<void> saveDownloads(List<MediaItem> mediaList) async {
var prefs = await SharedPreferences.getInstance();
var list =
mediaList.map((MediaItem mediaItem) => _jsonEncodeMediaItem(mediaItem)).toList();
var list = mediaList
.map((MediaItem mediaItem) => _jsonEncodeMediaItem(mediaItem))
.toList();
await prefs.setStringList(savedFilesKey, list);
}
}

View File

@ -6,6 +6,7 @@ import 'package:Medito/utils/utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'folder_provider.dart';
class NewFolderScreen extends ConsumerWidget {
@ -34,21 +35,26 @@ class NewFolderScreen extends ConsumerWidget {
},
child: Scaffold(
body: CollapsibleHeaderComponent(
bgImage: AssetConstants.dalle,
title: folder?.data?.title ?? '',
description: folder?.data?.description,
children: [
for (int i = 0; i < (folder?.data?.items?.length ?? 0); i++)
GestureDetector(
onTap: () => _onListItemTap(folder?.data?.items?[i].item?.id,
folder?.data?.items?[i].item?.type, ref.context),
child: _buildListTile(
context,
folder?.data?.items?[i].item?.title,
folder?.data?.items?[i].item?.subtitle,
true),
)
]),
bgImage: AssetConstants.dalle,
title: folder?.data?.title ?? '',
description: folder?.data?.description,
children: [
for (int i = 0; i < (folder?.data?.items?.length ?? 0); i++)
GestureDetector(
onTap: () => _onListItemTap(
folder?.data?.items?[i].item?.id,
folder?.data?.items?[i].item?.type,
ref.context,
),
child: _buildListTile(
context,
folder?.data?.items?[i].item?.title,
folder?.data?.items?[i].item?.subtitle,
true,
),
),
],
),
),
);
}

View File

@ -13,7 +13,7 @@ Affero GNU General Public License for more details.
You should have received a copy of the Affero GNU General Public License
along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'package:Medito/audioplayer/media_lib.dart';
import 'package:Medito/audioplayer/media_library.dart';
import 'package:Medito/network/auth.dart';
import 'package:Medito/network/http_get.dart';
import 'package:Medito/network/session_options/background_sounds.dart';

View File

@ -16,12 +16,12 @@ along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'dart:async';
import 'package:Medito/audioplayer/download_class.dart';
import 'package:Medito/audioplayer/media_lib.dart';
import 'package:Medito/audioplayer/media_library.dart';
import 'package:Medito/network/api_response.dart';
import 'package:Medito/network/session_options/session_options_repo.dart';
import 'package:Medito/network/session_options/session_opts.dart';
import 'package:Medito/tracking/tracking.dart';
import 'package:Medito/utils/duration_ext.dart';
import 'package:Medito/utils/duration_extensions.dart';
import 'package:audio_service/audio_service.dart';
import 'package:pedantic/pedantic.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -131,7 +131,7 @@ class SessionOptionsBloc {
{
Tracking.SESSION_ID: mediaItem.extras?[SESSION_ID].toString() ?? '',
Tracking.SESSION_DURATION: mediaItem.extras?[LENGTH].toString() ?? '',
Tracking.SESSION_GUIDE: mediaItem.artist ?? ''
Tracking.SESSION_GUIDE: mediaItem.artist ?? '',
},
),
);
@ -148,7 +148,7 @@ class SessionOptionsBloc {
secondaryColor: _options?.colorSecondary,
primaryColor: _options?.colorPrimary,
durationAsMilliseconds:
clockTimeToDuration(file?.length).inMilliseconds,
clockTimeToDuration(file?.length).inMilliseconds,
fileId: file?.id,
sessionId: _options?.id,
attributions: _options?.attribution);
@ -169,10 +169,10 @@ class SessionOptionsBloc {
// Add file data against each voice
voiceSet.toList().forEach((voice) {
var listForThisVoice =
items.where((element) => element?.voice == voice).toList();
items.where((element) => element?.voice == voice).toList();
var voiceItem =
VoiceItem(headerValue: voice, listForVoice: listForThisVoice);
VoiceItem(headerValue: voice, listForVoice: listForThisVoice);
voiceList.add(voiceItem);
});

View File

@ -19,6 +19,7 @@ class TextResponse {
if (data != null) {
data['data'] = this.data?.toJson();
}
return data;
}
}
@ -44,6 +45,7 @@ class Data {
data['title'] = title;
data['subtitle'] = subtitle;
data['body'] = body;
return data;
}
}

View File

@ -14,6 +14,7 @@ class UserResponse {
if (this.data != null) {
data['data'] = this.data?.toJson();
}
return data;
}
}
@ -30,6 +31,7 @@ class Data {
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['id'] = id;
return data;
}
}

View File

@ -17,6 +17,7 @@ Future<bool> firstOpenOperations() async {
var prefs = await SharedPreferences.getInstance();
var opened = _beginClearStorage(prefs);
await _logAccount(prefs);
return opened;
}
@ -46,6 +47,7 @@ bool _beginClearStorage(SharedPreferences prefs) {
if (!opened) {
unawaited(_clearStorage(prefs));
}
return opened;
}
@ -105,6 +107,7 @@ class UserRepo {
Future<String?> get generatedToken async {
var prefs = await SharedPreferences.getInstance();
return prefs.getString(TOKEN);
}
@ -141,7 +144,7 @@ Future<Map<String, String>> getDeviceDetails() async {
DEVICE_MODEL: deviceModel,
DEVICE_OS: deviceOS,
DEVICE_PLATFORM: devicePlatform,
DEVICE_LANGUAGE: deviceLanguage
DEVICE_LANGUAGE: deviceLanguage,
};
}

View File

@ -3,6 +3,7 @@ import 'package:Medito/models/models.dart';
import 'package:Medito/services/network/dio_api_services.dart';
import 'package:Medito/services/network/dio_client_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'background_sounds_repository.g.dart';
abstract class BackgroundSoundsRepository {
@ -19,6 +20,7 @@ class BackgroundSoundsRepositoryImpl extends BackgroundSoundsRepository {
try {
var res = await client.getRequest(HTTPConstants.BACKGROUND_SOUNDS);
var tempResponse = res as List;
return tempResponse
.map((x) => BackgroundSoundsModel.fromJson(x))
.toList();
@ -30,6 +32,7 @@ class BackgroundSoundsRepositoryImpl extends BackgroundSoundsRepository {
@riverpod
BackgroundSoundsRepositoryImpl backgroundSoundsRepository(
BackgroundSoundsRepositoryRef ref) {
BackgroundSoundsRepositoryRef ref,
) {
return BackgroundSoundsRepositoryImpl(client: ref.watch(dioClientProvider));
}

View File

@ -6,21 +6,30 @@ import 'package:Medito/services/network/dio_client_provider.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'downloader_repository.g.dart';
abstract class DownloaderRepository {
Future<dynamic> downloadFile(String url,
{String? name, void Function(int, int)? onReceiveProgress});
Future<dynamic> downloadFile(
String url, {
String? name,
void Function(int, int)? onReceiveProgress,
});
Future<dynamic> getDownloadedFile(String name);
}
class DownloaderRepositoryImpl extends DownloaderRepository {
DioApiService client;
DownloaderRepositoryImpl({required this.client});
@override
Future downloadFile(String url,
{String? name, void Function(int, int)? onReceiveProgress}) async {
Future downloadFile(
String url, {
String? name,
void Function(int, int)? onReceiveProgress,
}) async {
try {
var file = await getApplicationDocumentsDirectory();
var fileName = name ?? url.substring(url.lastIndexOf('/') + 1);
@ -28,12 +37,15 @@ class DownloaderRepositoryImpl extends DownloaderRepository {
print(savePath);
var isExists = await File(savePath).exists();
if (!isExists) {
await client.dio.download(url, savePath,
options: Options(headers: {
HttpHeaders.acceptEncodingHeader: '*',
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN
}),
onReceiveProgress: onReceiveProgress);
await client.dio.download(
url,
savePath,
options: Options(headers: {
HttpHeaders.acceptEncodingHeader: '*',
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN,
}),
onReceiveProgress: onReceiveProgress,
);
} else {
throw ('File already exists');
}

View File

@ -3,6 +3,7 @@ import 'package:Medito/models/models.dart';
import 'package:Medito/services/network/dio_api_services.dart';
import 'package:Medito/services/network/dio_client_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'folder_repository.g.dart';
abstract class FolderRepository {
@ -18,6 +19,7 @@ class FolderRepositoryImpl extends FolderRepository {
Future<FolderModel> fetchFolders(int folderId) async {
try {
var res = await client.getRequest('${HTTPConstants.FOLDERS}/$folderId');
return FolderModel.fromJson(res);
} catch (e) {
rethrow;

View File

@ -3,6 +3,7 @@ import 'package:Medito/models/models.dart';
import 'package:Medito/services/network/dio_api_services.dart';
import 'package:Medito/services/network/dio_client_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'session_repository.g.dart';
abstract class SessionRepository {
@ -18,6 +19,7 @@ class SessionRepositoryImpl extends SessionRepository {
Future<SessionModel> fetchSession(int sessionId) async {
try {
var res = await client.getRequest('${HTTPConstants.SESSIONS}/$sessionId');
return SessionModel.fromJson(res);
} catch (e) {
rethrow;

View File

@ -32,47 +32,47 @@ final router = GoRouter(
debugLogDiagnostics: true,
routes: [
GoRoute(
path: HomePath,
builder: (context, state) => HomeWrapperWidget(),
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getDailyRoute(),
_getWebviewRoute(),
GoRoute(
path: 'app',
routes: [_getPlayerRoute()],
pageBuilder: (context, state) => getCollectionMaterialPage(state),
),
GoRoute(
path: 'folder/:fid',
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getWebviewRoute(),
GoRoute(
path: 'folder2/:f2id',
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getWebviewRoute(),
GoRoute(
path: 'folder3/:f3id',
pageBuilder: (context, state) =>
getFolderMaterialPage(state),
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getWebviewRoute(),
],
),
],
pageBuilder: (context, state) => getFolderMaterialPage(state),
),
],
pageBuilder: (context, state) => getFolderMaterialPage(state),
),
]),
path: HomePath,
builder: (context, state) => HomeWrapperWidget(),
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getDailyRoute(),
_getWebviewRoute(),
GoRoute(
path: 'app',
routes: [_getPlayerRoute()],
pageBuilder: (context, state) => getCollectionMaterialPage(state),
),
GoRoute(
path: 'folder/:fid',
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getWebviewRoute(),
GoRoute(
path: 'folder2/:f2id',
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getWebviewRoute(),
GoRoute(
path: 'folder3/:f3id',
pageBuilder: (context, state) => getFolderMaterialPage(state),
routes: [
_getSessionRoute(),
_getArticleRoute(),
_getWebviewRoute(),
],
),
],
pageBuilder: (context, state) => getFolderMaterialPage(state),
),
],
pageBuilder: (context, state) => getFolderMaterialPage(state),
),
],
),
],
);
@ -101,11 +101,12 @@ GoRoute _getSessionRoute() {
GoRoute _getPlayerRoute() {
return GoRoute(
path: 'player',
pageBuilder: (context, state) {
return getPlayerMaterialPage(state);
},
routes: [_getWebviewRoute(), _getBackgroundSoundRoute()]);
path: 'player',
pageBuilder: (context, state) {
return getPlayerMaterialPage(state);
},
routes: [_getWebviewRoute(), _getBackgroundSoundRoute()],
);
}
GoRoute _getBackgroundSoundRoute() {
@ -125,6 +126,7 @@ GoRoute _getWebviewRoute() {
path: 'webview',
pageBuilder: (context, state) {
final url = state.extra! as Map;
return MaterialPage(
key: state.pageKey,
child: WebViewComponent(url: url['url']!),
@ -179,19 +181,19 @@ MaterialPage<void> getPlayerMaterialPage(GoRouterState state) {
MaterialPage<void> getFolderMaterialPage(GoRouterState state) {
if (state.params.length == 1) {
return MaterialPage(
key: state.pageKey, child: FolderView(id: state.params['fid'])
// child: NewFolderScreen(id: state.params['fid']),
);
key: state.pageKey, child: FolderView(id: state.params['fid']),
// child: NewFolderScreen(id: state.params['fid']),
);
} else if (state.params.length == 2) {
return MaterialPage(
key: state.pageKey, child: FolderView(id: state.params['fid'])
// child: NewFolderScreen(id: state.params['f2id']),
);
key: state.pageKey, child: FolderView(id: state.params['fid']),
// child: NewFolderScreen(id: state.params['f2id']),
);
} else {
return MaterialPage(
key: state.pageKey, child: FolderView(id: state.params['fid'])
// child: NewFolderScreen(id: state.params['f3id']),
);
key: state.pageKey, child: FolderView(id: state.params['fid']),
// child: NewFolderScreen(id: state.params['f3id']),
);
}
}
@ -228,5 +230,6 @@ String getPathFromString(String? place, List<String?> ids) {
if (place == 'app') {
return CollectionPath;
}
return '';
}

View File

@ -22,6 +22,7 @@ class DioApiService {
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
);
return response.data;
} on DioError catch (err) {
_returnDioErrorResponse(err);
@ -48,6 +49,7 @@ class DioApiService {
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
return response.data;
} on DioError catch (err) {
_returnDioErrorResponse(err);
@ -61,20 +63,25 @@ class DioApiService {
switch (error.response?.statusCode) {
case 400:
throw BadRequestException(
error.response!.statusMessage ?? 'Bad request');
error.response!.statusMessage ?? 'Bad request',
);
case 401:
throw UnauthorisedException(
'Unauthorised request: ${error.response!.statusCode}');
'Unauthorised request: ${error.response!.statusCode}',
);
case 403:
throw UnauthorisedException(
'Access forbidden: ${error.response!.statusCode}');
'Access forbidden: ${error.response!.statusCode}',
);
case 404:
throw FetchDataException(
'Api not found: ${error.response!.statusCode}');
'Api not found: ${error.response!.statusCode}',
);
case 500:
default:
throw FetchDataException(
'Error occurred while Communication with Server ');
'Error occurred while Communication with Server ',
);
}
}
}

View File

@ -1,31 +1,38 @@
import 'dart:io';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/services/network/dio_api_services.dart';
import 'package:dio/dio.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'dio_client_provider.g.dart';
part 'dio_client_provider.g.dart';
@riverpod
DioApiService dioClient(DioClientRef ref) {
var dio = Dio();
dio.options = BaseOptions(
connectTimeout: Duration(milliseconds: 60000),
// baseUrl: 'https://medito-content.medito-api.repl.co/v1/',
baseUrl: HTTPConstants.BASE_URL,
headers: {
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN,
HttpHeaders.accessControlAllowOriginHeader: '*',
HttpHeaders.accessControlAllowHeadersHeader:
'Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale',
HttpHeaders.accessControlAllowCredentialsHeader: 'true',
HttpHeaders.accessControlAllowMethodsHeader: 'POST, OPTIONS, HEAD, GET',
HttpHeaders.contentTypeHeader: ContentType.json.value,
HttpHeaders.refererHeader: 'no-referrer-when-downgrade',
HttpHeaders.acceptHeader: '*/*'
});
connectTimeout: Duration(milliseconds: 60000),
// baseUrl: 'https://medito-content.medito-api.repl.co/v1/',
baseUrl: HTTPConstants.BASE_URL,
headers: {
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN,
HttpHeaders.accessControlAllowOriginHeader: '*',
HttpHeaders.accessControlAllowHeadersHeader:
'Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale',
HttpHeaders.accessControlAllowCredentialsHeader: 'true',
HttpHeaders.accessControlAllowMethodsHeader: 'POST, OPTIONS, HEAD, GET',
HttpHeaders.contentTypeHeader: ContentType.json.value,
HttpHeaders.refererHeader: 'no-referrer-when-downgrade',
HttpHeaders.acceptHeader: '*/*',
},
);
dio.interceptors.add(LogInterceptor(
request: true, responseBody: true, requestBody: true, error: true));
request: true,
responseBody: true,
requestBody: true,
error: true,
));
var dioApiService = DioApiService(dio: dio);
return dioApiService;
}

View File

@ -9,6 +9,7 @@ class SharedPreferencesService {
static Future<String?> getStringFromSF(String key) async {
var pref = await SharedPreferences.getInstance();
var stringValue = pref.getString(key);
return stringValue;
}
@ -20,6 +21,7 @@ class SharedPreferencesService {
static Future<int?> getIntFromSF(String key) async {
var pref = await SharedPreferences.getInstance();
var intValue = pref.getInt(key);
return intValue;
}
@ -31,6 +33,7 @@ class SharedPreferencesService {
static Future<double?> getDoubleFromSF(String key) async {
var pref = await SharedPreferences.getInstance();
var doubleValue = pref.getDouble(key);
return doubleValue;
}
@ -41,18 +44,21 @@ class SharedPreferencesService {
static Future<bool?> getBoolFromPref(String key) async {
var pref = await SharedPreferences.getInstance();
return pref.getBool(key);
}
static Future<bool> removeValueFromSF(String key) async {
var pref = await SharedPreferences.getInstance();
var isRemoved = await pref.remove(key);
return isRemoved;
}
static Future<bool> checkValueInSF(String key) async {
var pref = await SharedPreferences.getInstance();
var isRemoved = pref.containsKey(key);
return isRemoved;
}
}

View File

@ -51,12 +51,14 @@ class Tracking {
static List<Map<String, String>> destinationData(String type, String item) {
return [
{TYPE: type, ITEM: item}
{TYPE: type, ITEM: item},
];
}
static Future<void> postUsage(String type,
[Map<String, String> body = const {}]) async {
static Future<void> postUsage(
String type, [
Map<String, String> body = const {},
]) async {
if (kReleaseMode) {
var packageInfo = await PackageInfo.fromPlatform();
var version = packageInfo.buildNumber;
@ -91,6 +93,7 @@ class Tracking {
),
);
print('post usage failed: ' + e.toString());
return;
}
}
@ -130,5 +133,6 @@ String mapToPlural(String fileType) {
if (fileType.contains('daily')) {
return 'dailies';
}
return '';
}

View File

@ -42,6 +42,7 @@ Future<double> _getSavedVolume() async {
}
if (vol == null || vol > 1) vol = DEFAULT_VOLUME;
return vol;
}

View File

@ -5,24 +5,29 @@ extension DurationExtensions on Duration {
/// 05:35 -> 05 min 35 sec
String toMinutesSeconds() {
var twoDigitMinutes = _toTwoDigits(
inMinutes.remainder(100)); //NB: if it's over 100 min it'll show 0:00!!
inMinutes.remainder(100),
); //NB: if it's over 100 min it'll show 0:00!!
var twoDigitSeconds = _toTwoDigits(inSeconds.remainder(60));
return '$twoDigitMinutes:$twoDigitSeconds';
}
String toReadable() {
var twoDigitMinutes = _toTwoDigits(
inMinutes.remainder(100)); //NB: if it's over 100 min it'll show 0:00!!
inMinutes.remainder(100),
); //NB: if it's over 100 min it'll show 0:00!!
var twoDigitSeconds = _toTwoDigits(inSeconds.remainder(60));
if (twoDigitSeconds.isNotNullAndNotEmpty() && twoDigitMinutes != '00') {
return '$twoDigitMinutes min $twoDigitSeconds sec';
}
return '$twoDigitSeconds sec';
}
String _toTwoDigits(int n) {
if (n >= 10) return '$n';
return '0$n';
}
}
@ -41,9 +46,11 @@ String formatSessionLength(String? item) {
}
time = min.toString();
}
return '$time min';
}
if (item == null) return '';
return item + ' min';
}

View File

@ -15,23 +15,26 @@ along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'dart:io';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/network/auth.dart';
import 'package:Medito/network/user/user_utils.dart';
import 'package:Medito/constants/constants.dart';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher/url_launcher_string.dart';
Widget getNetworkImageWidget(String? url) {
if (url.isNullOrEmpty()) return Container();
final headers = {HttpHeaders.authorizationHeader: CONTENT_TOKEN};
return Image.network(url!, fit: BoxFit.fill, headers: headers);
}
NetworkImage getNetworkImage(String url) {
final headers = {HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN};
final headers = {
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN
};
return NetworkImage(url, headers: headers);
}

View File

@ -1,8 +1,8 @@
import 'package:Medito/audioplayer/media_lib.dart';
import 'package:Medito/audioplayer/media_library.dart';
import 'package:Medito/audioplayer/medito_audio_handler.dart';
import 'package:Medito/network/downloads/downloads_bloc.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/utils/duration_ext.dart';
import 'package:Medito/network/downloads/downloads_bloc.dart';
import 'package:Medito/utils/duration_extensions.dart';
import 'package:Medito/utils/utils.dart';
import 'package:Medito/views/empty_widget.dart';
import 'package:Medito/views/main/app_bar_widget.dart';
@ -93,7 +93,7 @@ class _DownloadsListWidgetState extends State<DownloadsListWidget>
onDismissed: (direction) {
if (mounted) {
_downloadList.removeWhere((element) => element == item);
DownloadsBloc.removeSessionFromDownloads(context, item);
DownloadsBloc.removeSessionFromDownloads(item);
setState(() {});
}
@ -142,7 +142,8 @@ class _DownloadsListWidgetState extends State<DownloadsListWidget>
}
void showSwipeToDeleteTip() {
createSnackBar(StringConstants.SWIPE_TO_DELETE, context, color: ColorConstants.darkMoon);
createSnackBar(StringConstants.SWIPE_TO_DELETE, context,
color: ColorConstants.darkMoon);
}
void _refreshDownloadList() {

View File

@ -14,15 +14,16 @@ You should have received a copy of the Affero GNU General Public License
along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'dart:async';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/network/api_response.dart';
import 'package:Medito/network/downloads/downloads_bloc.dart';
import 'package:Medito/network/home/home_bloc.dart';
import 'package:Medito/network/home/home_repo.dart';
import 'package:Medito/network/home/menu_response.dart';
import 'package:Medito/network/user/user_utils.dart';
import 'package:Medito/tracking/tracking.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/routes/routes.dart';
import 'package:Medito/tracking/tracking.dart';
import 'package:Medito/utils/utils.dart';
import 'package:Medito/views/home/courses_row_widget.dart';
import 'package:Medito/views/home/daily_message_widget.dart';
@ -92,9 +93,9 @@ class _HomeWidgetState extends ConsumerState<HomeWidget> {
type, id, context, Tracking.SHORTCUT_TAPPED),
),
CoursesRowWidget(
key: _coursesKey,
onTap: (type, id) => _navigate(
type, id, context, Tracking.COURSE_TAPPED)),
key: _coursesKey,
onTap: (type, id) => _navigate(
type, id, context, Tracking.COURSE_TAPPED)),
StatsWidget(),
SizedBox(height: 16),
DailyMessageWidget(key: _dailyMessageKey),
@ -194,40 +195,50 @@ class _HomeWidgetState extends ConsumerState<HomeWidget> {
}
Widget _getTitleWidget(BuildContext context) => FutureBuilder<String>(
future: _bloc.getTitleText(DateTime.now()),
initialData: 'Medito',
builder: (context, snapshot) {
return GestureDetector(
onLongPress: () => _showVersionPopUp(context),
child: Text(snapshot.data ?? '',
style: Theme.of(context).textTheme.headline1),
);
});
future: _bloc.getTitleText(DateTime.now()),
initialData: 'Medito',
builder: (context, snapshot) {
return GestureDetector(
onLongPress: () => _showVersionPopUp(context),
child: Text(
snapshot.data ?? '',
style: Theme.of(context).textTheme.headline1,
),
);
},
);
Future<void> _showVersionPopUp(BuildContext context) async {
var line1 = await getDeviceInfoString();
var prefs = await SharedPreferences.getInstance();
var userID = prefs.getString(USER_ID) ?? 'None';
final snackBar = SnackBar(
content: GestureDetector(
onTap: () {
Share.share('$line1 $userID');
},
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Tap here to copy',
style: TextStyle(color: ColorConstants.walterWhite)),
Text(line1,
style: TextStyle(color: ColorConstants.meditoTextGrey)),
Text(userID,
style: TextStyle(color: ColorConstants.meditoTextGrey))
],
),
content: GestureDetector(
onTap: () {
Share.share('$line1 $userID');
},
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tap here to copy',
style: TextStyle(color: ColorConstants.walterWhite),
),
Text(
line1,
style: TextStyle(color: ColorConstants.meditoTextGrey),
),
Text(
userID,
style: TextStyle(color: ColorConstants.meditoTextGrey),
),
],
),
backgroundColor: ColorConstants.midnight);
),
backgroundColor: ColorConstants.midnight,
);
// Find the Scaffold in the Widget tree and use it to show a SnackBar!
ScaffoldMessenger.of(context).showSnackBar(snackBar);
@ -252,8 +263,11 @@ class _HomeWidgetState extends ConsumerState<HomeWidget> {
await DownloadsBloc.seenTip().then((seen) {
if (!seen) {
unawaited(DownloadsBloc.setSeenTip());
createSnackBar(StringConstants.SWIPE_TO_DELETE, context,
color: ColorConstants.darkMoon);
createSnackBar(
StringConstants.SWIPE_TO_DELETE,
context,
color: ColorConstants.darkMoon,
);
}
});
}

View File

@ -5,6 +5,7 @@ import 'package:flutter_svg/svg.dart';
class EmptyStateWidget extends StatelessWidget {
final String? message;
final SvgPicture? image;
const EmptyStateWidget({Key? key, this.message, this.image})
: super(key: key);

View File

@ -33,7 +33,10 @@ class FolderView extends ConsumerWidget {
Widget _buildLoadingWidget() => const FolderShimmerComponent();
RefreshIndicator _buildScaffoldWithData(
BuildContext context, FolderModel folder, WidgetRef ref) {
BuildContext context,
FolderModel folder,
WidgetRef ref,
) {
return RefreshIndicator(
onRefresh: () async {
return await ref.refresh(FoldersProvider(folderId: 28));
@ -60,7 +63,11 @@ class FolderView extends ConsumerWidget {
}
Container _buildListTile(
BuildContext context, String? title, String? subtitle, String type) {
BuildContext context,
String? title,
String? subtitle,
String type,
) {
return Container(
decoration: BoxDecoration(
border: Border(

View File

@ -1,6 +1,6 @@
import 'package:Medito/constants/constants.dart';
import 'package:Medito/models/models.dart';
import 'package:Medito/utils/duration_ext.dart';
import 'package:Medito/utils/duration_extensions.dart';
import 'package:Medito/view_model/audio_player/audio_player_viewmodel.dart';
import 'package:Medito/view_model/player/audio_position_viewmodel.dart';
import 'package:flutter/material.dart';

View File

@ -16,10 +16,10 @@ along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'package:Medito/audioplayer/audio_inherited_widget.dart';
import 'package:Medito/audioplayer/medito_audio_handler.dart';
import 'package:Medito/audioplayer/player_utils.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/network/api_response.dart';
import 'package:Medito/network/session_options/background_sounds.dart';
import 'package:Medito/utils/bgvolume_utils.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/utils/shared_preferences_utils.dart';
import 'package:Medito/utils/utils.dart';
import 'package:Medito/views/player_old/components/position_indicator_widget.dart';
@ -60,8 +60,12 @@ class _ChooseBackgroundSoundDialogState
}
// On some android phones, the back button kills the session :/
bool backInterceptor(bool stopDefaultButtonEvent, RouteInfo info) {
bool backInterceptor(
bool stopDefaultButtonEvent,
RouteInfo info,
) {
Navigator.pop(context);
return true;
}
@ -70,6 +74,7 @@ class _ChooseBackgroundSoundDialogState
_volume = await retrieveSavedBgVolume();
await await Future.delayed(Duration(milliseconds: 200)).then((value) {
_handler?.customAction(SET_BG_SOUND_VOL, {SET_BG_SOUND_VOL: _volume});
return _handler?.customAction(SEND_BG_SOUND, {SEND_BG_SOUND: bgSound});
});
}
@ -79,94 +84,69 @@ class _ChooseBackgroundSoundDialogState
_handler = AudioHandlerInheritedWidget.of(context).audioHandler;
return StreamBuilder(
stream: Stream.fromFuture(
Connectivity().checkConnectivity(),
),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.data == ConnectivityResult.none) {
_isOffline = true;
}
return StreamBuilder<dynamic>(
stream: widget.handler?.customEvent.stream,
initialData: {SEND_BG_SOUND: NONE},
builder: (context, snapshot) {
var currentSound =
_getCurrentSoundFromSnapshot(snapshot.data);
return DraggableScrollableSheet(
expand: false,
builder: (BuildContext context,
ScrollController scrollController) {
return SafeArea(
top: true,
bottom: false,
child: Material(
color: ColorConstants.moonlight,
child: _isOffline
? _offlineBackgroundSounds(
currentSound, scrollController)
: _onlineBackgroundSounds(
currentSound, scrollController)),
);
},
);
});
} else {
return Container(); // return a spinner
stream: Stream.fromFuture(
Connectivity().checkConnectivity(),
),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.data == ConnectivityResult.none) {
_isOffline = true;
}
});
return StreamBuilder<dynamic>(
stream: widget.handler?.customEvent.stream,
initialData: {SEND_BG_SOUND: NONE},
builder: (context, snapshot) {
var currentSound = _getCurrentSoundFromSnapshot(snapshot.data);
return DraggableScrollableSheet(
expand: false,
builder:
(BuildContext context, ScrollController scrollController) {
return SafeArea(
top: true,
bottom: false,
child: Material(
color: ColorConstants.moonlight,
child: _isOffline
? _offlineBackgroundSounds(
currentSound, scrollController)
: _onlineBackgroundSounds(
currentSound, scrollController),
),
);
},
);
},
);
} else {
return Container(); // return a spinner
}
},
);
}
Widget _onlineBackgroundSounds(
String currentSound, ScrollController scrollController) {
String currentSound,
ScrollController scrollController,
) {
return StreamBuilder<ApiResponse<BackgroundSoundsResponse>>(
stream: widget.stream,
initialData: ApiResponse.loading(),
builder: (context, snapshot) {
switch (snapshot.data?.status) {
case Status.LOADING:
return Center(
child: const CircularProgressIndicator(
backgroundColor: Colors.black,
valueColor: AlwaysStoppedAnimation<Color>(
ColorConstants.walterWhite)));
case Status.COMPLETED:
var list = snapshot.data?.body?.data;
stream: widget.stream,
initialData: ApiResponse.loading(),
builder: (context, snapshot) {
switch (snapshot.data?.status) {
case Status.LOADING:
return Center(
child: const CircularProgressIndicator(
backgroundColor: Colors.black,
valueColor: AlwaysStoppedAnimation<Color>(
ColorConstants.walterWhite,
),
),
);
case Status.COMPLETED:
var list = snapshot.data?.body?.data;
var widgetList = <Widget>[
Divider(height: 16),
_getHeader(),
Divider(height: 16),
_getVolumeWidget(),
Divider(height: 16),
_getNoneListItem(currentSound)
];
if (list != null) {
widgetList.addAll(list
.map<Widget>((e) =>
_getBackgroundSoundListTile(e, currentSound, context))
.toList());
}
return ListView(
controller: scrollController, children: widgetList);
case Status.ERROR:
return _getErrorWidget();
case null:
return Container();
}
});
}
Widget _offlineBackgroundSounds(
String currentSound, ScrollController scrollController) {
return FutureBuilder<List<BackgroundSoundData>>(
future: getBgSoundFromOfflineSharedPrefs(),
initialData: [],
builder: (context, snapshot) {
if (snapshot.hasData) {
var list = snapshot.data;
var widgetList = <Widget>[
Divider(height: 16),
_getHeader(),
@ -177,20 +157,57 @@ class _ChooseBackgroundSoundDialogState
];
if (list != null) {
widgetList.addAll(list
.map((e) =>
.map<Widget>((e) =>
_getBackgroundSoundListTile(e, currentSound, context))
.toList());
}
return ListView(controller: scrollController, children: widgetList);
} else {
return Center(
child: const CircularProgressIndicator(
backgroundColor: Colors.black,
valueColor: AlwaysStoppedAnimation<Color>(
ColorConstants.walterWhite)));
case Status.ERROR:
return _getErrorWidget();
case null:
return Container();
}
},
);
}
Widget _offlineBackgroundSounds(
String currentSound, ScrollController scrollController) {
return FutureBuilder<List<BackgroundSoundData>>(
future: getBgSoundFromOfflineSharedPrefs(),
initialData: [],
builder: (context, snapshot) {
if (snapshot.hasData) {
var list = snapshot.data;
var widgetList = <Widget>[
Divider(height: 16),
_getHeader(),
Divider(height: 16),
_getVolumeWidget(),
Divider(height: 16),
_getNoneListItem(currentSound),
];
if (list != null) {
widgetList.addAll(list
.map((e) =>
_getBackgroundSoundListTile(e, currentSound, context))
.toList());
}
});
return ListView(controller: scrollController, children: widgetList);
} else {
return Center(
child: const CircularProgressIndicator(
backgroundColor: Colors.black,
valueColor:
AlwaysStoppedAnimation<Color>(ColorConstants.walterWhite),
),
);
}
},
);
}
Widget _getErrorWidget() => Padding(
@ -217,11 +234,12 @@ class _ChooseBackgroundSoundDialogState
TextStyle? _getTheme(current, String? name) {
return Theme.of(context).textTheme.bodyText2?.copyWith(
fontWeight:
_isSelected(current, name) ? FontWeight.w600 : FontWeight.normal,
color: _isSelected(current, name)
? ColorConstants.walterWhite
: ColorConstants.meditoTextGrey);
fontWeight:
_isSelected(current, name) ? FontWeight.w600 : FontWeight.normal,
color: _isSelected(current, name)
? ColorConstants.walterWhite
: ColorConstants.meditoTextGrey,
);
}
Widget _getVisibilityWidget(String name, String current, Widget child) =>
@ -234,44 +252,65 @@ class _ChooseBackgroundSoundDialogState
current == name || (current == '' && name == NONE);
Widget _getBackgroundSoundListTile(
BackgroundSoundData item, String current, BuildContext context) {
BackgroundSoundData item,
String current,
BuildContext context,
) {
var assetUrl = item.file?.toAssetUrl();
return InkWell(
onTap: () {
setState(() {
_downloadingItem = item.name;
});
onTap: () {
setState(() {
_downloadingItem = item.name;
});
downloadBGMusicFromURL(assetUrl, item.name).then((filePath) {
if (filePath == 'Connectivity lost') {
_downloadingItem = '';
_isOffline = true;
setState(() {});
createSnackBar(
'Connectivity lost. Displaying offline background sounds.',
context);
_noneSelected();
}
downloadBGMusicFromURL(assetUrl, item.name).then((filePath) {
if (filePath == 'Connectivity lost') {
_downloadingItem = '';
addBgSoundSelectionToSharedPrefs(filePath, item.name);
widget.handler
?.customAction(PLAY_BG_SOUND, {PLAY_BG_SOUND: filePath});
return widget.handler
?.customAction(SEND_BG_SOUND, {SEND_BG_SOUND: item.name});
});
},
child: ListTile(
enableFeedback: true,
title: Text('${item.name}', style: _getTheme(current, item.name)),
trailing: _isDownloading(item)
? _getSmallLoadingWidget()
: _getVisibilityWidget(
item.name ?? '',
current,
Icon(
Icons.check_circle_outline,
color: ColorConstants.walterWhite,
))));
_isOffline = true;
setState(() {});
createSnackBar(
'Connectivity lost. Displaying offline background sounds.',
context,
);
_noneSelected();
}
_downloadingItem = '';
addBgSoundSelectionToSharedPrefs(
filePath,
item.name,
);
widget.handler?.customAction(
PLAY_BG_SOUND,
{PLAY_BG_SOUND: filePath},
);
return widget.handler?.customAction(
SEND_BG_SOUND,
{SEND_BG_SOUND: item.name},
);
});
},
child: ListTile(
enableFeedback: true,
title: Text(
'${item.name}',
style: _getTheme(
current,
item.name,
),
),
trailing: _isDownloading(item)
? _getSmallLoadingWidget()
: _getVisibilityWidget(
item.name ?? '',
current,
Icon(
Icons.check_circle_outline,
color: ColorConstants.walterWhite,
),
),
),
);
}
bool _isDownloading(BackgroundSoundData item) =>
@ -280,12 +319,14 @@ class _ChooseBackgroundSoundDialogState
Widget _getSmallLoadingWidget() => Padding(
padding: const EdgeInsets.only(right: 6.0),
child: SizedBox(
height: 16,
width: 16,
child: const CircularProgressIndicator(
backgroundColor: Colors.black,
valueColor:
AlwaysStoppedAnimation<Color>(ColorConstants.walterWhite))),
height: 16,
width: 16,
child: const CircularProgressIndicator(
backgroundColor: Colors.black,
valueColor:
AlwaysStoppedAnimation<Color>(ColorConstants.walterWhite),
),
),
);
void _noneSelected() {
@ -297,11 +338,12 @@ class _ChooseBackgroundSoundDialogState
Widget _getHeader() {
return Padding(
padding: const EdgeInsets.only(bottom: 8.0, left: 16.0, top: 8.0),
child: Text(
StringConstants.BACKGROUND_SOUNDS,
style: Theme.of(context).textTheme.headline1,
));
padding: const EdgeInsets.only(bottom: 8.0, left: 16.0, top: 8.0),
child: Text(
StringConstants.BACKGROUND_SOUNDS,
style: Theme.of(context).textTheme.headline1,
),
);
}
Widget _getVolumeWidget() {
@ -310,45 +352,49 @@ class _ChooseBackgroundSoundDialogState
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: StreamBuilder<Object>(
stream: _dragBgVolumeSubject,
builder: (context, snapshot) {
var volume = _dragBgVolumeSubject.value;
var volumeIcon = _volumeIconFunction(volume);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(volumeIcon, size: 24, color: ColorConstants.walterWhite),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 24.0, right: 4),
child: SliderTheme(
data: SliderThemeData(
trackShape: CustomTrackShape(addTopPadding: false),
thumbShape:
RoundSliderThumbShape(enabledThumbRadius: 10.0),
),
child: Slider(
min: 0.0,
activeColor: ColorConstants.walterWhite,
inactiveColor:
ColorConstants.walterWhite.withOpacity(0.7),
max: 1.0,
value: volume,
onChanged: (value) {
_dragBgVolumeSubject.add(value);
_handler?.customAction(
SET_BG_SOUND_VOL, {SET_BG_SOUND_VOL: value});
},
onChangeEnd: (value) {
saveBgVolume(value);
},
),
stream: _dragBgVolumeSubject,
builder: (context, snapshot) {
var volume = _dragBgVolumeSubject.value;
var volumeIcon = _volumeIconFunction(volume);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(volumeIcon, size: 24, color: ColorConstants.walterWhite),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 24.0, right: 4),
child: SliderTheme(
data: SliderThemeData(
trackShape: CustomTrackShape(addTopPadding: false),
thumbShape:
RoundSliderThumbShape(enabledThumbRadius: 10.0),
),
child: Slider(
min: 0.0,
activeColor: ColorConstants.walterWhite,
inactiveColor:
ColorConstants.walterWhite.withOpacity(0.7),
max: 1.0,
value: volume,
onChanged: (value) {
_dragBgVolumeSubject.add(value);
_handler?.customAction(
SET_BG_SOUND_VOL,
{SET_BG_SOUND_VOL: value},
);
},
onChangeEnd: (value) {
saveBgVolume(value);
},
),
),
),
],
);
}),
),
],
);
},
),
),
);
}

View File

@ -1,14 +1,13 @@
import 'dart:math';
import 'package:Medito/audioplayer/media_lib.dart';
import 'package:Medito/audioplayer/media_library.dart';
import 'package:Medito/audioplayer/medito_audio_handler.dart';
import 'package:Medito/network/player/player_bloc.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/utils/duration_ext.dart';
import 'package:Medito/routes/routes.dart';
import 'package:Medito/utils/duration_extensions.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:rxdart/rxdart.dart';
import 'background_sounds_sheet_widget.dart';
class PositionIndicatorWidget extends StatefulWidget {
final MeditoAudioHandler? handler;

View File

@ -15,11 +15,11 @@ along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'dart:async';
import 'package:Medito/audioplayer/media_lib.dart';
import 'package:Medito/audioplayer/media_library.dart';
import 'package:Medito/audioplayer/medito_audio_handler.dart';
import 'package:Medito/components/components.dart';
import 'package:Medito/network/player/player_bloc.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/network/player/player_bloc.dart';
import 'package:Medito/routes/routes.dart';
import 'package:Medito/utils/shared_preferences_utils.dart';
import 'package:Medito/utils/utils.dart';
@ -29,6 +29,7 @@ import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import '../../../audioplayer/audio_inherited_widget.dart';
import '../../../tracking/tracking.dart';
import '../../../utils/bgvolume_utils.dart';
@ -93,13 +94,16 @@ class _PlayerWidgetState extends State<PlayerWidget> {
event[AUDIO_COMPLETE] == true) {
_trackSessionEnd(_handler?.mediaItem.value);
showGeneralDialog(
transitionDuration: Duration(milliseconds: 400),
context: context,
barrierColor: ColorConstants.darkMoon,
pageBuilder: (_, __, ___) {
return AudioCompleteDialog(
bloc: _bloc, mediaItem: _handler?.mediaItem.value);
});
transitionDuration: Duration(milliseconds: 400),
context: context,
barrierColor: ColorConstants.darkMoon,
pageBuilder: (_, __, ___) {
return AudioCompleteDialog(
bloc: _bloc,
mediaItem: _handler?.mediaItem.value,
);
},
);
}
});
@ -112,8 +116,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
image: getNetworkImage(mediaItem?.artUri?.toString() ?? ''),
fit: BoxFit.fill,
colorFilter: ColorFilter.mode(
ColorConstants.almostBlack.withOpacity(0.65),
BlendMode.overlay),
ColorConstants.almostBlack.withOpacity(0.65),
BlendMode.overlay,
),
),
),
child: SafeArea(
@ -131,8 +136,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
_buildPlayerButtonRow(mediaItem),
// A seek bar.
PositionIndicatorWidget(
handler: _handler,
bgSoundsStream: _bloc.bgSoundsListController?.stream),
handler: _handler,
bgSoundsStream: _bloc.bgSoundsListController?.stream,
),
Container(height: 24),
],
),
@ -149,12 +155,14 @@ class _PlayerWidgetState extends State<PlayerWidget> {
getSavedBgSoundData();
}
} on Exception catch (e, s) {
unawaited(Sentry.captureException(e,
stackTrace: s,
hint: Hint.withMap({
'message':
'Failed trying to get save background sounds data: extras[HAS_BG_SOUND]: ${_hasBGSound()}'
})));
unawaited(Sentry.captureException(
e,
stackTrace: s,
hint: Hint.withMap({
'message':
'Failed trying to get save background sounds data: extras[HAS_BG_SOUND]: ${_hasBGSound()}',
}),
));
}
}
@ -207,10 +215,12 @@ class _PlayerWidgetState extends State<PlayerWidget> {
Padding _getSubtitleWidget(MediaItem? mediaItem) {
var attr = mediaItem?.extras != null ? (mediaItem?.extras?['attr']) : '';
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: MarkdownComponent(
body: 'Giovanni Dienstmann https://www.google.com/'),
body: 'Giovanni Dienstmann https://www.google.com/',
),
);
}
@ -255,7 +265,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
{
Tracking.SESSION_ID: mediaItem.extras?[SESSION_ID].toString() ?? '',
Tracking.SESSION_DURATION: mediaItem.extras?[LENGTH].toString() ?? '',
Tracking.SESSION_GUIDE: mediaItem.artist ?? ''
Tracking.SESSION_GUIDE: mediaItem.artist ?? '',
},
),
);

View File

@ -13,9 +13,8 @@ Affero GNU General Public License for more details.
You should have received a copy of the Affero GNU General Public License
along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
import 'package:Medito/constants/constants.dart';
import 'package:Medito/network/text/text_bloc.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/constants/constants.dart';
import 'package:Medito/utils/utils.dart';
import 'package:Medito/views/main/app_bar_widget.dart';
import 'package:flutter/material.dart';
@ -62,14 +61,15 @@ class _TextFileWidgetState extends State<TextFileWidget>
appBar: PreferredSize(
preferredSize: const Size(double.infinity, kToolbarHeight),
child: StreamBuilder<String>(
stream: _bloc.titleController.stream,
initialData: '...',
builder: (context, snapshot) {
return MeditoAppBarWidget(
isTransparent: true,
title: snapshot.data ?? '',
);
}), // StreamBuilder
stream: _bloc.titleController.stream,
initialData: '...',
builder: (context, snapshot) {
return MeditoAppBarWidget(
isTransparent: true,
title: snapshot.data ?? '',
);
},
), // StreamBuilder
),
body: RefreshIndicator(
onRefresh: () => _bloc.fetchText(widget.id, true),
@ -105,32 +105,43 @@ class _TextFileWidgetState extends State<TextFileWidget>
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 16.0, right: 16.0, top: 12.0, bottom: 16.0),
left: 16.0,
right: 16.0,
top: 12.0,
bottom: 16.0,
),
child: StreamBuilder<String>(
stream: _bloc.bodyController.stream,
initialData: 'Loading...',
builder: (context, snapshot) {
return Markdown(
data: snapshot.data ?? '',
onTapLink: _linkTap,
physics: NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
shrinkWrap: true,
selectable: true,
styleSheet: buildMarkdownStyleSheet(context).copyWith(
horizontalRuleDecoration: BoxDecoration(
border: Border(
top: BorderSide(
width: 1.0,
color: ColorConstants.meditoTextGrey,
),
),
),
h2: TextStyle(
color: ColorConstants.walterWhite, height: 1.5),
p: TextStyle(
color: ColorConstants.walterWhite, height: 1.5)));
}),
stream: _bloc.bodyController.stream,
initialData: 'Loading...',
builder: (context, snapshot) {
return Markdown(
data: snapshot.data ?? '',
onTapLink: _linkTap,
physics: NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
shrinkWrap: true,
selectable: true,
styleSheet: buildMarkdownStyleSheet(context).copyWith(
horizontalRuleDecoration: BoxDecoration(
border: Border(
top: BorderSide(
width: 1.0,
color: ColorConstants.meditoTextGrey,
),
),
),
h2: TextStyle(
color: ColorConstants.walterWhite,
height: 1.5,
),
p: TextStyle(
color: ColorConstants.walterWhite,
height: 1.5,
),
),
);
},
),
),
],
),

View File

@ -36,11 +36,12 @@ void main() {
isPublished: true,
items: [
FolderItemsModel(
type: 'session',
id: 120,
title: 'Complete meditation',
subtitle: '19 min',
path: 'sessions/120')
type: 'session',
id: 120,
title: 'Complete meditation',
subtitle: '19 min',
path: 'sessions/120',
),
],
);
final mockFolderRepository = MockFolderRepository();