mirror of
https://github.com/meditohq/medito-app.git
synced 2024-08-16 15:40:36 +03:00
Fixed warnings
This commit is contained in:
parent
482b73f374
commit
bead831986
@ -11,4 +11,19 @@ dart_code_metrics:
|
|||||||
metrics-exclude:
|
metrics-exclude:
|
||||||
- test/**
|
- test/**
|
||||||
rules:
|
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
|
@ -85,7 +85,7 @@ class _Download {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore: unnecessary_cast
|
// ignore: unnecessary_cast
|
||||||
downloadAmountListener.value = progress as double;
|
downloadAmountListener.value = progress as double; // it is necessary
|
||||||
}).onDone(() async {
|
}).onDone(() async {
|
||||||
try {
|
try {
|
||||||
await file.writeAsBytes(_bytes);
|
await file.writeAsBytes(_bytes);
|
||||||
@ -103,6 +103,7 @@ class _Download {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -115,11 +116,8 @@ class _Download {
|
|||||||
.then((value) => _throwResponse = value);
|
.then((value) => _throwResponse = value);
|
||||||
_total = _throwResponse?.contentLength ?? 0;
|
_total = _throwResponse?.contentLength ?? 0;
|
||||||
}
|
}
|
||||||
if (_received != null && _total != null) {
|
|
||||||
return _received! / _total!;
|
return (_received != null && _total != null) ? (_received! / _total!) : 0;
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,20 +146,23 @@ class DownloadSingleton {
|
|||||||
double getProgress(AudioFile file) {
|
double getProgress(AudioFile file) {
|
||||||
if (_download == null) return -1;
|
if (_download == null) return -1;
|
||||||
if (isDownloadingMe(file)) return _download?.getProgress() ?? 0.0;
|
if (isDownloadingMe(file)) return _download?.getProgress() ?? 0.0;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool start(BuildContext context, AudioFile file, MediaItem mediaItem) {
|
bool start(AudioFile file, MediaItem mediaItem) {
|
||||||
if (_download == null) return false;
|
if (_download == null) return false;
|
||||||
if (_download?.isDownloadingMe(file) ?? false) return true;
|
if (_download?.isDownloadingMe(file) ?? false) return true;
|
||||||
if (isDownloadingSomething()) return false;
|
if (isDownloadingSomething()) return false;
|
||||||
|
|
||||||
if (_download?.isThisFile(file) ?? false) {
|
if (_download?.isThisFile(file) ?? false) {
|
||||||
_download?.startDownloading(file, mediaItem);
|
_download?.startDownloading(file, mediaItem);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_download = _Download(file);
|
_download = _Download(file);
|
||||||
_download?.startDownloading(file, mediaItem);
|
_download?.startDownloading(file, mediaItem);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import 'package:audio_service/audio_service.dart';
|
import 'package:audio_service/audio_service.dart';
|
||||||
|
|
||||||
class MediaLibrary {
|
class MediaLibrary {
|
||||||
static MediaItem getMediaLibrary(
|
static MediaItem getMediaLibrary({
|
||||||
{String? description,
|
String? description,
|
||||||
String? title,
|
String? title,
|
||||||
String? illustrationUrl,
|
String? illustrationUrl,
|
||||||
String? secondaryColor,
|
String? secondaryColor,
|
||||||
String? primaryColor,
|
String? primaryColor,
|
||||||
int? durationAsMilliseconds,
|
int? durationAsMilliseconds,
|
||||||
String? fileId,
|
String? fileId,
|
||||||
String? attributions,
|
String? attributions,
|
||||||
String? voice,
|
String? voice,
|
||||||
String? length,
|
String? length,
|
||||||
bool? hasBgSound,
|
bool? hasBgSound,
|
||||||
int? sessionId}) {
|
int? sessionId,
|
||||||
|
}) {
|
||||||
return MediaItem(
|
return MediaItem(
|
||||||
id: fileId ?? '',
|
id: fileId ?? '',
|
||||||
extras: {
|
extras: {
|
||||||
@ -25,10 +26,12 @@ class MediaLibrary {
|
|||||||
ATTR: attributions,
|
ATTR: attributions,
|
||||||
LENGTH: length,
|
LENGTH: length,
|
||||||
DURATION: durationAsMilliseconds,
|
DURATION: durationAsMilliseconds,
|
||||||
HAS_BG_SOUND : hasBgSound,
|
HAS_BG_SOUND: hasBgSound,
|
||||||
},
|
},
|
||||||
artist: voice,
|
artist: voice,
|
||||||
album: '', //empty to remove it from the notification
|
displayDescription: description,
|
||||||
|
album: '',
|
||||||
|
//empty to remove it from the notification
|
||||||
title: title ?? '',
|
title: title ?? '',
|
||||||
artUri: Uri.parse(illustrationUrl ?? ''),
|
artUri: Uri.parse(illustrationUrl ?? ''),
|
||||||
);
|
);
|
||||||
@ -45,4 +48,4 @@ const String PRIMARY_COLOUR = 'primaryColor';
|
|||||||
const String ID = 'id';
|
const String ID = 'id';
|
||||||
const String SESSION_ID = 'sessionId';
|
const String SESSION_ID = 'sessionId';
|
||||||
const String SESSION_TITLE = 'sessionTitle';
|
const String SESSION_TITLE = 'sessionTitle';
|
||||||
const String LOCATION = 'location';
|
const String LOCATION = 'location';
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:Medito/constants/constants.dart';
|
|
||||||
import 'package:Medito/utils/utils.dart';
|
import 'package:Medito/utils/utils.dart';
|
||||||
import 'package:audio_service/audio_service.dart';
|
import 'package:audio_service/audio_service.dart';
|
||||||
import 'package:audio_session/audio_session.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/auth.dart';
|
||||||
import '../network/cache.dart';
|
import '../network/cache.dart';
|
||||||
import '../utils/bgvolume_utils.dart';
|
import '../utils/bgvolume_utils.dart';
|
||||||
import 'media_lib.dart';
|
import 'media_library.dart';
|
||||||
import 'player_utils.dart';
|
import 'player_utils.dart';
|
||||||
|
|
||||||
//This is the duration of bgSound fade towards the end.
|
//This is the duration of bgSound fade towards the end.
|
||||||
@ -170,7 +169,7 @@ class MeditoAudioHandler extends BaseAudioHandler
|
|||||||
unawaited(_bgPlayer.setVolume(_bgVolume));
|
unawaited(_bgPlayer.setVolume(_bgVolume));
|
||||||
break;
|
break;
|
||||||
case PLAY_BG_SOUND:
|
case PLAY_BG_SOUND:
|
||||||
await _playBgSound(extras);
|
_playBgSound(extras);
|
||||||
break;
|
break;
|
||||||
case INIT_BG_SOUND:
|
case INIT_BG_SOUND:
|
||||||
_bgVolume = extras?[SET_BG_SOUND_VOL] ?? DEFAULT_VOLUME;
|
_bgVolume = extras?[SET_BG_SOUND_VOL] ?? DEFAULT_VOLUME;
|
||||||
@ -186,7 +185,7 @@ class MeditoAudioHandler extends BaseAudioHandler
|
|||||||
return super.customAction(name, extras);
|
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];
|
var bgSound = extras?[PLAY_BG_SOUND];
|
||||||
if (bgSound != null) {
|
if (bgSound != null) {
|
||||||
unawaited(_bgPlayer.setFilePath(extras?[PLAY_BG_SOUND]));
|
unawaited(_bgPlayer.setFilePath(extras?[PLAY_BG_SOUND]));
|
||||||
@ -212,13 +211,16 @@ class MeditoAudioHandler extends BaseAudioHandler
|
|||||||
print(_bgPlayer.volume - (_bgVolume / FADE_DURATION));
|
print(_bgPlayer.volume - (_bgVolume / FADE_DURATION));
|
||||||
if (_bgPlayer.volume > 0) {
|
if (_bgPlayer.volume > 0) {
|
||||||
unawaited(
|
unawaited(
|
||||||
_bgPlayer.setVolume(_bgPlayer.volume - (_bgVolume / FADE_DURATION)));
|
_bgPlayer.setVolume(_bgPlayer.volume - (_bgVolume / FADE_DURATION)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void skipForward30Secs() {
|
void skipForward30Secs() {
|
||||||
var seekDuration = min(_duration?.inMilliseconds ?? 0,
|
var seekDuration = min(
|
||||||
_player.position.inMilliseconds + Duration(seconds: 30).inMilliseconds);
|
_duration?.inMilliseconds ?? 0,
|
||||||
|
_player.position.inMilliseconds + Duration(seconds: 30).inMilliseconds,
|
||||||
|
);
|
||||||
_player.seek(Duration(milliseconds: seekDuration));
|
_player.seek(Duration(milliseconds: seekDuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ Future<bool?> checkBgSoundExists(String name) async {
|
|||||||
var filePath = (await getFilePath(name));
|
var filePath = (await getFilePath(name));
|
||||||
var file = File(filePath);
|
var file = File(filePath);
|
||||||
var exists = await file.exists();
|
var exists = await file.exists();
|
||||||
|
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
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/>.*/
|
along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:Medito/audioplayer/medito_audio_handler.dart';
|
import 'package:Medito/audioplayer/medito_audio_handler.dart';
|
||||||
import 'package:Medito/constants/constants.dart';
|
import 'package:Medito/constants/constants.dart';
|
||||||
import 'package:Medito/routes/routes.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/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.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:sentry_flutter/sentry_flutter.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|
||||||
import 'audioplayer/audio_inherited_widget.dart';
|
import 'audioplayer/audio_inherited_widget.dart';
|
||||||
import 'network/auth.dart';
|
import 'network/auth.dart';
|
||||||
|
|
||||||
@ -106,14 +108,15 @@ class _ParentWidgetState extends State<ParentWidget>
|
|||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
routerConfig: router,
|
routerConfig: router,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
splashColor: ColorConstants.moonlight,
|
splashColor: ColorConstants.moonlight,
|
||||||
canvasColor: ColorConstants.greyIsTheNewBlack,
|
canvasColor: ColorConstants.greyIsTheNewBlack,
|
||||||
pageTransitionsTheme: PageTransitionsTheme(builders: {
|
pageTransitionsTheme: PageTransitionsTheme(builders: {
|
||||||
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
|
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
|
||||||
TargetPlatform.android: SlideTransitionBuilder(),
|
TargetPlatform.android: SlideTransitionBuilder(),
|
||||||
}),
|
}),
|
||||||
colorScheme: ColorScheme.dark(secondary: ColorConstants.walterWhite),
|
colorScheme: ColorScheme.dark(secondary: ColorConstants.walterWhite),
|
||||||
textTheme: meditoTextTheme(context)),
|
textTheme: meditoTextTheme(context),
|
||||||
|
),
|
||||||
title: ParentWidget._title,
|
title: ParentWidget._title,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,10 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
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/audioplayer/player_utils.dart';
|
||||||
import 'package:Medito/network/session_options/session_opts.dart';
|
import 'package:Medito/network/session_options/session_opts.dart';
|
||||||
import 'package:audio_service/audio_service.dart';
|
import 'package:audio_service/audio_service.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:package_info/package_info.dart';
|
import 'package:package_info/package_info.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
@ -15,16 +14,19 @@ class DownloadsBloc {
|
|||||||
|
|
||||||
static Future<bool> seenTip() async {
|
static Future<bool> seenTip() async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
return prefs.getBool('seenDownloadsToolTip') ?? false;
|
return prefs.getBool('seenDownloadsToolTip') ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> setSeenTip() async {
|
static Future<bool> setSeenTip() async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
return prefs.setBool('seenDownloadsToolTip', true);
|
return prefs.setBool('seenDownloadsToolTip', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> saveFileToDownloadedFilesList(
|
static Future<void> saveFileToDownloadedFilesList(
|
||||||
MediaItem _mediaItem) async {
|
MediaItem _mediaItem,
|
||||||
|
) async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
var list = prefs.getStringList(savedFilesKey) ?? [];
|
var list = prefs.getStringList(savedFilesKey) ?? [];
|
||||||
|
|
||||||
@ -42,7 +44,7 @@ class DownloadsBloc {
|
|||||||
'artist': _mediaItem.artist,
|
'artist': _mediaItem.artist,
|
||||||
'duration': _mediaItem.duration?.inMilliseconds,
|
'duration': _mediaItem.duration?.inMilliseconds,
|
||||||
'artUri': _mediaItem.artUri.toString(),
|
'artUri': _mediaItem.artUri.toString(),
|
||||||
'extras': _mediaItem.extras
|
'extras': _mediaItem.extras,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,12 +68,13 @@ class DownloadsBloc {
|
|||||||
|
|
||||||
static MediaItem _getMediaItemFromMap(json) {
|
static MediaItem _getMediaItemFromMap(json) {
|
||||||
return MediaItem(
|
return MediaItem(
|
||||||
id: json['id'],
|
id: json['id'],
|
||||||
title: json['title'],
|
title: json['title'],
|
||||||
artist: json['artist'],
|
artist: json['artist'],
|
||||||
duration: Duration(milliseconds: json['duration'] ?? 0),
|
duration: Duration(milliseconds: json['duration'] ?? 0),
|
||||||
artUri: Uri.parse(json['artUri']),
|
artUri: Uri.parse(json['artUri']),
|
||||||
extras: json['extras']);
|
extras: json['extras'],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> isAudioFileDownloaded(AudioFile? file) async {
|
static Future<bool> isAudioFileDownloaded(AudioFile? file) async {
|
||||||
@ -87,7 +90,8 @@ class DownloadsBloc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> removeSessionFromDownloads(
|
static Future<void> removeSessionFromDownloads(
|
||||||
BuildContext context, MediaItem mediaFile) async {
|
MediaItem mediaFile,
|
||||||
|
) async {
|
||||||
// Delete the download file from disk for this session
|
// Delete the download file from disk for this session
|
||||||
var filePath = (await getFilePath(mediaFile.id));
|
var filePath = (await getFilePath(mediaFile.id));
|
||||||
var file = File(filePath);
|
var file = File(filePath);
|
||||||
@ -99,7 +103,8 @@ class DownloadsBloc {
|
|||||||
// Remove the session from all downloads list
|
// Remove the session from all downloads list
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
var list = prefs.getStringList(savedFilesKey) ?? [];
|
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);
|
await prefs.setStringList(savedFilesKey, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,8 +112,9 @@ class DownloadsBloc {
|
|||||||
/// Saves a given `List` of `MediaItem` elements (downloaded sessions)
|
/// Saves a given `List` of `MediaItem` elements (downloaded sessions)
|
||||||
static Future<void> saveDownloads(List<MediaItem> mediaList) async {
|
static Future<void> saveDownloads(List<MediaItem> mediaList) async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
var list =
|
var list = mediaList
|
||||||
mediaList.map((MediaItem mediaItem) => _jsonEncodeMediaItem(mediaItem)).toList();
|
.map((MediaItem mediaItem) => _jsonEncodeMediaItem(mediaItem))
|
||||||
|
.toList();
|
||||||
await prefs.setStringList(savedFilesKey, list);
|
await prefs.setStringList(savedFilesKey, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import 'package:Medito/utils/utils.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import 'folder_provider.dart';
|
import 'folder_provider.dart';
|
||||||
|
|
||||||
class NewFolderScreen extends ConsumerWidget {
|
class NewFolderScreen extends ConsumerWidget {
|
||||||
@ -34,21 +35,26 @@ class NewFolderScreen extends ConsumerWidget {
|
|||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: CollapsibleHeaderComponent(
|
body: CollapsibleHeaderComponent(
|
||||||
bgImage: AssetConstants.dalle,
|
bgImage: AssetConstants.dalle,
|
||||||
title: folder?.data?.title ?? '',
|
title: folder?.data?.title ?? '',
|
||||||
description: folder?.data?.description,
|
description: folder?.data?.description,
|
||||||
children: [
|
children: [
|
||||||
for (int i = 0; i < (folder?.data?.items?.length ?? 0); i++)
|
for (int i = 0; i < (folder?.data?.items?.length ?? 0); i++)
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => _onListItemTap(folder?.data?.items?[i].item?.id,
|
onTap: () => _onListItemTap(
|
||||||
folder?.data?.items?[i].item?.type, ref.context),
|
folder?.data?.items?[i].item?.id,
|
||||||
child: _buildListTile(
|
folder?.data?.items?[i].item?.type,
|
||||||
context,
|
ref.context,
|
||||||
folder?.data?.items?[i].item?.title,
|
),
|
||||||
folder?.data?.items?[i].item?.subtitle,
|
child: _buildListTile(
|
||||||
true),
|
context,
|
||||||
)
|
folder?.data?.items?[i].item?.title,
|
||||||
]),
|
folder?.data?.items?[i].item?.subtitle,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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
|
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/>.*/
|
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/auth.dart';
|
||||||
import 'package:Medito/network/http_get.dart';
|
import 'package:Medito/network/http_get.dart';
|
||||||
import 'package:Medito/network/session_options/background_sounds.dart';
|
import 'package:Medito/network/session_options/background_sounds.dart';
|
||||||
|
@ -16,12 +16,12 @@ along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:Medito/audioplayer/download_class.dart';
|
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/api_response.dart';
|
||||||
import 'package:Medito/network/session_options/session_options_repo.dart';
|
import 'package:Medito/network/session_options/session_options_repo.dart';
|
||||||
import 'package:Medito/network/session_options/session_opts.dart';
|
import 'package:Medito/network/session_options/session_opts.dart';
|
||||||
import 'package:Medito/tracking/tracking.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:audio_service/audio_service.dart';
|
||||||
import 'package:pedantic/pedantic.dart';
|
import 'package:pedantic/pedantic.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@ -131,7 +131,7 @@ class SessionOptionsBloc {
|
|||||||
{
|
{
|
||||||
Tracking.SESSION_ID: mediaItem.extras?[SESSION_ID].toString() ?? '',
|
Tracking.SESSION_ID: mediaItem.extras?[SESSION_ID].toString() ?? '',
|
||||||
Tracking.SESSION_DURATION: mediaItem.extras?[LENGTH].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,
|
secondaryColor: _options?.colorSecondary,
|
||||||
primaryColor: _options?.colorPrimary,
|
primaryColor: _options?.colorPrimary,
|
||||||
durationAsMilliseconds:
|
durationAsMilliseconds:
|
||||||
clockTimeToDuration(file?.length).inMilliseconds,
|
clockTimeToDuration(file?.length).inMilliseconds,
|
||||||
fileId: file?.id,
|
fileId: file?.id,
|
||||||
sessionId: _options?.id,
|
sessionId: _options?.id,
|
||||||
attributions: _options?.attribution);
|
attributions: _options?.attribution);
|
||||||
@ -169,10 +169,10 @@ class SessionOptionsBloc {
|
|||||||
// Add file data against each voice
|
// Add file data against each voice
|
||||||
voiceSet.toList().forEach((voice) {
|
voiceSet.toList().forEach((voice) {
|
||||||
var listForThisVoice =
|
var listForThisVoice =
|
||||||
items.where((element) => element?.voice == voice).toList();
|
items.where((element) => element?.voice == voice).toList();
|
||||||
|
|
||||||
var voiceItem =
|
var voiceItem =
|
||||||
VoiceItem(headerValue: voice, listForVoice: listForThisVoice);
|
VoiceItem(headerValue: voice, listForVoice: listForThisVoice);
|
||||||
voiceList.add(voiceItem);
|
voiceList.add(voiceItem);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ class TextResponse {
|
|||||||
if (data != null) {
|
if (data != null) {
|
||||||
data['data'] = this.data?.toJson();
|
data['data'] = this.data?.toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,6 +45,7 @@ class Data {
|
|||||||
data['title'] = title;
|
data['title'] = title;
|
||||||
data['subtitle'] = subtitle;
|
data['subtitle'] = subtitle;
|
||||||
data['body'] = body;
|
data['body'] = body;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ class UserResponse {
|
|||||||
if (this.data != null) {
|
if (this.data != null) {
|
||||||
data['data'] = this.data?.toJson();
|
data['data'] = this.data?.toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,6 +31,7 @@ class Data {
|
|||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final data = <String, dynamic>{};
|
final data = <String, dynamic>{};
|
||||||
data['id'] = id;
|
data['id'] = id;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,6 +17,7 @@ Future<bool> firstOpenOperations() async {
|
|||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
var opened = _beginClearStorage(prefs);
|
var opened = _beginClearStorage(prefs);
|
||||||
await _logAccount(prefs);
|
await _logAccount(prefs);
|
||||||
|
|
||||||
return opened;
|
return opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ bool _beginClearStorage(SharedPreferences prefs) {
|
|||||||
if (!opened) {
|
if (!opened) {
|
||||||
unawaited(_clearStorage(prefs));
|
unawaited(_clearStorage(prefs));
|
||||||
}
|
}
|
||||||
|
|
||||||
return opened;
|
return opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +107,7 @@ class UserRepo {
|
|||||||
|
|
||||||
Future<String?> get generatedToken async {
|
Future<String?> get generatedToken async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
return prefs.getString(TOKEN);
|
return prefs.getString(TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +144,7 @@ Future<Map<String, String>> getDeviceDetails() async {
|
|||||||
DEVICE_MODEL: deviceModel,
|
DEVICE_MODEL: deviceModel,
|
||||||
DEVICE_OS: deviceOS,
|
DEVICE_OS: deviceOS,
|
||||||
DEVICE_PLATFORM: devicePlatform,
|
DEVICE_PLATFORM: devicePlatform,
|
||||||
DEVICE_LANGUAGE: deviceLanguage
|
DEVICE_LANGUAGE: deviceLanguage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_api_services.dart';
|
||||||
import 'package:Medito/services/network/dio_client_provider.dart';
|
import 'package:Medito/services/network/dio_client_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'background_sounds_repository.g.dart';
|
part 'background_sounds_repository.g.dart';
|
||||||
|
|
||||||
abstract class BackgroundSoundsRepository {
|
abstract class BackgroundSoundsRepository {
|
||||||
@ -19,6 +20,7 @@ class BackgroundSoundsRepositoryImpl extends BackgroundSoundsRepository {
|
|||||||
try {
|
try {
|
||||||
var res = await client.getRequest(HTTPConstants.BACKGROUND_SOUNDS);
|
var res = await client.getRequest(HTTPConstants.BACKGROUND_SOUNDS);
|
||||||
var tempResponse = res as List;
|
var tempResponse = res as List;
|
||||||
|
|
||||||
return tempResponse
|
return tempResponse
|
||||||
.map((x) => BackgroundSoundsModel.fromJson(x))
|
.map((x) => BackgroundSoundsModel.fromJson(x))
|
||||||
.toList();
|
.toList();
|
||||||
@ -30,6 +32,7 @@ class BackgroundSoundsRepositoryImpl extends BackgroundSoundsRepository {
|
|||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
BackgroundSoundsRepositoryImpl backgroundSoundsRepository(
|
BackgroundSoundsRepositoryImpl backgroundSoundsRepository(
|
||||||
BackgroundSoundsRepositoryRef ref) {
|
BackgroundSoundsRepositoryRef ref,
|
||||||
|
) {
|
||||||
return BackgroundSoundsRepositoryImpl(client: ref.watch(dioClientProvider));
|
return BackgroundSoundsRepositoryImpl(client: ref.watch(dioClientProvider));
|
||||||
}
|
}
|
||||||
|
@ -6,21 +6,30 @@ import 'package:Medito/services/network/dio_client_provider.dart';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'downloader_repository.g.dart';
|
part 'downloader_repository.g.dart';
|
||||||
|
|
||||||
abstract class DownloaderRepository {
|
abstract class DownloaderRepository {
|
||||||
Future<dynamic> downloadFile(String url,
|
Future<dynamic> downloadFile(
|
||||||
{String? name, void Function(int, int)? onReceiveProgress});
|
String url, {
|
||||||
|
String? name,
|
||||||
|
void Function(int, int)? onReceiveProgress,
|
||||||
|
});
|
||||||
|
|
||||||
Future<dynamic> getDownloadedFile(String name);
|
Future<dynamic> getDownloadedFile(String name);
|
||||||
}
|
}
|
||||||
|
|
||||||
class DownloaderRepositoryImpl extends DownloaderRepository {
|
class DownloaderRepositoryImpl extends DownloaderRepository {
|
||||||
DioApiService client;
|
DioApiService client;
|
||||||
|
|
||||||
DownloaderRepositoryImpl({required this.client});
|
DownloaderRepositoryImpl({required this.client});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future downloadFile(String url,
|
Future downloadFile(
|
||||||
{String? name, void Function(int, int)? onReceiveProgress}) async {
|
String url, {
|
||||||
|
String? name,
|
||||||
|
void Function(int, int)? onReceiveProgress,
|
||||||
|
}) async {
|
||||||
try {
|
try {
|
||||||
var file = await getApplicationDocumentsDirectory();
|
var file = await getApplicationDocumentsDirectory();
|
||||||
var fileName = name ?? url.substring(url.lastIndexOf('/') + 1);
|
var fileName = name ?? url.substring(url.lastIndexOf('/') + 1);
|
||||||
@ -28,12 +37,15 @@ class DownloaderRepositoryImpl extends DownloaderRepository {
|
|||||||
print(savePath);
|
print(savePath);
|
||||||
var isExists = await File(savePath).exists();
|
var isExists = await File(savePath).exists();
|
||||||
if (!isExists) {
|
if (!isExists) {
|
||||||
await client.dio.download(url, savePath,
|
await client.dio.download(
|
||||||
options: Options(headers: {
|
url,
|
||||||
HttpHeaders.acceptEncodingHeader: '*',
|
savePath,
|
||||||
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN
|
options: Options(headers: {
|
||||||
}),
|
HttpHeaders.acceptEncodingHeader: '*',
|
||||||
onReceiveProgress: onReceiveProgress);
|
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN,
|
||||||
|
}),
|
||||||
|
onReceiveProgress: onReceiveProgress,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
throw ('File already exists');
|
throw ('File already exists');
|
||||||
}
|
}
|
||||||
|
@ -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_api_services.dart';
|
||||||
import 'package:Medito/services/network/dio_client_provider.dart';
|
import 'package:Medito/services/network/dio_client_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'folder_repository.g.dart';
|
part 'folder_repository.g.dart';
|
||||||
|
|
||||||
abstract class FolderRepository {
|
abstract class FolderRepository {
|
||||||
@ -18,6 +19,7 @@ class FolderRepositoryImpl extends FolderRepository {
|
|||||||
Future<FolderModel> fetchFolders(int folderId) async {
|
Future<FolderModel> fetchFolders(int folderId) async {
|
||||||
try {
|
try {
|
||||||
var res = await client.getRequest('${HTTPConstants.FOLDERS}/$folderId');
|
var res = await client.getRequest('${HTTPConstants.FOLDERS}/$folderId');
|
||||||
|
|
||||||
return FolderModel.fromJson(res);
|
return FolderModel.fromJson(res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
|
@ -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_api_services.dart';
|
||||||
import 'package:Medito/services/network/dio_client_provider.dart';
|
import 'package:Medito/services/network/dio_client_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'session_repository.g.dart';
|
part 'session_repository.g.dart';
|
||||||
|
|
||||||
abstract class SessionRepository {
|
abstract class SessionRepository {
|
||||||
@ -18,6 +19,7 @@ class SessionRepositoryImpl extends SessionRepository {
|
|||||||
Future<SessionModel> fetchSession(int sessionId) async {
|
Future<SessionModel> fetchSession(int sessionId) async {
|
||||||
try {
|
try {
|
||||||
var res = await client.getRequest('${HTTPConstants.SESSIONS}/$sessionId');
|
var res = await client.getRequest('${HTTPConstants.SESSIONS}/$sessionId');
|
||||||
|
|
||||||
return SessionModel.fromJson(res);
|
return SessionModel.fromJson(res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
|
@ -32,47 +32,47 @@ final router = GoRouter(
|
|||||||
debugLogDiagnostics: true,
|
debugLogDiagnostics: true,
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: HomePath,
|
path: HomePath,
|
||||||
builder: (context, state) => HomeWrapperWidget(),
|
builder: (context, state) => HomeWrapperWidget(),
|
||||||
routes: [
|
routes: [
|
||||||
_getSessionRoute(),
|
_getSessionRoute(),
|
||||||
_getArticleRoute(),
|
_getArticleRoute(),
|
||||||
_getDailyRoute(),
|
_getDailyRoute(),
|
||||||
_getWebviewRoute(),
|
_getWebviewRoute(),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'app',
|
path: 'app',
|
||||||
routes: [_getPlayerRoute()],
|
routes: [_getPlayerRoute()],
|
||||||
pageBuilder: (context, state) => getCollectionMaterialPage(state),
|
pageBuilder: (context, state) => getCollectionMaterialPage(state),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'folder/:fid',
|
path: 'folder/:fid',
|
||||||
routes: [
|
routes: [
|
||||||
_getSessionRoute(),
|
_getSessionRoute(),
|
||||||
_getArticleRoute(),
|
_getArticleRoute(),
|
||||||
_getWebviewRoute(),
|
_getWebviewRoute(),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'folder2/:f2id',
|
path: 'folder2/:f2id',
|
||||||
routes: [
|
routes: [
|
||||||
_getSessionRoute(),
|
_getSessionRoute(),
|
||||||
_getArticleRoute(),
|
_getArticleRoute(),
|
||||||
_getWebviewRoute(),
|
_getWebviewRoute(),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'folder3/:f3id',
|
path: 'folder3/:f3id',
|
||||||
pageBuilder: (context, state) =>
|
pageBuilder: (context, state) => getFolderMaterialPage(state),
|
||||||
getFolderMaterialPage(state),
|
routes: [
|
||||||
routes: [
|
_getSessionRoute(),
|
||||||
_getSessionRoute(),
|
_getArticleRoute(),
|
||||||
_getArticleRoute(),
|
_getWebviewRoute(),
|
||||||
_getWebviewRoute(),
|
],
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
],
|
pageBuilder: (context, state) => getFolderMaterialPage(state),
|
||||||
pageBuilder: (context, state) => getFolderMaterialPage(state),
|
),
|
||||||
),
|
],
|
||||||
],
|
pageBuilder: (context, state) => getFolderMaterialPage(state),
|
||||||
pageBuilder: (context, state) => getFolderMaterialPage(state),
|
),
|
||||||
),
|
],
|
||||||
]),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -101,11 +101,12 @@ GoRoute _getSessionRoute() {
|
|||||||
|
|
||||||
GoRoute _getPlayerRoute() {
|
GoRoute _getPlayerRoute() {
|
||||||
return GoRoute(
|
return GoRoute(
|
||||||
path: 'player',
|
path: 'player',
|
||||||
pageBuilder: (context, state) {
|
pageBuilder: (context, state) {
|
||||||
return getPlayerMaterialPage(state);
|
return getPlayerMaterialPage(state);
|
||||||
},
|
},
|
||||||
routes: [_getWebviewRoute(), _getBackgroundSoundRoute()]);
|
routes: [_getWebviewRoute(), _getBackgroundSoundRoute()],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GoRoute _getBackgroundSoundRoute() {
|
GoRoute _getBackgroundSoundRoute() {
|
||||||
@ -125,6 +126,7 @@ GoRoute _getWebviewRoute() {
|
|||||||
path: 'webview',
|
path: 'webview',
|
||||||
pageBuilder: (context, state) {
|
pageBuilder: (context, state) {
|
||||||
final url = state.extra! as Map;
|
final url = state.extra! as Map;
|
||||||
|
|
||||||
return MaterialPage(
|
return MaterialPage(
|
||||||
key: state.pageKey,
|
key: state.pageKey,
|
||||||
child: WebViewComponent(url: url['url']!),
|
child: WebViewComponent(url: url['url']!),
|
||||||
@ -179,19 +181,19 @@ MaterialPage<void> getPlayerMaterialPage(GoRouterState state) {
|
|||||||
MaterialPage<void> getFolderMaterialPage(GoRouterState state) {
|
MaterialPage<void> getFolderMaterialPage(GoRouterState state) {
|
||||||
if (state.params.length == 1) {
|
if (state.params.length == 1) {
|
||||||
return MaterialPage(
|
return MaterialPage(
|
||||||
key: state.pageKey, child: FolderView(id: state.params['fid'])
|
key: state.pageKey, child: FolderView(id: state.params['fid']),
|
||||||
// child: NewFolderScreen(id: state.params['fid']),
|
// child: NewFolderScreen(id: state.params['fid']),
|
||||||
);
|
);
|
||||||
} else if (state.params.length == 2) {
|
} else if (state.params.length == 2) {
|
||||||
return MaterialPage(
|
return MaterialPage(
|
||||||
key: state.pageKey, child: FolderView(id: state.params['fid'])
|
key: state.pageKey, child: FolderView(id: state.params['fid']),
|
||||||
// child: NewFolderScreen(id: state.params['f2id']),
|
// child: NewFolderScreen(id: state.params['f2id']),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return MaterialPage(
|
return MaterialPage(
|
||||||
key: state.pageKey, child: FolderView(id: state.params['fid'])
|
key: state.pageKey, child: FolderView(id: state.params['fid']),
|
||||||
// child: NewFolderScreen(id: state.params['f3id']),
|
// child: NewFolderScreen(id: state.params['f3id']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,5 +230,6 @@ String getPathFromString(String? place, List<String?> ids) {
|
|||||||
if (place == 'app') {
|
if (place == 'app') {
|
||||||
return CollectionPath;
|
return CollectionPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ class DioApiService {
|
|||||||
cancelToken: cancelToken,
|
cancelToken: cancelToken,
|
||||||
onReceiveProgress: onReceiveProgress,
|
onReceiveProgress: onReceiveProgress,
|
||||||
);
|
);
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
} on DioError catch (err) {
|
} on DioError catch (err) {
|
||||||
_returnDioErrorResponse(err);
|
_returnDioErrorResponse(err);
|
||||||
@ -48,6 +49,7 @@ class DioApiService {
|
|||||||
onSendProgress: onSendProgress,
|
onSendProgress: onSendProgress,
|
||||||
onReceiveProgress: onReceiveProgress,
|
onReceiveProgress: onReceiveProgress,
|
||||||
);
|
);
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
} on DioError catch (err) {
|
} on DioError catch (err) {
|
||||||
_returnDioErrorResponse(err);
|
_returnDioErrorResponse(err);
|
||||||
@ -61,20 +63,25 @@ class DioApiService {
|
|||||||
switch (error.response?.statusCode) {
|
switch (error.response?.statusCode) {
|
||||||
case 400:
|
case 400:
|
||||||
throw BadRequestException(
|
throw BadRequestException(
|
||||||
error.response!.statusMessage ?? 'Bad request');
|
error.response!.statusMessage ?? 'Bad request',
|
||||||
|
);
|
||||||
case 401:
|
case 401:
|
||||||
throw UnauthorisedException(
|
throw UnauthorisedException(
|
||||||
'Unauthorised request: ${error.response!.statusCode}');
|
'Unauthorised request: ${error.response!.statusCode}',
|
||||||
|
);
|
||||||
case 403:
|
case 403:
|
||||||
throw UnauthorisedException(
|
throw UnauthorisedException(
|
||||||
'Access forbidden: ${error.response!.statusCode}');
|
'Access forbidden: ${error.response!.statusCode}',
|
||||||
|
);
|
||||||
case 404:
|
case 404:
|
||||||
throw FetchDataException(
|
throw FetchDataException(
|
||||||
'Api not found: ${error.response!.statusCode}');
|
'Api not found: ${error.response!.statusCode}',
|
||||||
|
);
|
||||||
case 500:
|
case 500:
|
||||||
default:
|
default:
|
||||||
throw FetchDataException(
|
throw FetchDataException(
|
||||||
'Error occurred while Communication with Server ');
|
'Error occurred while Communication with Server ',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,38 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:Medito/constants/constants.dart';
|
import 'package:Medito/constants/constants.dart';
|
||||||
import 'package:Medito/services/network/dio_api_services.dart';
|
import 'package:Medito/services/network/dio_api_services.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'dio_client_provider.g.dart';
|
|
||||||
|
|
||||||
|
part 'dio_client_provider.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
DioApiService dioClient(DioClientRef ref) {
|
DioApiService dioClient(DioClientRef ref) {
|
||||||
var dio = Dio();
|
var dio = Dio();
|
||||||
dio.options = BaseOptions(
|
dio.options = BaseOptions(
|
||||||
connectTimeout: Duration(milliseconds: 60000),
|
connectTimeout: Duration(milliseconds: 60000),
|
||||||
// baseUrl: 'https://medito-content.medito-api.repl.co/v1/',
|
// baseUrl: 'https://medito-content.medito-api.repl.co/v1/',
|
||||||
baseUrl: HTTPConstants.BASE_URL,
|
baseUrl: HTTPConstants.BASE_URL,
|
||||||
headers: {
|
headers: {
|
||||||
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN,
|
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN,
|
||||||
HttpHeaders.accessControlAllowOriginHeader: '*',
|
HttpHeaders.accessControlAllowOriginHeader: '*',
|
||||||
HttpHeaders.accessControlAllowHeadersHeader:
|
HttpHeaders.accessControlAllowHeadersHeader:
|
||||||
'Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale',
|
'Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale',
|
||||||
HttpHeaders.accessControlAllowCredentialsHeader: 'true',
|
HttpHeaders.accessControlAllowCredentialsHeader: 'true',
|
||||||
HttpHeaders.accessControlAllowMethodsHeader: 'POST, OPTIONS, HEAD, GET',
|
HttpHeaders.accessControlAllowMethodsHeader: 'POST, OPTIONS, HEAD, GET',
|
||||||
HttpHeaders.contentTypeHeader: ContentType.json.value,
|
HttpHeaders.contentTypeHeader: ContentType.json.value,
|
||||||
HttpHeaders.refererHeader: 'no-referrer-when-downgrade',
|
HttpHeaders.refererHeader: 'no-referrer-when-downgrade',
|
||||||
HttpHeaders.acceptHeader: '*/*'
|
HttpHeaders.acceptHeader: '*/*',
|
||||||
});
|
},
|
||||||
|
);
|
||||||
dio.interceptors.add(LogInterceptor(
|
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);
|
var dioApiService = DioApiService(dio: dio);
|
||||||
|
|
||||||
return dioApiService;
|
return dioApiService;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ class SharedPreferencesService {
|
|||||||
static Future<String?> getStringFromSF(String key) async {
|
static Future<String?> getStringFromSF(String key) async {
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var stringValue = pref.getString(key);
|
var stringValue = pref.getString(key);
|
||||||
|
|
||||||
return stringValue;
|
return stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ class SharedPreferencesService {
|
|||||||
static Future<int?> getIntFromSF(String key) async {
|
static Future<int?> getIntFromSF(String key) async {
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var intValue = pref.getInt(key);
|
var intValue = pref.getInt(key);
|
||||||
|
|
||||||
return intValue;
|
return intValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +33,7 @@ class SharedPreferencesService {
|
|||||||
static Future<double?> getDoubleFromSF(String key) async {
|
static Future<double?> getDoubleFromSF(String key) async {
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var doubleValue = pref.getDouble(key);
|
var doubleValue = pref.getDouble(key);
|
||||||
|
|
||||||
return doubleValue;
|
return doubleValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,18 +44,21 @@ class SharedPreferencesService {
|
|||||||
|
|
||||||
static Future<bool?> getBoolFromPref(String key) async {
|
static Future<bool?> getBoolFromPref(String key) async {
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
return pref.getBool(key);
|
return pref.getBool(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> removeValueFromSF(String key) async {
|
static Future<bool> removeValueFromSF(String key) async {
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var isRemoved = await pref.remove(key);
|
var isRemoved = await pref.remove(key);
|
||||||
|
|
||||||
return isRemoved;
|
return isRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> checkValueInSF(String key) async {
|
static Future<bool> checkValueInSF(String key) async {
|
||||||
var pref = await SharedPreferences.getInstance();
|
var pref = await SharedPreferences.getInstance();
|
||||||
var isRemoved = pref.containsKey(key);
|
var isRemoved = pref.containsKey(key);
|
||||||
|
|
||||||
return isRemoved;
|
return isRemoved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,14 @@ class Tracking {
|
|||||||
|
|
||||||
static List<Map<String, String>> destinationData(String type, String item) {
|
static List<Map<String, String>> destinationData(String type, String item) {
|
||||||
return [
|
return [
|
||||||
{TYPE: type, ITEM: item}
|
{TYPE: type, ITEM: item},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> postUsage(String type,
|
static Future<void> postUsage(
|
||||||
[Map<String, String> body = const {}]) async {
|
String type, [
|
||||||
|
Map<String, String> body = const {},
|
||||||
|
]) async {
|
||||||
if (kReleaseMode) {
|
if (kReleaseMode) {
|
||||||
var packageInfo = await PackageInfo.fromPlatform();
|
var packageInfo = await PackageInfo.fromPlatform();
|
||||||
var version = packageInfo.buildNumber;
|
var version = packageInfo.buildNumber;
|
||||||
@ -91,6 +93,7 @@ class Tracking {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
print('post usage failed: ' + e.toString());
|
print('post usage failed: ' + e.toString());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,5 +133,6 @@ String mapToPlural(String fileType) {
|
|||||||
if (fileType.contains('daily')) {
|
if (fileType.contains('daily')) {
|
||||||
return 'dailies';
|
return 'dailies';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ Future<double> _getSavedVolume() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vol == null || vol > 1) vol = DEFAULT_VOLUME;
|
if (vol == null || vol > 1) vol = DEFAULT_VOLUME;
|
||||||
|
|
||||||
return vol;
|
return vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,24 +5,29 @@ extension DurationExtensions on Duration {
|
|||||||
/// 05:35 -> 05 min 35 sec
|
/// 05:35 -> 05 min 35 sec
|
||||||
String toMinutesSeconds() {
|
String toMinutesSeconds() {
|
||||||
var twoDigitMinutes = _toTwoDigits(
|
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));
|
var twoDigitSeconds = _toTwoDigits(inSeconds.remainder(60));
|
||||||
|
|
||||||
return '$twoDigitMinutes:$twoDigitSeconds';
|
return '$twoDigitMinutes:$twoDigitSeconds';
|
||||||
}
|
}
|
||||||
|
|
||||||
String toReadable() {
|
String toReadable() {
|
||||||
var twoDigitMinutes = _toTwoDigits(
|
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));
|
var twoDigitSeconds = _toTwoDigits(inSeconds.remainder(60));
|
||||||
|
|
||||||
if (twoDigitSeconds.isNotNullAndNotEmpty() && twoDigitMinutes != '00') {
|
if (twoDigitSeconds.isNotNullAndNotEmpty() && twoDigitMinutes != '00') {
|
||||||
return '$twoDigitMinutes min $twoDigitSeconds sec';
|
return '$twoDigitMinutes min $twoDigitSeconds sec';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '$twoDigitSeconds sec';
|
return '$twoDigitSeconds sec';
|
||||||
}
|
}
|
||||||
|
|
||||||
String _toTwoDigits(int n) {
|
String _toTwoDigits(int n) {
|
||||||
if (n >= 10) return '$n';
|
if (n >= 10) return '$n';
|
||||||
|
|
||||||
return '0$n';
|
return '0$n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,9 +46,11 @@ String formatSessionLength(String? item) {
|
|||||||
}
|
}
|
||||||
time = min.toString();
|
time = min.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return '$time min';
|
return '$time min';
|
||||||
}
|
}
|
||||||
if (item == null) return '';
|
if (item == null) return '';
|
||||||
|
|
||||||
return item + ' min';
|
return item + ' min';
|
||||||
}
|
}
|
||||||
|
|
@ -15,23 +15,26 @@ along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
|
|||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:Medito/constants/constants.dart';
|
||||||
import 'package:Medito/network/auth.dart';
|
import 'package:Medito/network/auth.dart';
|
||||||
import 'package:Medito/network/user/user_utils.dart';
|
import 'package:Medito/network/user/user_utils.dart';
|
||||||
import 'package:Medito/constants/constants.dart';
|
|
||||||
import 'package:connectivity/connectivity.dart';
|
import 'package:connectivity/connectivity.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
Widget getNetworkImageWidget(String? url) {
|
Widget getNetworkImageWidget(String? url) {
|
||||||
if (url.isNullOrEmpty()) return Container();
|
if (url.isNullOrEmpty()) return Container();
|
||||||
final headers = {HttpHeaders.authorizationHeader: CONTENT_TOKEN};
|
final headers = {HttpHeaders.authorizationHeader: CONTENT_TOKEN};
|
||||||
|
|
||||||
return Image.network(url!, fit: BoxFit.fill, headers: headers);
|
return Image.network(url!, fit: BoxFit.fill, headers: headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkImage getNetworkImage(String url) {
|
NetworkImage getNetworkImage(String url) {
|
||||||
final headers = {HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN};
|
final headers = {
|
||||||
|
|
||||||
|
HttpHeaders.authorizationHeader: HTTPConstants.CONTENT_TOKEN
|
||||||
|
};
|
||||||
return NetworkImage(url, headers: headers);
|
return NetworkImage(url, headers: headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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/audioplayer/medito_audio_handler.dart';
|
||||||
import 'package:Medito/network/downloads/downloads_bloc.dart';
|
|
||||||
import 'package:Medito/constants/constants.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/utils/utils.dart';
|
||||||
import 'package:Medito/views/empty_widget.dart';
|
import 'package:Medito/views/empty_widget.dart';
|
||||||
import 'package:Medito/views/main/app_bar_widget.dart';
|
import 'package:Medito/views/main/app_bar_widget.dart';
|
||||||
@ -93,7 +93,7 @@ class _DownloadsListWidgetState extends State<DownloadsListWidget>
|
|||||||
onDismissed: (direction) {
|
onDismissed: (direction) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_downloadList.removeWhere((element) => element == item);
|
_downloadList.removeWhere((element) => element == item);
|
||||||
DownloadsBloc.removeSessionFromDownloads(context, item);
|
DownloadsBloc.removeSessionFromDownloads(item);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,8 @@ class _DownloadsListWidgetState extends State<DownloadsListWidget>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showSwipeToDeleteTip() {
|
void showSwipeToDeleteTip() {
|
||||||
createSnackBar(StringConstants.SWIPE_TO_DELETE, context, color: ColorConstants.darkMoon);
|
createSnackBar(StringConstants.SWIPE_TO_DELETE, context,
|
||||||
|
color: ColorConstants.darkMoon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _refreshDownloadList() {
|
void _refreshDownloadList() {
|
||||||
|
@ -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/>.*/
|
along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:Medito/constants/constants.dart';
|
||||||
import 'package:Medito/network/api_response.dart';
|
import 'package:Medito/network/api_response.dart';
|
||||||
import 'package:Medito/network/downloads/downloads_bloc.dart';
|
import 'package:Medito/network/downloads/downloads_bloc.dart';
|
||||||
import 'package:Medito/network/home/home_bloc.dart';
|
import 'package:Medito/network/home/home_bloc.dart';
|
||||||
import 'package:Medito/network/home/home_repo.dart';
|
import 'package:Medito/network/home/home_repo.dart';
|
||||||
import 'package:Medito/network/home/menu_response.dart';
|
import 'package:Medito/network/home/menu_response.dart';
|
||||||
import 'package:Medito/network/user/user_utils.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/routes/routes.dart';
|
||||||
|
import 'package:Medito/tracking/tracking.dart';
|
||||||
import 'package:Medito/utils/utils.dart';
|
import 'package:Medito/utils/utils.dart';
|
||||||
import 'package:Medito/views/home/courses_row_widget.dart';
|
import 'package:Medito/views/home/courses_row_widget.dart';
|
||||||
import 'package:Medito/views/home/daily_message_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),
|
type, id, context, Tracking.SHORTCUT_TAPPED),
|
||||||
),
|
),
|
||||||
CoursesRowWidget(
|
CoursesRowWidget(
|
||||||
key: _coursesKey,
|
key: _coursesKey,
|
||||||
onTap: (type, id) => _navigate(
|
onTap: (type, id) => _navigate(
|
||||||
type, id, context, Tracking.COURSE_TAPPED)),
|
type, id, context, Tracking.COURSE_TAPPED)),
|
||||||
StatsWidget(),
|
StatsWidget(),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
DailyMessageWidget(key: _dailyMessageKey),
|
DailyMessageWidget(key: _dailyMessageKey),
|
||||||
@ -194,40 +195,50 @@ class _HomeWidgetState extends ConsumerState<HomeWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _getTitleWidget(BuildContext context) => FutureBuilder<String>(
|
Widget _getTitleWidget(BuildContext context) => FutureBuilder<String>(
|
||||||
future: _bloc.getTitleText(DateTime.now()),
|
future: _bloc.getTitleText(DateTime.now()),
|
||||||
initialData: 'Medito',
|
initialData: 'Medito',
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onLongPress: () => _showVersionPopUp(context),
|
onLongPress: () => _showVersionPopUp(context),
|
||||||
child: Text(snapshot.data ?? '',
|
child: Text(
|
||||||
style: Theme.of(context).textTheme.headline1),
|
snapshot.data ?? '',
|
||||||
);
|
style: Theme.of(context).textTheme.headline1,
|
||||||
});
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> _showVersionPopUp(BuildContext context) async {
|
Future<void> _showVersionPopUp(BuildContext context) async {
|
||||||
var line1 = await getDeviceInfoString();
|
var line1 = await getDeviceInfoString();
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
var userID = prefs.getString(USER_ID) ?? 'None';
|
var userID = prefs.getString(USER_ID) ?? 'None';
|
||||||
final snackBar = SnackBar(
|
final snackBar = SnackBar(
|
||||||
content: GestureDetector(
|
content: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Share.share('$line1 $userID');
|
Share.share('$line1 $userID');
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text('Tap here to copy',
|
Text(
|
||||||
style: TextStyle(color: ColorConstants.walterWhite)),
|
'Tap here to copy',
|
||||||
Text(line1,
|
style: TextStyle(color: ColorConstants.walterWhite),
|
||||||
style: TextStyle(color: ColorConstants.meditoTextGrey)),
|
),
|
||||||
Text(userID,
|
Text(
|
||||||
style: TextStyle(color: ColorConstants.meditoTextGrey))
|
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!
|
// Find the Scaffold in the Widget tree and use it to show a SnackBar!
|
||||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
@ -252,8 +263,11 @@ class _HomeWidgetState extends ConsumerState<HomeWidget> {
|
|||||||
await DownloadsBloc.seenTip().then((seen) {
|
await DownloadsBloc.seenTip().then((seen) {
|
||||||
if (!seen) {
|
if (!seen) {
|
||||||
unawaited(DownloadsBloc.setSeenTip());
|
unawaited(DownloadsBloc.setSeenTip());
|
||||||
createSnackBar(StringConstants.SWIPE_TO_DELETE, context,
|
createSnackBar(
|
||||||
color: ColorConstants.darkMoon);
|
StringConstants.SWIPE_TO_DELETE,
|
||||||
|
context,
|
||||||
|
color: ColorConstants.darkMoon,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'package:flutter_svg/svg.dart';
|
|||||||
class EmptyStateWidget extends StatelessWidget {
|
class EmptyStateWidget extends StatelessWidget {
|
||||||
final String? message;
|
final String? message;
|
||||||
final SvgPicture? image;
|
final SvgPicture? image;
|
||||||
|
|
||||||
const EmptyStateWidget({Key? key, this.message, this.image})
|
const EmptyStateWidget({Key? key, this.message, this.image})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
|
@ -33,7 +33,10 @@ class FolderView extends ConsumerWidget {
|
|||||||
Widget _buildLoadingWidget() => const FolderShimmerComponent();
|
Widget _buildLoadingWidget() => const FolderShimmerComponent();
|
||||||
|
|
||||||
RefreshIndicator _buildScaffoldWithData(
|
RefreshIndicator _buildScaffoldWithData(
|
||||||
BuildContext context, FolderModel folder, WidgetRef ref) {
|
BuildContext context,
|
||||||
|
FolderModel folder,
|
||||||
|
WidgetRef ref,
|
||||||
|
) {
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
return await ref.refresh(FoldersProvider(folderId: 28));
|
return await ref.refresh(FoldersProvider(folderId: 28));
|
||||||
@ -60,7 +63,11 @@ class FolderView extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Container _buildListTile(
|
Container _buildListTile(
|
||||||
BuildContext context, String? title, String? subtitle, String type) {
|
BuildContext context,
|
||||||
|
String? title,
|
||||||
|
String? subtitle,
|
||||||
|
String type,
|
||||||
|
) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:Medito/constants/constants.dart';
|
import 'package:Medito/constants/constants.dart';
|
||||||
import 'package:Medito/models/models.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/audio_player/audio_player_viewmodel.dart';
|
||||||
import 'package:Medito/view_model/player/audio_position_viewmodel.dart';
|
import 'package:Medito/view_model/player/audio_position_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -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/audio_inherited_widget.dart';
|
||||||
import 'package:Medito/audioplayer/medito_audio_handler.dart';
|
import 'package:Medito/audioplayer/medito_audio_handler.dart';
|
||||||
import 'package:Medito/audioplayer/player_utils.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/api_response.dart';
|
||||||
import 'package:Medito/network/session_options/background_sounds.dart';
|
import 'package:Medito/network/session_options/background_sounds.dart';
|
||||||
import 'package:Medito/utils/bgvolume_utils.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/shared_preferences_utils.dart';
|
||||||
import 'package:Medito/utils/utils.dart';
|
import 'package:Medito/utils/utils.dart';
|
||||||
import 'package:Medito/views/player_old/components/position_indicator_widget.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 :/
|
// 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);
|
Navigator.pop(context);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +74,7 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
_volume = await retrieveSavedBgVolume();
|
_volume = await retrieveSavedBgVolume();
|
||||||
await await Future.delayed(Duration(milliseconds: 200)).then((value) {
|
await await Future.delayed(Duration(milliseconds: 200)).then((value) {
|
||||||
_handler?.customAction(SET_BG_SOUND_VOL, {SET_BG_SOUND_VOL: _volume});
|
_handler?.customAction(SET_BG_SOUND_VOL, {SET_BG_SOUND_VOL: _volume});
|
||||||
|
|
||||||
return _handler?.customAction(SEND_BG_SOUND, {SEND_BG_SOUND: bgSound});
|
return _handler?.customAction(SEND_BG_SOUND, {SEND_BG_SOUND: bgSound});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -79,94 +84,69 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
_handler = AudioHandlerInheritedWidget.of(context).audioHandler;
|
_handler = AudioHandlerInheritedWidget.of(context).audioHandler;
|
||||||
|
|
||||||
return StreamBuilder(
|
return StreamBuilder(
|
||||||
stream: Stream.fromFuture(
|
stream: Stream.fromFuture(
|
||||||
Connectivity().checkConnectivity(),
|
Connectivity().checkConnectivity(),
|
||||||
),
|
),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
if (snapshot.data == ConnectivityResult.none) {
|
if (snapshot.data == ConnectivityResult.none) {
|
||||||
_isOffline = true;
|
_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
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
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(
|
Widget _onlineBackgroundSounds(
|
||||||
String currentSound, ScrollController scrollController) {
|
String currentSound,
|
||||||
|
ScrollController scrollController,
|
||||||
|
) {
|
||||||
return StreamBuilder<ApiResponse<BackgroundSoundsResponse>>(
|
return StreamBuilder<ApiResponse<BackgroundSoundsResponse>>(
|
||||||
stream: widget.stream,
|
stream: widget.stream,
|
||||||
initialData: ApiResponse.loading(),
|
initialData: ApiResponse.loading(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
switch (snapshot.data?.status) {
|
switch (snapshot.data?.status) {
|
||||||
case Status.LOADING:
|
case Status.LOADING:
|
||||||
return Center(
|
return Center(
|
||||||
child: const CircularProgressIndicator(
|
child: const CircularProgressIndicator(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(
|
valueColor: AlwaysStoppedAnimation<Color>(
|
||||||
ColorConstants.walterWhite)));
|
ColorConstants.walterWhite,
|
||||||
case Status.COMPLETED:
|
),
|
||||||
var list = snapshot.data?.body?.data;
|
),
|
||||||
|
);
|
||||||
|
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>[
|
var widgetList = <Widget>[
|
||||||
Divider(height: 16),
|
Divider(height: 16),
|
||||||
_getHeader(),
|
_getHeader(),
|
||||||
@ -177,20 +157,57 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
];
|
];
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
widgetList.addAll(list
|
widgetList.addAll(list
|
||||||
.map((e) =>
|
.map<Widget>((e) =>
|
||||||
_getBackgroundSoundListTile(e, currentSound, context))
|
_getBackgroundSoundListTile(e, currentSound, context))
|
||||||
.toList());
|
.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView(controller: scrollController, children: widgetList);
|
return ListView(controller: scrollController, children: widgetList);
|
||||||
} else {
|
|
||||||
return Center(
|
case Status.ERROR:
|
||||||
child: const CircularProgressIndicator(
|
return _getErrorWidget();
|
||||||
backgroundColor: Colors.black,
|
case null:
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(
|
return Container();
|
||||||
ColorConstants.walterWhite)));
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
Widget _getErrorWidget() => Padding(
|
||||||
@ -217,11 +234,12 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
|
|
||||||
TextStyle? _getTheme(current, String? name) {
|
TextStyle? _getTheme(current, String? name) {
|
||||||
return Theme.of(context).textTheme.bodyText2?.copyWith(
|
return Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontWeight:
|
fontWeight:
|
||||||
_isSelected(current, name) ? FontWeight.w600 : FontWeight.normal,
|
_isSelected(current, name) ? FontWeight.w600 : FontWeight.normal,
|
||||||
color: _isSelected(current, name)
|
color: _isSelected(current, name)
|
||||||
? ColorConstants.walterWhite
|
? ColorConstants.walterWhite
|
||||||
: ColorConstants.meditoTextGrey);
|
: ColorConstants.meditoTextGrey,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getVisibilityWidget(String name, String current, Widget child) =>
|
Widget _getVisibilityWidget(String name, String current, Widget child) =>
|
||||||
@ -234,44 +252,65 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
current == name || (current == '' && name == NONE);
|
current == name || (current == '' && name == NONE);
|
||||||
|
|
||||||
Widget _getBackgroundSoundListTile(
|
Widget _getBackgroundSoundListTile(
|
||||||
BackgroundSoundData item, String current, BuildContext context) {
|
BackgroundSoundData item,
|
||||||
|
String current,
|
||||||
|
BuildContext context,
|
||||||
|
) {
|
||||||
var assetUrl = item.file?.toAssetUrl();
|
var assetUrl = item.file?.toAssetUrl();
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_downloadingItem = item.name;
|
_downloadingItem = item.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
downloadBGMusicFromURL(assetUrl, item.name).then((filePath) {
|
downloadBGMusicFromURL(assetUrl, item.name).then((filePath) {
|
||||||
if (filePath == 'Connectivity lost') {
|
if (filePath == 'Connectivity lost') {
|
||||||
_downloadingItem = '';
|
|
||||||
_isOffline = true;
|
|
||||||
setState(() {});
|
|
||||||
createSnackBar(
|
|
||||||
'Connectivity lost. Displaying offline background sounds.',
|
|
||||||
context);
|
|
||||||
_noneSelected();
|
|
||||||
}
|
|
||||||
_downloadingItem = '';
|
_downloadingItem = '';
|
||||||
addBgSoundSelectionToSharedPrefs(filePath, item.name);
|
_isOffline = true;
|
||||||
widget.handler
|
setState(() {});
|
||||||
?.customAction(PLAY_BG_SOUND, {PLAY_BG_SOUND: filePath});
|
createSnackBar(
|
||||||
return widget.handler
|
'Connectivity lost. Displaying offline background sounds.',
|
||||||
?.customAction(SEND_BG_SOUND, {SEND_BG_SOUND: item.name});
|
context,
|
||||||
});
|
);
|
||||||
},
|
_noneSelected();
|
||||||
child: ListTile(
|
}
|
||||||
enableFeedback: true,
|
_downloadingItem = '';
|
||||||
title: Text('${item.name}', style: _getTheme(current, item.name)),
|
addBgSoundSelectionToSharedPrefs(
|
||||||
trailing: _isDownloading(item)
|
filePath,
|
||||||
? _getSmallLoadingWidget()
|
item.name,
|
||||||
: _getVisibilityWidget(
|
);
|
||||||
item.name ?? '',
|
widget.handler?.customAction(
|
||||||
current,
|
PLAY_BG_SOUND,
|
||||||
Icon(
|
{PLAY_BG_SOUND: filePath},
|
||||||
Icons.check_circle_outline,
|
);
|
||||||
color: ColorConstants.walterWhite,
|
|
||||||
))));
|
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) =>
|
bool _isDownloading(BackgroundSoundData item) =>
|
||||||
@ -280,12 +319,14 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
Widget _getSmallLoadingWidget() => Padding(
|
Widget _getSmallLoadingWidget() => Padding(
|
||||||
padding: const EdgeInsets.only(right: 6.0),
|
padding: const EdgeInsets.only(right: 6.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
width: 16,
|
width: 16,
|
||||||
child: const CircularProgressIndicator(
|
child: const CircularProgressIndicator(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
valueColor:
|
valueColor:
|
||||||
AlwaysStoppedAnimation<Color>(ColorConstants.walterWhite))),
|
AlwaysStoppedAnimation<Color>(ColorConstants.walterWhite),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
void _noneSelected() {
|
void _noneSelected() {
|
||||||
@ -297,11 +338,12 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
|
|
||||||
Widget _getHeader() {
|
Widget _getHeader() {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 8.0, left: 16.0, top: 8.0),
|
padding: const EdgeInsets.only(bottom: 8.0, left: 16.0, top: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
StringConstants.BACKGROUND_SOUNDS,
|
StringConstants.BACKGROUND_SOUNDS,
|
||||||
style: Theme.of(context).textTheme.headline1,
|
style: Theme.of(context).textTheme.headline1,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getVolumeWidget() {
|
Widget _getVolumeWidget() {
|
||||||
@ -310,45 +352,49 @@ class _ChooseBackgroundSoundDialogState
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
child: StreamBuilder<Object>(
|
child: StreamBuilder<Object>(
|
||||||
stream: _dragBgVolumeSubject,
|
stream: _dragBgVolumeSubject,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
var volume = _dragBgVolumeSubject.value;
|
var volume = _dragBgVolumeSubject.value;
|
||||||
var volumeIcon = _volumeIconFunction(volume);
|
var volumeIcon = _volumeIconFunction(volume);
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
return Row(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
Icon(volumeIcon, size: 24, color: ColorConstants.walterWhite),
|
children: [
|
||||||
Expanded(
|
Icon(volumeIcon, size: 24, color: ColorConstants.walterWhite),
|
||||||
child: Padding(
|
Expanded(
|
||||||
padding: const EdgeInsets.only(left: 24.0, right: 4),
|
child: Padding(
|
||||||
child: SliderTheme(
|
padding: const EdgeInsets.only(left: 24.0, right: 4),
|
||||||
data: SliderThemeData(
|
child: SliderTheme(
|
||||||
trackShape: CustomTrackShape(addTopPadding: false),
|
data: SliderThemeData(
|
||||||
thumbShape:
|
trackShape: CustomTrackShape(addTopPadding: false),
|
||||||
RoundSliderThumbShape(enabledThumbRadius: 10.0),
|
thumbShape:
|
||||||
),
|
RoundSliderThumbShape(enabledThumbRadius: 10.0),
|
||||||
child: Slider(
|
),
|
||||||
min: 0.0,
|
child: Slider(
|
||||||
activeColor: ColorConstants.walterWhite,
|
min: 0.0,
|
||||||
inactiveColor:
|
activeColor: ColorConstants.walterWhite,
|
||||||
ColorConstants.walterWhite.withOpacity(0.7),
|
inactiveColor:
|
||||||
max: 1.0,
|
ColorConstants.walterWhite.withOpacity(0.7),
|
||||||
value: volume,
|
max: 1.0,
|
||||||
onChanged: (value) {
|
value: volume,
|
||||||
_dragBgVolumeSubject.add(value);
|
onChanged: (value) {
|
||||||
_handler?.customAction(
|
_dragBgVolumeSubject.add(value);
|
||||||
SET_BG_SOUND_VOL, {SET_BG_SOUND_VOL: value});
|
_handler?.customAction(
|
||||||
},
|
SET_BG_SOUND_VOL,
|
||||||
onChangeEnd: (value) {
|
{SET_BG_SOUND_VOL: value},
|
||||||
saveBgVolume(value);
|
);
|
||||||
},
|
},
|
||||||
),
|
onChangeEnd: (value) {
|
||||||
|
saveBgVolume(value);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
);
|
],
|
||||||
}),
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import 'dart:math';
|
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/audioplayer/medito_audio_handler.dart';
|
||||||
import 'package:Medito/network/player/player_bloc.dart';
|
|
||||||
import 'package:Medito/constants/constants.dart';
|
import 'package:Medito/constants/constants.dart';
|
||||||
import 'package:Medito/utils/duration_ext.dart';
|
|
||||||
import 'package:Medito/routes/routes.dart';
|
import 'package:Medito/routes/routes.dart';
|
||||||
|
import 'package:Medito/utils/duration_extensions.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
import 'background_sounds_sheet_widget.dart';
|
|
||||||
|
|
||||||
class PositionIndicatorWidget extends StatefulWidget {
|
class PositionIndicatorWidget extends StatefulWidget {
|
||||||
final MeditoAudioHandler? handler;
|
final MeditoAudioHandler? handler;
|
||||||
|
@ -15,11 +15,11 @@ along with Medito App. If not, see <https://www.gnu.org/licenses/>.*/
|
|||||||
|
|
||||||
import 'dart:async';
|
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/audioplayer/medito_audio_handler.dart';
|
||||||
import 'package:Medito/components/components.dart';
|
import 'package:Medito/components/components.dart';
|
||||||
import 'package:Medito/network/player/player_bloc.dart';
|
|
||||||
import 'package:Medito/constants/constants.dart';
|
import 'package:Medito/constants/constants.dart';
|
||||||
|
import 'package:Medito/network/player/player_bloc.dart';
|
||||||
import 'package:Medito/routes/routes.dart';
|
import 'package:Medito/routes/routes.dart';
|
||||||
import 'package:Medito/utils/shared_preferences_utils.dart';
|
import 'package:Medito/utils/shared_preferences_utils.dart';
|
||||||
import 'package:Medito/utils/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/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||||
|
|
||||||
import '../../../audioplayer/audio_inherited_widget.dart';
|
import '../../../audioplayer/audio_inherited_widget.dart';
|
||||||
import '../../../tracking/tracking.dart';
|
import '../../../tracking/tracking.dart';
|
||||||
import '../../../utils/bgvolume_utils.dart';
|
import '../../../utils/bgvolume_utils.dart';
|
||||||
@ -93,13 +94,16 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
|||||||
event[AUDIO_COMPLETE] == true) {
|
event[AUDIO_COMPLETE] == true) {
|
||||||
_trackSessionEnd(_handler?.mediaItem.value);
|
_trackSessionEnd(_handler?.mediaItem.value);
|
||||||
showGeneralDialog(
|
showGeneralDialog(
|
||||||
transitionDuration: Duration(milliseconds: 400),
|
transitionDuration: Duration(milliseconds: 400),
|
||||||
context: context,
|
context: context,
|
||||||
barrierColor: ColorConstants.darkMoon,
|
barrierColor: ColorConstants.darkMoon,
|
||||||
pageBuilder: (_, __, ___) {
|
pageBuilder: (_, __, ___) {
|
||||||
return AudioCompleteDialog(
|
return AudioCompleteDialog(
|
||||||
bloc: _bloc, mediaItem: _handler?.mediaItem.value);
|
bloc: _bloc,
|
||||||
});
|
mediaItem: _handler?.mediaItem.value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,8 +116,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
|||||||
image: getNetworkImage(mediaItem?.artUri?.toString() ?? ''),
|
image: getNetworkImage(mediaItem?.artUri?.toString() ?? ''),
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.fill,
|
||||||
colorFilter: ColorFilter.mode(
|
colorFilter: ColorFilter.mode(
|
||||||
ColorConstants.almostBlack.withOpacity(0.65),
|
ColorConstants.almostBlack.withOpacity(0.65),
|
||||||
BlendMode.overlay),
|
BlendMode.overlay,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
@ -131,8 +136,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
|||||||
_buildPlayerButtonRow(mediaItem),
|
_buildPlayerButtonRow(mediaItem),
|
||||||
// A seek bar.
|
// A seek bar.
|
||||||
PositionIndicatorWidget(
|
PositionIndicatorWidget(
|
||||||
handler: _handler,
|
handler: _handler,
|
||||||
bgSoundsStream: _bloc.bgSoundsListController?.stream),
|
bgSoundsStream: _bloc.bgSoundsListController?.stream,
|
||||||
|
),
|
||||||
Container(height: 24),
|
Container(height: 24),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -149,12 +155,14 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
|||||||
getSavedBgSoundData();
|
getSavedBgSoundData();
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e, s) {
|
||||||
unawaited(Sentry.captureException(e,
|
unawaited(Sentry.captureException(
|
||||||
stackTrace: s,
|
e,
|
||||||
hint: Hint.withMap({
|
stackTrace: s,
|
||||||
'message':
|
hint: Hint.withMap({
|
||||||
'Failed trying to get save background sounds data: extras[HAS_BG_SOUND]: ${_hasBGSound()}'
|
'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) {
|
Padding _getSubtitleWidget(MediaItem? mediaItem) {
|
||||||
var attr = mediaItem?.extras != null ? (mediaItem?.extras?['attr']) : '';
|
var attr = mediaItem?.extras != null ? (mediaItem?.extras?['attr']) : '';
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: MarkdownComponent(
|
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_ID: mediaItem.extras?[SESSION_ID].toString() ?? '',
|
||||||
Tracking.SESSION_DURATION: mediaItem.extras?[LENGTH].toString() ?? '',
|
Tracking.SESSION_DURATION: mediaItem.extras?[LENGTH].toString() ?? '',
|
||||||
Tracking.SESSION_GUIDE: mediaItem.artist ?? ''
|
Tracking.SESSION_GUIDE: mediaItem.artist ?? '',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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
|
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/>.*/
|
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/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/utils/utils.dart';
|
||||||
import 'package:Medito/views/main/app_bar_widget.dart';
|
import 'package:Medito/views/main/app_bar_widget.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -62,14 +61,15 @@ class _TextFileWidgetState extends State<TextFileWidget>
|
|||||||
appBar: PreferredSize(
|
appBar: PreferredSize(
|
||||||
preferredSize: const Size(double.infinity, kToolbarHeight),
|
preferredSize: const Size(double.infinity, kToolbarHeight),
|
||||||
child: StreamBuilder<String>(
|
child: StreamBuilder<String>(
|
||||||
stream: _bloc.titleController.stream,
|
stream: _bloc.titleController.stream,
|
||||||
initialData: '...',
|
initialData: '...',
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return MeditoAppBarWidget(
|
return MeditoAppBarWidget(
|
||||||
isTransparent: true,
|
isTransparent: true,
|
||||||
title: snapshot.data ?? '',
|
title: snapshot.data ?? '',
|
||||||
);
|
);
|
||||||
}), // StreamBuilder
|
},
|
||||||
|
), // StreamBuilder
|
||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () => _bloc.fetchText(widget.id, true),
|
onRefresh: () => _bloc.fetchText(widget.id, true),
|
||||||
@ -105,32 +105,43 @@ class _TextFileWidgetState extends State<TextFileWidget>
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
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>(
|
child: StreamBuilder<String>(
|
||||||
stream: _bloc.bodyController.stream,
|
stream: _bloc.bodyController.stream,
|
||||||
initialData: 'Loading...',
|
initialData: 'Loading...',
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return Markdown(
|
return Markdown(
|
||||||
data: snapshot.data ?? '',
|
data: snapshot.data ?? '',
|
||||||
onTapLink: _linkTap,
|
onTapLink: _linkTap,
|
||||||
physics: NeverScrollableScrollPhysics(),
|
physics: NeverScrollableScrollPhysics(),
|
||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
styleSheet: buildMarkdownStyleSheet(context).copyWith(
|
styleSheet: buildMarkdownStyleSheet(context).copyWith(
|
||||||
horizontalRuleDecoration: BoxDecoration(
|
horizontalRuleDecoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
top: BorderSide(
|
top: BorderSide(
|
||||||
width: 1.0,
|
width: 1.0,
|
||||||
color: ColorConstants.meditoTextGrey,
|
color: ColorConstants.meditoTextGrey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
h2: TextStyle(
|
h2: TextStyle(
|
||||||
color: ColorConstants.walterWhite, height: 1.5),
|
color: ColorConstants.walterWhite,
|
||||||
p: TextStyle(
|
height: 1.5,
|
||||||
color: ColorConstants.walterWhite, height: 1.5)));
|
),
|
||||||
}),
|
p: TextStyle(
|
||||||
|
color: ColorConstants.walterWhite,
|
||||||
|
height: 1.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -36,11 +36,12 @@ void main() {
|
|||||||
isPublished: true,
|
isPublished: true,
|
||||||
items: [
|
items: [
|
||||||
FolderItemsModel(
|
FolderItemsModel(
|
||||||
type: 'session',
|
type: 'session',
|
||||||
id: 120,
|
id: 120,
|
||||||
title: 'Complete meditation',
|
title: 'Complete meditation',
|
||||||
subtitle: '19 min',
|
subtitle: '19 min',
|
||||||
path: 'sessions/120')
|
path: 'sessions/120',
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
final mockFolderRepository = MockFolderRepository();
|
final mockFolderRepository = MockFolderRepository();
|
||||||
|
Loading…
Reference in New Issue
Block a user