Browse Source

add: play music and audio service and fix padding

pull/18/head
AmirrezaChegini 3 weeks ago
parent
commit
bb3cffd351
  1. 4
      assets/images/unmusic.svg
  2. 1
      lib/common_ui/resources/my_assets.dart
  3. 6
      lib/core/routers/my_routes.dart
  4. 81
      lib/core/services/audio_service.dart
  5. 11
      lib/features/home/presentation/bloc/home_bloc.dart
  6. 34
      lib/features/home/presentation/ui/home_page.dart
  7. 11
      lib/features/level/presentation/bloc/level_bloc.dart
  8. 13
      lib/features/level/presentation/ui/level_page.dart
  9. 18
      lib/features/question/presentation/bloc/question_bloc.dart
  10. 9
      lib/features/question/presentation/ui/question_page.dart
  11. 2
      lib/features/question/presentation/ui/widgets/glassy_button.dart
  12. 2
      lib/init_bindings.dart
  13. 64
      pubspec.lock
  14. 1
      pubspec.yaml

4
assets/images/unmusic.svg

@ -0,0 +1,4 @@
<svg width="25" height="26" viewBox="0 0 25 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.2388 2.93567C19.6559 2.86189 20.0869 2.92457 20.4624 3.11438C20.6268 3.19751 20.7749 3.30445 20.9058 3.42786L14.8003 10.6486L9.06885 11.6505V17.4279L5.28369 21.9034C4.89628 21.9358 4.50419 21.9177 4.11865 21.8439C3.31513 21.69 2.57688 21.3098 1.99756 20.7521C1.41823 20.1943 1.02361 19.4838 0.86377 18.7101C0.703931 17.9364 0.785586 17.1342 1.09912 16.4054C1.41265 15.6767 1.94341 15.0536 2.62451 14.6154C3.30572 14.1771 4.10699 13.9435 4.92627 13.9435C5.87728 13.9453 6.79857 14.2623 7.53564 14.8409V7.45227C7.52417 6.76299 7.7665 6.09178 8.21924 5.55774C8.6832 5.03604 9.32023 4.68401 10.022 4.56067L19.2388 2.93567ZM21.4653 16.8654C21.4635 17.7688 21.1426 18.6454 20.5562 19.3507C19.9697 20.0558 19.1519 20.5488 18.2368 20.7482C17.3215 20.9475 16.3628 20.841 15.5181 20.4474C14.6735 20.0538 13.9929 19.3959 13.5874 18.5812C13.2766 17.9567 13.1423 17.2688 13.1909 16.5851L16.2056 13.0197C16.5695 12.9214 16.9474 12.8686 17.3306 12.8693C18.269 12.871 19.179 13.1795 19.9116 13.7443V9.75598L18.8013 9.94934L21.4653 6.79895V16.8654Z" fill="#E4E3F7"/>
<rect x="22.1079" y="0.460083" width="2.60346" height="30.3502" transform="rotate(40.2151 22.1079 0.460083)" fill="#E4E3F7"/>
</svg>

1
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';
}

6
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(),
),

81
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<Duration?> setAudio({String? filePath}) async {
try {
return _player.setAudioSource(AudioSource.file(filePath ?? ''));
} catch (e) {
if (kDebugMode) {
print('$e');
}
return Duration.zero;
}
}
Future<void> play() async {
try {
return _player.play();
} catch (e) {
if (kDebugMode) {
print('$e');
}
}
}
Future<void> pause() async {
try {
return _player.pause();
} catch (e) {
if (kDebugMode) {
print('$e');
}
}
}
Future<void> stop() async {
try {
return _player.stop();
} catch (e) {
if (kDebugMode) {
print('$e');
}
}
}
Future<void> dispose() async {
try {
return _player.dispose();
} catch (e) {
if (kDebugMode) {
print('$e');
}
}
}
Future<void> changeMute() async {
try {
if (_player.volume == 0) {
await _player.setVolume(1);
} else {
await _player.setVolume(0);
}
} catch (e) {
if (kDebugMode) {
print('$e');
}
}
}
Stream<double> volumeStream() async* {
try {
yield* _player.volumeStream;
} catch (e) {
if (kDebugMode) {
print('$e');
}
}
}
}

