diff --git a/assets/images/unmusic.svg b/assets/images/unmusic.svg
new file mode 100644
index 0000000..fca9700
--- /dev/null
+++ b/assets/images/unmusic.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart
index 33e746f..23d84bb 100644
--- a/lib/common_ui/resources/my_assets.dart
+++ b/lib/common_ui/resources/my_assets.dart
@@ -45,4 +45,5 @@ class MyAssets {
static const String diamondBig = 'assets/images/diamond_big.png';
static const String ship = 'assets/images/ship.png';
static const String shiny = 'assets/images/shiny.png';
+ static const String unMusic = 'assets/images/unmusic.svg';
}
\ No newline at end of file
diff --git a/lib/core/routers/my_routes.dart b/lib/core/routers/my_routes.dart
index a4cf4a9..0f9ef04 100644
--- a/lib/core/routers/my_routes.dart
+++ b/lib/core/routers/my_routes.dart
@@ -63,7 +63,7 @@ GoRouter get appPages => GoRouter(
name: Routes.homePage,
path: Routes.homePage,
builder: (context, state) => BlocProvider(
- create: (context) => HomeBloc(),
+ create: (context) => HomeBloc(locator()),
child: const HomePage(),
),
),
@@ -71,7 +71,7 @@ GoRouter get appPages => GoRouter(
name: Routes.levelPage,
path: Routes.levelPage,
builder: (context, state) => BlocProvider(
- create: (context) => LevelBloc(locator())..add(SetCurrentLevelEvent()),
+ create: (context) => LevelBloc(locator(), locator())..add(SetCurrentLevelEvent()),
child: const LevelPage(),
),
),
@@ -80,7 +80,7 @@ GoRouter get appPages => GoRouter(
path: '${Routes.questionPage}/:id',
builder: (context, state) => BlocProvider(
create: (context) =>
- QuestionBloc(locator(), locator())
+ QuestionBloc(locator(), locator(), locator())
..add(GetLevelEvent(state.pathParameters['id'])),
child: const QuestionPage(),
),
diff --git a/lib/core/services/audio_service.dart b/lib/core/services/audio_service.dart
new file mode 100644
index 0000000..9670981
--- /dev/null
+++ b/lib/core/services/audio_service.dart
@@ -0,0 +1,81 @@
+import 'package:flutter/foundation.dart';
+import 'package:just_audio/just_audio.dart';
+
+class AudioService {
+ final AudioPlayer _player = AudioPlayer();
+
+ Future setAudio({String? filePath}) async {
+ try {
+ return _player.setAudioSource(AudioSource.file(filePath ?? ''));
+ } catch (e) {
+ if (kDebugMode) {
+ print('$e');
+ }
+ return Duration.zero;
+ }
+ }
+
+ Future play() async {
+ try {
+ return _player.play();
+ } catch (e) {
+ if (kDebugMode) {
+ print('$e');
+ }
+ }
+ }
+
+ Future pause() async {
+ try {
+ return _player.pause();
+ } catch (e) {
+ if (kDebugMode) {
+ print('$e');
+ }
+ }
+ }
+
+ Future stop() async {
+ try {
+ return _player.stop();
+ } catch (e) {
+ if (kDebugMode) {
+ print('$e');
+ }
+ }
+ }
+
+ Future dispose() async {
+ try {
+ return _player.dispose();
+ } catch (e) {
+ if (kDebugMode) {
+ print('$e');
+ }
+ }
+ }
+
+ Future changeMute() async {
+ try {
+ if (_player.volume == 0) {
+ await _player.setVolume(1);
+ } else {
+ await _player.setVolume(0);
+ }
+ } catch (e) {
+ if (kDebugMode) {
+ print('$e');
+ }
+ }
+ }
+
+ Stream volumeStream() async* {
+ try {
+ yield* _player.volumeStream;
+ } catch (e) {
+ if (kDebugMode) {
+ print('$e');
+ }
+ }
+ }
+}
diff --git a/lib/features/home/presentation/bloc/home_bloc.dart b/lib/features/home/presentation/bloc/home_bloc.dart
index c9c59a8..1ba9839 100644
--- a/lib/features/home/presentation/bloc/home_bloc.dart
+++ b/lib/features/home/presentation/bloc/home_bloc.dart
@@ -4,21 +4,27 @@ import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
+import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/core/widgets/about_us_dialog/about_us_dialog.dart';
import 'package:hadi_hoda_flutter/features/home/presentation/bloc/home_event.dart';
import 'package:hadi_hoda_flutter/features/home/presentation/bloc/home_state.dart';
class HomeBloc extends Bloc {
/// ------------constructor------------
- HomeBloc() : super(const HomeState()) {
+ HomeBloc(
+ this._audioService,
+ ) : super(const HomeState()) {
+ volumeStream = _audioService.volumeStream();
on(_getHomeEvent);
}
/// ------------UseCases------------
/// ------------Variables------------
+ late final Stream volumeStream;
/// ------------Controllers------------
+ final AudioService _audioService;
/// ------------Functions------------
void goToLevelPage(BuildContext context){
@@ -33,6 +39,9 @@ class HomeBloc extends Bloc {
showAboutUsDialog(context: context);
}
+ Future changeMute() async {
+ await _audioService.changeMute();
+ }
/// ------------Api Calls------------
FutureOr _getHomeEvent(event, emit) async {}
}
diff --git a/lib/features/home/presentation/ui/home_page.dart b/lib/features/home/presentation/ui/home_page.dart
index 3234e84..2905c4f 100644
--- a/lib/features/home/presentation/ui/home_page.dart
+++ b/lib/features/home/presentation/ui/home_page.dart
@@ -1,8 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
-import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart';
-import 'package:hadi_hoda_flutter/core/utils/check_platform.dart';
+import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart';
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart';
@@ -16,7 +15,6 @@ class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
- appBar: AppBar(backgroundColor: MyColors.transparent),
extendBodyBehindAppBar: true,
body: DecoratedBox(
decoration: BoxDecoration(
@@ -41,13 +39,19 @@ class HomePage extends StatelessWidget {
);
}
- Positioned _music(BuildContext context) {
- return Positioned(
- top: checkSize(context: context, mobile: 36, tablet: 60),
- right: checkSize(context: context, mobile: 16, tablet: 30),
- child: MyImage(
- image: MyAssets.musicOn,
- size: checkSize(context: context, tablet: 120),
+ Widget _music(BuildContext context) {
+ return PositionedDirectional(
+ top: MediaQuery.viewPaddingOf(context).top + MySpaces.s16,
+ end: MySpaces.s16,
+ child: StreamBuilder(
+ initialData: 1,
+ stream: context.read().volumeStream,
+ builder: (context, snapshot) => InkWell(
+ onTap: () => context.read().changeMute(),
+ child: MyImage(
+ image: snapshot.data == 1 ? MyAssets.musicOn : MyAssets.musicOff,
+ ),
+ ),
),
);
}
@@ -58,7 +62,7 @@ class HomePage extends StatelessWidget {
top: 146,
child: MyImage(
image: MyAssets.hadiHoda,
- size: checkSize(context: context, mobile: 232, tablet: 400),
+ size: 232,
fit: BoxFit.cover,
),
);
@@ -66,9 +70,9 @@ class HomePage extends StatelessWidget {
Positioned _bottomBtns(BuildContext context) {
return Positioned(
- bottom: checkSize(context: context, mobile: 40, tablet: 60),
- left: checkSize(context: context, mobile: 16, tablet: 30),
- right: checkSize(context: context, mobile: 16, tablet: 30),
+ bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16,
+ left: MySpaces.s16,
+ right: MySpaces.s16,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -77,7 +81,6 @@ class HomePage extends StatelessWidget {
onTap: () => context.read().goToLanguagePage(context),
child: MyImage(
image: MyAssets.language,
- size: checkSize(context: context, tablet: 120),
),
),
MyButton(
@@ -89,7 +92,6 @@ class HomePage extends StatelessWidget {
onTap: () => context.read().showAboutUs(context),
child: MyImage(
image: MyAssets.theme,
- size: checkSize(context: context, tablet: 120),
),
),
],
diff --git a/lib/features/level/presentation/bloc/level_bloc.dart b/lib/features/level/presentation/bloc/level_bloc.dart
index 36e8d40..23b2d8c 100644
--- a/lib/features/level/presentation/bloc/level_bloc.dart
+++ b/lib/features/level/presentation/bloc/level_bloc.dart
@@ -6,6 +6,7 @@ import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/params/level_params.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
+import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart';
@@ -19,7 +20,9 @@ class LevelBloc extends Bloc {
/// ------------constructor------------
LevelBloc(
this._getLeveslUseCase,
+ this._audioService,
) : super(const LevelState()) {
+ volumeStream = _audioService.volumeStream();
on(_getLevelListEvent);
on(_setCurrentLevelEvent);
on(_startScrollEvent);
@@ -64,9 +67,13 @@ class LevelBloc extends Bloc {
final List bottom8LevelList = [];
final List top12LevelList = [];
+ late final Stream volumeStream;
+
+
/// ------------Controllers------------
final ScrollController scrollController = ScrollController();
+ final AudioService _audioService;
/// ------------Functions------------
void goToQuestionPage(BuildContext context, LevelEntity level){
@@ -96,6 +103,10 @@ class LevelBloc extends Bloc {
}
}
+ Future changeMute() async {
+ await _audioService.changeMute();
+ }
+
/// ------------Api Calls------------
FutureOr _getLevelListEvent(GetLevelListEvent event,
Emitter emit) async {
diff --git a/lib/features/level/presentation/ui/level_page.dart b/lib/features/level/presentation/ui/level_page.dart
index fd6c9ab..08d8fff 100644
--- a/lib/features/level/presentation/ui/level_page.dart
+++ b/lib/features/level/presentation/ui/level_page.dart
@@ -67,7 +67,7 @@ class LevelPage extends StatelessWidget {
return Positioned(
left: MySpaces.s16,
right: MySpaces.s16,
- top: MediaQuery.viewPaddingOf(context).top,
+ top: MediaQuery.viewPaddingOf(context).top + MySpaces.s16,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -77,8 +77,15 @@ class LevelPage extends StatelessWidget {
image: MyAssets.homeButton,
),
),
- MyImage(
- image: MyAssets.musicOn,
+ StreamBuilder(
+ initialData: 1,
+ stream: context.read().volumeStream,
+ builder: (context, snapshot) => InkWell(
+ onTap: () => context.read().changeMute(),
+ child: MyImage(
+ image: snapshot.data == 1 ? MyAssets.musicOn : MyAssets.musicOff,
+ ),
+ ),
),
],
),
diff --git a/lib/features/question/presentation/bloc/question_bloc.dart b/lib/features/question/presentation/bloc/question_bloc.dart
index 5c0a87f..e33c3bb 100644
--- a/lib/features/question/presentation/bloc/question_bloc.dart
+++ b/lib/features/question/presentation/bloc/question_bloc.dart
@@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/params/question_params.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
+import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart';
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart';
@@ -24,7 +25,9 @@ class QuestionBloc extends Bloc {
QuestionBloc(
this._getLevelUseCase,
this._getNextLevelUseCase,
+ this._audioService,
) : super(QuestionState()) {
+ volumeStream = _audioService.volumeStream();
on(_getLevelEvent);
on(_chooseAnswerEvent);
on(_getNextLevelEvent);
@@ -47,9 +50,10 @@ class QuestionBloc extends Bloc {
GlobalKey(),
GlobalKey(),
];
-
+ late final Stream volumeStream;
/// ------------Controllers------------
+ final AudioService _audioService;
final ConfettiController confettiController = ConfettiController(
duration: Duration(seconds: 1),
);
@@ -67,6 +71,15 @@ class QuestionBloc extends Bloc {
context.pushReplacement(Routes.levelPage);
}
+ Future playVoice() async {
+ await _audioService.setAudio(filePath: state.currentQuestion?.audio);
+ await _audioService.play();
+ }
+
+ Future changeMute() async {
+ await _audioService.changeMute();
+ }
+
/// ------------Event Calls------------
FutureOr _getLevelEvent(GetLevelEvent event, Emitter emit) async {
await _getLevelUseCase(QuestionParams(id: int.parse(event.id ?? '0'))).then(
@@ -87,6 +100,7 @@ class QuestionBloc extends Bloc {
levelEntity: level,
currentQuestion: data.questions?.first,
));
+ playVoice();
},
(error) {
emit(state.copyWith(getQuestionStatus: BaseError(error.errorMessage)));
@@ -119,6 +133,8 @@ class QuestionBloc extends Bloc {
key: MyConstants.currentLevel,
value: '$currentLevel',
);
+ } else {
+ await playVoice();
}
});
}
diff --git a/lib/features/question/presentation/ui/question_page.dart b/lib/features/question/presentation/ui/question_page.dart
index 9a7912b..70efad9 100644
--- a/lib/features/question/presentation/ui/question_page.dart
+++ b/lib/features/question/presentation/ui/question_page.dart
@@ -105,7 +105,14 @@ class QuestionPage extends StatelessWidget {
onTap: () => context.read().showHadith(context: context),
),
MySpaces.s10.gapWidth,
- GlassyButton(image: MyAssets.music, onTap: () {}),
+ StreamBuilder(
+ initialData: 1,
+ stream: context.read().volumeStream,
+ builder: (context, snapshot) => GlassyButton(
+ image: snapshot.data == 1 ? MyAssets.music : MyAssets.unMusic,
+ onTap: () => context.read().changeMute(),
+ ),
+ ),
],
);
}
diff --git a/lib/features/question/presentation/ui/widgets/glassy_button.dart b/lib/features/question/presentation/ui/widgets/glassy_button.dart
index e346f4d..b3beb7b 100644
--- a/lib/features/question/presentation/ui/widgets/glassy_button.dart
+++ b/lib/features/question/presentation/ui/widgets/glassy_button.dart
@@ -32,7 +32,7 @@ class GlassyButton extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(
padding: const EdgeInsets.all(MySpaces.s12),
- child: MyImage(image: image),
+ child: MyImage(image: image, size: MySpaces.s22),
),
),
),
diff --git a/lib/init_bindings.dart b/lib/init_bindings.dart
index 84d2bfb..4741241 100644
--- a/lib/init_bindings.dart
+++ b/lib/init_bindings.dart
@@ -4,6 +4,7 @@ import 'package:get_it/get_it.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/network/http_request.dart';
import 'package:hadi_hoda_flutter/core/network/http_request_impl.dart';
+import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/features/download/data/datasource/download_datasource.dart';
import 'package:hadi_hoda_flutter/features/download/data/repository_impl/download_repository_impl.dart';
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart';
@@ -41,6 +42,7 @@ final GetIt locator = GetIt.I;
void initBindings() {
/// Classes
locator.registerSingleton(HttpRequestImpl());
+ locator.registerSingleton(AudioService());
/// Sample Feature
locator.registerLazySingleton(() => SampleDatasourceImpl(locator()));
diff --git a/pubspec.lock b/pubspec.lock
index b77f400..1b61d45 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -41,6 +41,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.13.0"
+ audio_session:
+ dependency: transitive
+ description:
+ name: audio_session
+ sha256: "8f96a7fecbb718cb093070f868b4cdcb8a9b1053dce342ff8ab2fde10eb9afb7"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.2"
bloc:
dependency: "direct main"
description:
@@ -421,6 +429,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.9.0"
+ just_audio:
+ dependency: "direct main"
+ description:
+ name: just_audio
+ sha256: "9694e4734f515f2a052493d1d7e0d6de219ee0427c7c29492e246ff32a219908"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.5"
+ just_audio_platform_interface:
+ dependency: transitive
+ description:
+ name: just_audio_platform_interface
+ sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.6.0"
+ just_audio_web:
+ dependency: transitive
+ description:
+ name: just_audio_web
+ sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.4.16"
leak_tracker:
dependency: transitive
description:
@@ -661,6 +693,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.0"
+ rxdart:
+ dependency: transitive
+ description:
+ name: rxdart
+ sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.28.0"
shared_preferences:
dependency: "direct main"
description:
@@ -770,6 +810,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.1"
+ sprintf:
+ dependency: transitive
+ description:
+ name: sprintf
+ sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
stack_trace:
dependency: transitive
description:
@@ -802,6 +850,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.1"
+ synchronized:
+ dependency: transitive
+ description:
+ name: synchronized
+ sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.4.0"
term_glyph:
dependency: transitive
description:
@@ -834,6 +890,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.0"
+ uuid:
+ dependency: transitive
+ description:
+ name: uuid
+ sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.5.1"
vector_graphics:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 8f6a09e..84f89c0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -23,6 +23,7 @@ dependencies:
go_router: ^16.1.0
hive: ^2.2.3
intl: ^0.20.2
+ just_audio: ^0.10.5
path_drawing: ^1.0.1
path_provider: ^2.1.5
pretty_dio_logger: ^1.4.0