11
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<HomeEvent, HomeState> {
/// ------------constructor------------
HomeBloc() : super(const HomeState()) {
HomeBloc(
this._audioService,
) : super(const HomeState()) {
volumeStream = _audioService.volumeStream();
on<GetHomeEvent>(_getHomeEvent);
}
/// ------------UseCases------------
/// ------------Variables------------
late final Stream<double> volumeStream;
/// ------------Controllers------------
final AudioService _audioService;
/// ------------Functions------------
void goToLevelPage(BuildContext context){
@ -33,6 +39,9 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
showAboutUsDialog(context: context);
}
Future<void> changeMute() async {
await _audioService.changeMute();
}
/// ------------Api Calls------------
FutureOr<void> _getHomeEvent(event, emit) async {}
}

34
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<double>(
initialData: 1,
stream: context.read<HomeBloc>().volumeStream,
builder: (context, snapshot) => InkWell(
onTap: () => context.read<HomeBloc>().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<HomeBloc>().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<HomeBloc>().showAboutUs(context),
child: MyImage(
image: MyAssets.theme,
size: checkSize(context: context, tablet: 120),
),
),
],

11
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<LevelEvent, LevelState> {
/// ------------constructor------------
LevelBloc(
this._getLeveslUseCase,
this._audioService,
) : super(const LevelState()) {
volumeStream = _audioService.volumeStream();
on<GetLevelListEvent>(_getLevelListEvent);
on<SetCurrentLevelEvent>(_setCurrentLevelEvent);
on<StartScrollEvent>(_startScrollEvent);
@ -64,9 +67,13 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
final List<LevelEntity> bottom8LevelList = [];
final List<LevelEntity> top12LevelList = [];
late final Stream<double> volumeStream;
/// ------------Controllers------------
final ScrollController scrollController = ScrollController();
final AudioService _audioService;
/// ------------Functions------------
void goToQuestionPage(BuildContext context, LevelEntity level){
@ -96,6 +103,10 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
}
}
Future<void> changeMute() async {
await _audioService.changeMute();
}
/// ------------Api Calls------------
FutureOr<void> _getLevelListEvent(GetLevelListEvent event,
Emitter<LevelState> emit) async {

13
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<double>(
initialData: 1,
stream: context.read<LevelBloc>().volumeStream,
builder: (context, snapshot) => InkWell(
onTap: () => context.read<LevelBloc>().changeMute(),
child: MyImage(
image: snapshot.data == 1 ? MyAssets.musicOn : MyAssets.musicOff,
),
),
),
],
),

18
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<QuestionEvent, QuestionState> {
QuestionBloc(
this._getLevelUseCase,
this._getNextLevelUseCase,
this._audioService,
) : super(QuestionState()) {
volumeStream = _audioService.volumeStream();
on<GetLevelEvent>(_getLevelEvent);
on<ChooseAnswerEvent>(_chooseAnswerEvent);
on<GetNextLevelEvent>(_getNextLevelEvent);
@ -47,9 +50,10 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
GlobalKey(),
GlobalKey(),
];
late final Stream<double> volumeStream;
/// ------------Controllers------------
final AudioService _audioService;
final ConfettiController confettiController = ConfettiController(
duration: Duration(seconds: 1),
);
@ -67,6 +71,15 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
context.pushReplacement(Routes.levelPage);
}
Future<void> playVoice() async {
await _audioService.setAudio(filePath: state.currentQuestion?.audio);
await _audioService.play();
}
Future<void> changeMute() async {
await _audioService.changeMute();
}
/// ------------Event Calls------------
FutureOr<void> _getLevelEvent(GetLevelEvent event, Emitter<QuestionState> emit) async {
await _getLevelUseCase(QuestionParams(id: int.parse(event.id ?? '0'))).then(
@ -87,6 +100,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
levelEntity: level,
currentQuestion: data.questions?.first,
));
playVoice();
},
(error) {
emit(state.copyWith(getQuestionStatus: BaseError(error.errorMessage)));
@ -119,6 +133,8 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
key: MyConstants.currentLevel,
value: '$currentLevel',
);
} else {
await playVoice();
}
});
}

9
lib/features/question/presentation/ui/question_page.dart

@ -105,7 +105,14 @@ class QuestionPage extends StatelessWidget {
onTap: () => context.read<QuestionBloc>().showHadith(context: context),
),
MySpaces.s10.gapWidth,
GlassyButton(image: MyAssets.music, onTap: () {}),
StreamBuilder<double>(
initialData: 1,
stream: context.read<QuestionBloc>().volumeStream,
builder: (context, snapshot) => GlassyButton(
image: snapshot.data == 1 ? MyAssets.music : MyAssets.unMusic,
onTap: () => context.read<QuestionBloc>().changeMute(),
),
),
],
);
}

2
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),
),
),
),

2
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<IHttpRequest>(HttpRequestImpl());
locator.registerSingleton<AudioService>(AudioService());
/// Sample Feature
locator.registerLazySingleton<ISampleDatasource>(() => SampleDatasourceImpl(locator()));

64
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:

1
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

Loading…
Cancel
Save