diff --git a/lib/main/adapter/gateway/installation_api_service.dart b/lib/main/adapter/gateway/installation_api_service.dart new file mode 100644 index 0000000..9f8d547 --- /dev/null +++ b/lib/main/adapter/gateway/installation_api_service.dart @@ -0,0 +1,7 @@ +import 'dart:typed_data'; + +import 'package:minecraft_server_installer/main/application/repository/installation_repository.dart'; + +abstract interface class InstallationApiService { + Future fetchRemoteFile(Uri url, {DownloadProgressCallback? onProgressChanged}); +} diff --git a/lib/main/adapter/gateway/installation_file_storage.dart b/lib/main/adapter/gateway/installation_file_storage.dart new file mode 100644 index 0000000..3f79ae6 --- /dev/null +++ b/lib/main/adapter/gateway/installation_file_storage.dart @@ -0,0 +1,5 @@ +import 'dart:typed_data'; + +abstract interface class InstallationFileStorage { + Future saveFile(Uint8List fileBytes, String path); +} diff --git a/lib/main/adapter/gateway/installation_repository_impl.dart b/lib/main/adapter/gateway/installation_repository_impl.dart new file mode 100644 index 0000000..7d35089 --- /dev/null +++ b/lib/main/adapter/gateway/installation_repository_impl.dart @@ -0,0 +1,16 @@ +import 'package:minecraft_server_installer/main/adapter/gateway/installation_api_service.dart'; +import 'package:minecraft_server_installer/main/adapter/gateway/installation_file_storage.dart'; +import 'package:minecraft_server_installer/main/application/repository/installation_repository.dart'; + +class InstallationRepositoryImpl implements InstallationRepository { + final InstallationApiService _apiService; + final InstallationFileStorage _fileStorage; + + InstallationRepositoryImpl(this._apiService, this._fileStorage); + + @override + Future downloadServerFile(Uri url, String path, {DownloadProgressCallback? onProgressChanged}) async { + final fileBytes = await _apiService.fetchRemoteFile(url, onProgressChanged: onProgressChanged); + await _fileStorage.saveFile(fileBytes, path); + } +} diff --git a/lib/main/adapter/presentation/installation_bloc.dart b/lib/main/adapter/presentation/installation_bloc.dart index bfb9d47..316e529 100644 --- a/lib/main/adapter/presentation/installation_bloc.dart +++ b/lib/main/adapter/presentation/installation_bloc.dart @@ -1,9 +1,46 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart'; +import 'package:minecraft_server_installer/main/adapter/presentation/progress_view_model.dart'; +import 'package:minecraft_server_installer/main/application/use_case/download_file_use_case.dart'; +import 'package:minecraft_server_installer/main/constants.dart'; import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart'; +import 'package:path/path.dart' as path; class InstallationBloc extends Bloc { - InstallationBloc() : super(const InstallationState.empty()) { + InstallationBloc(DownloadFileUseCase downloadFileUseCase) : super(const InstallationState.empty()) { + on((_, emit) async { + if (!state.canStartToInstall) { + return; + } + + final gameVersion = state.gameVersion!; + final savePath = state.savePath!; + + emit(state.copyWith(isLocked: true, downloadProgress: const ProgressViewModel.start())); + + await downloadFileUseCase( + gameVersion.url, + path.join(savePath, Constants.serverFileName), + onProgressChanged: (progressValue) => add(_InstallationProgressValueChangedEvent(progressValue)), + ); + + emit(state.copyWith(isLocked: false, downloadProgress: const ProgressViewModel.complete())); + }); + + on<_InstallationProgressValueChangedEvent>((event, emit) { + ProgressViewModel newProgress; + + if (event.progressValue < 0) { + newProgress = state.downloadProgress.copyWith(value: 0.0); + } else if (event.progressValue > 1) { + newProgress = state.downloadProgress.copyWith(value: 1.0); + } else { + newProgress = state.downloadProgress.copyWith(value: event.progressValue); + } + + emit(state.copyWith(downloadProgress: newProgress)); + }); + on((event, emit) { final newState = state.copyWith( gameVersion: event.gameVersion, @@ -16,6 +53,14 @@ class InstallationBloc extends Bloc { sealed class InstallationEvent {} +class InstallationStartedEvent extends InstallationEvent {} + +class _InstallationProgressValueChangedEvent extends InstallationEvent { + final double progressValue; + + _InstallationProgressValueChangedEvent(this.progressValue); +} + class InstallationConfigurationUpdatedEvent extends InstallationEvent { final GameVersionViewModel? gameVersion; final String? savePath; diff --git a/lib/main/adapter/presentation/installation_state.dart b/lib/main/adapter/presentation/installation_state.dart index 9eb4d55..e70e6be 100644 --- a/lib/main/adapter/presentation/installation_state.dart +++ b/lib/main/adapter/presentation/installation_state.dart @@ -1,39 +1,52 @@ import 'package:equatable/equatable.dart'; +import 'package:minecraft_server_installer/main/adapter/presentation/progress_view_model.dart'; import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart'; class InstallationState with EquatableMixin { final GameVersionViewModel? gameVersion; final String? savePath; + final ProgressViewModel downloadProgress; + final bool isLocked; const InstallationState({ - this.gameVersion, - this.savePath, + required this.gameVersion, + required this.savePath, + required this.downloadProgress, + required this.isLocked, }); const InstallationState.empty() : this( gameVersion: null, savePath: null, + downloadProgress: const ProgressViewModel.zero(), + isLocked: false, ); @override List get props => [ gameVersion, savePath, + downloadProgress, + isLocked, ]; InstallationState copyWith({ GameVersionViewModel? gameVersion, String? savePath, + ProgressViewModel? downloadProgress, + bool? isLocked, }) => InstallationState( gameVersion: gameVersion ?? this.gameVersion, savePath: savePath ?? this.savePath, + downloadProgress: downloadProgress ?? this.downloadProgress, + isLocked: isLocked ?? this.isLocked, ); bool get isGameVersionSelected => gameVersion != null; bool get isSavePathSelected => savePath != null && savePath!.isNotEmpty; - bool get canStartToInstall => isGameVersionSelected && isSavePathSelected; + bool get canStartToInstall => isGameVersionSelected && isSavePathSelected && !isLocked; } diff --git a/lib/main/adapter/presentation/progress_view_model.dart b/lib/main/adapter/presentation/progress_view_model.dart new file mode 100644 index 0000000..e4f463f --- /dev/null +++ b/lib/main/adapter/presentation/progress_view_model.dart @@ -0,0 +1,33 @@ +import 'package:equatable/equatable.dart'; + +class ProgressViewModel with EquatableMixin { + /// The value should between 0.0 and 1.0. + final double value; + final bool isInProgress; + + const ProgressViewModel({ + required this.value, + required this.isInProgress, + }); + + const ProgressViewModel.zero() : this(value: 0.0, isInProgress: false); + + const ProgressViewModel.start() : this(value: 0.0, isInProgress: true); + + const ProgressViewModel.complete() : this(value: 1.0, isInProgress: false); + + @override + List get props => [ + value, + isInProgress, + ]; + + ProgressViewModel copyWith({ + double? value, + bool? isInProgress, + }) => + ProgressViewModel( + value: value ?? this.value, + isInProgress: isInProgress ?? this.isInProgress, + ); +} diff --git a/lib/main/application/repository/installation_repository.dart b/lib/main/application/repository/installation_repository.dart new file mode 100644 index 0000000..e155472 --- /dev/null +++ b/lib/main/application/repository/installation_repository.dart @@ -0,0 +1,5 @@ +typedef DownloadProgressCallback = void Function(double progress); + +abstract interface class InstallationRepository { + Future downloadServerFile(Uri url, String path, {DownloadProgressCallback? onProgressChanged}); +} diff --git a/lib/main/application/use_case/download_file_use_case.dart b/lib/main/application/use_case/download_file_use_case.dart new file mode 100644 index 0000000..2afdbc0 --- /dev/null +++ b/lib/main/application/use_case/download_file_use_case.dart @@ -0,0 +1,10 @@ +import 'package:minecraft_server_installer/main/application/repository/installation_repository.dart'; + +class DownloadFileUseCase { + final InstallationRepository _installationRepository; + + DownloadFileUseCase(this._installationRepository); + + Future call(Uri url, String path, {DownloadProgressCallback? onProgressChanged}) => + _installationRepository.downloadServerFile(url, path, onProgressChanged: onProgressChanged); +} diff --git a/lib/main/framework/api/installation_api_service_impl.dart b/lib/main/framework/api/installation_api_service_impl.dart new file mode 100644 index 0000000..0edf58c --- /dev/null +++ b/lib/main/framework/api/installation_api_service_impl.dart @@ -0,0 +1,40 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:http/http.dart' as http; +import 'package:minecraft_server_installer/main/adapter/gateway/installation_api_service.dart'; +import 'package:minecraft_server_installer/main/application/repository/installation_repository.dart'; + +class InstallationApiServiceImpl implements InstallationApiService { + @override + Future fetchRemoteFile(Uri url, {DownloadProgressCallback? onProgressChanged}) async { + final client = http.Client(); + final request = http.Request('GET', url); + final response = await client.send(request); + + final contentLength = response.contentLength; + final completer = Completer(); + final bytes = []; + var receivedBytes = 0; + + response.stream.listen( + (chunk) { + bytes.addAll(chunk); + receivedBytes += chunk.length; + if (onProgressChanged != null && contentLength != null) { + onProgressChanged(receivedBytes / contentLength); + } + }, + onDone: () { + if (onProgressChanged != null) { + onProgressChanged(1); + } + completer.complete(Uint8List.fromList(bytes)); + }, + onError: completer.completeError, + cancelOnError: true, + ); + + return completer.future; + } +} diff --git a/lib/main/framework/storage/installation_file_storage_impl.dart b/lib/main/framework/storage/installation_file_storage_impl.dart new file mode 100644 index 0000000..2089032 --- /dev/null +++ b/lib/main/framework/storage/installation_file_storage_impl.dart @@ -0,0 +1,18 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:minecraft_server_installer/main/adapter/gateway/installation_file_storage.dart'; + +class InstallationFileStorageImpl implements InstallationFileStorage { + @override + Future saveFile(Uint8List fileBytes, String path) async { + final file = File(path); + + if (!await file.parent.exists()) { + await file.parent.create(recursive: true); + } + + await file.create(); + await file.writeAsBytes(fileBytes, flush: true); + } +} diff --git a/lib/main/framework/ui/basic_configuration_tab.dart b/lib/main/framework/ui/basic_configuration_tab.dart index 2e1b07e..c24e4c9 100644 --- a/lib/main/framework/ui/basic_configuration_tab.dart +++ b/lib/main/framework/ui/basic_configuration_tab.dart @@ -2,11 +2,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:gap/gap.dart'; import 'package:minecraft_server_installer/main/adapter/presentation/installation_bloc.dart'; +import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart'; import 'package:minecraft_server_installer/main/framework/ui/path_browsing_field.dart'; import 'package:minecraft_server_installer/main/framework/ui/strings.dart'; -import 'package:minecraft_server_installer/vanilla/adapter/presentation/vanilla_bloc.dart'; import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart'; -import 'package:minecraft_server_installer/vanilla/adapter/presentation/vanilla_state.dart'; import 'package:minecraft_server_installer/vanilla/framework/ui/game_version_dropdown.dart'; class BasicConfigurationTab extends StatefulWidget { @@ -30,16 +29,17 @@ class _BasicConfigurationTabState extends State { ], ); - Widget get _bottomControl => BlocConsumer( + Widget get _bottomControl => BlocConsumer( listener: (_, __) {}, builder: (_, state) => Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - if (state.isDownloading) Expanded(child: LinearProgressIndicator(value: state.downloadProgress)), + if (state.downloadProgress.isInProgress) + Expanded(child: LinearProgressIndicator(value: state.downloadProgress.value)), const Gap(32), ElevatedButton.icon( style: ElevatedButton.styleFrom(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4))), - onPressed: context.watch().state.isGameVersionSelected ? _downloadServerFile : null, + onPressed: context.watch().state.canStartToInstall ? _downloadServerFile : null, icon: const Icon(Icons.download), label: const Padding( padding: EdgeInsets.symmetric(vertical: 12), @@ -51,7 +51,6 @@ class _BasicConfigurationTabState extends State { ); void _downloadServerFile() { - final savePath = context.read().state.savePath; - context.read().add(VanillaServerFileDownloadedEvent(savePath!)); + context.read().add((InstallationStartedEvent())); } } diff --git a/lib/main/framework/ui/minecraft_server_installer.dart b/lib/main/framework/ui/minecraft_server_installer.dart index c1ae2bd..baa02c9 100644 --- a/lib/main/framework/ui/minecraft_server_installer.dart +++ b/lib/main/framework/ui/minecraft_server_installer.dart @@ -1,14 +1,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:minecraft_server_installer/main/adapter/gateway/installation_repository_impl.dart'; import 'package:minecraft_server_installer/main/adapter/presentation/installation_bloc.dart'; +import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart'; +import 'package:minecraft_server_installer/main/application/use_case/download_file_use_case.dart'; +import 'package:minecraft_server_installer/main/framework/api/installation_api_service_impl.dart'; +import 'package:minecraft_server_installer/main/framework/storage/installation_file_storage_impl.dart'; import 'package:minecraft_server_installer/main/framework/ui/basic_configuration_tab.dart'; import 'package:minecraft_server_installer/vanilla/adapter/gateway/vanilla_repository_impl.dart'; import 'package:minecraft_server_installer/vanilla/adapter/presentation/vanilla_bloc.dart'; -import 'package:minecraft_server_installer/vanilla/adapter/presentation/vanilla_state.dart'; -import 'package:minecraft_server_installer/vanilla/application/use_case/download_server_file_use_case.dart'; import 'package:minecraft_server_installer/vanilla/application/use_case/get_game_version_list_use_case.dart'; import 'package:minecraft_server_installer/vanilla/framework/api/vanilla_api_service_impl.dart'; -import 'package:minecraft_server_installer/vanilla/framework/storage/vanilla_file_storage_impl.dart'; class MinecraftServerInstaller extends StatelessWidget { const MinecraftServerInstaller({super.key}); @@ -18,27 +20,28 @@ class MinecraftServerInstaller extends StatelessWidget { @override Widget build(BuildContext context) { - final gameVersionApiService = VanillaApiServiceImpl(); - final gameVersionFileStorage = VanillaFileStorageImpl(); - final gameVersionRepository = VanillaRepositoryImpl(gameVersionApiService, gameVersionFileStorage); - final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository); - final downloadServerFileUseCase = DownloadServerFileUseCase(gameVersionRepository); + final installationApiService = InstallationApiServiceImpl(); + final installationFileStorage = InstallationFileStorageImpl(); + final installationRepository = InstallationRepositoryImpl(installationApiService, installationFileStorage); - final installationBloc = InstallationBloc(); + final gameVersionApiService = VanillaApiServiceImpl(); + final gameVersionRepository = VanillaRepositoryImpl(gameVersionApiService); + + final downloadFileUseCase = DownloadFileUseCase(installationRepository); + final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository); return MaterialApp( title: 'Minecraft Server Installer', theme: ThemeData.light().copyWith(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade900)), home: MultiBlocProvider( providers: [ - BlocProvider.value(value: installationBloc), + BlocProvider(create: (_) => InstallationBloc(downloadFileUseCase)), BlocProvider( - create: (_) => VanillaBloc(installationBloc, getGameVersionListUseCase, downloadServerFileUseCase) - ..add(VanillaGameVersionListLoadedEvent()), + create: (_) => VanillaBloc(getGameVersionListUseCase)..add(VanillaGameVersionListLoadedEvent()), ), ], child: Scaffold( - body: BlocConsumer( + body: BlocConsumer( listener: (_, __) {}, builder: (_, state) { if (state.isLocked) { diff --git a/lib/vanilla/adapter/gateway/vanilla_api_service.dart b/lib/vanilla/adapter/gateway/vanilla_api_service.dart index 2c50673..37e50a8 100644 --- a/lib/vanilla/adapter/gateway/vanilla_api_service.dart +++ b/lib/vanilla/adapter/gateway/vanilla_api_service.dart @@ -1,10 +1,5 @@ -import 'dart:typed_data'; - -import 'package:minecraft_server_installer/vanilla/application/use_case/download_server_file_use_case.dart'; import 'package:minecraft_server_installer/vanilla/domain/entity/game_version.dart'; abstract interface class VanillaApiService { Future> fetchGameVersionList(); - - Future fetchServerFile(Uri url, {DownloadProgressCallback? onProgressChanged}); } diff --git a/lib/vanilla/adapter/gateway/vanilla_file_storage.dart b/lib/vanilla/adapter/gateway/vanilla_file_storage.dart deleted file mode 100644 index 3217984..0000000 --- a/lib/vanilla/adapter/gateway/vanilla_file_storage.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'dart:typed_data'; - -abstract interface class VanillaFileStorage { - Future saveFile(Uint8List fileBytes, String savePath); -} diff --git a/lib/vanilla/adapter/gateway/vanilla_repository_impl.dart b/lib/vanilla/adapter/gateway/vanilla_repository_impl.dart index a6e7782..e097bbb 100644 --- a/lib/vanilla/adapter/gateway/vanilla_repository_impl.dart +++ b/lib/vanilla/adapter/gateway/vanilla_repository_impl.dart @@ -1,28 +1,12 @@ import 'package:minecraft_server_installer/vanilla/adapter/gateway/vanilla_api_service.dart'; -import 'package:minecraft_server_installer/vanilla/adapter/gateway/vanilla_file_storage.dart'; import 'package:minecraft_server_installer/vanilla/application/repository/vanilla_repository.dart'; -import 'package:minecraft_server_installer/vanilla/application/use_case/download_server_file_use_case.dart'; import 'package:minecraft_server_installer/vanilla/domain/entity/game_version.dart'; class VanillaRepositoryImpl implements VanillaRepository { final VanillaApiService _gameVersionApiService; - final VanillaFileStorage _gameVersionFileStorage; - VanillaRepositoryImpl(this._gameVersionApiService, this._gameVersionFileStorage); + VanillaRepositoryImpl(this._gameVersionApiService); @override Future> getGameVersionList() => _gameVersionApiService.fetchGameVersionList(); - - @override - Future downloadServerFile( - GameVersion version, - String savePath, { - DownloadProgressCallback? onProgressChanged, - }) async { - final fileBytes = await _gameVersionApiService.fetchServerFile( - version.url, - onProgressChanged: onProgressChanged, - ); - await _gameVersionFileStorage.saveFile(fileBytes, savePath); - } } diff --git a/lib/vanilla/adapter/presentation/vanilla_bloc.dart b/lib/vanilla/adapter/presentation/vanilla_bloc.dart index 6d7f317..a2082e0 100644 --- a/lib/vanilla/adapter/presentation/vanilla_bloc.dart +++ b/lib/vanilla/adapter/presentation/vanilla_bloc.dart @@ -1,25 +1,13 @@ import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:minecraft_server_installer/main/adapter/presentation/installation_bloc.dart'; -import 'package:minecraft_server_installer/main/constants.dart'; import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart'; import 'package:minecraft_server_installer/vanilla/adapter/presentation/vanilla_state.dart'; -import 'package:minecraft_server_installer/vanilla/application/use_case/download_server_file_use_case.dart'; import 'package:minecraft_server_installer/vanilla/application/use_case/get_game_version_list_use_case.dart'; -import 'package:path/path.dart' as path; class VanillaBloc extends Bloc { - final InstallationBloc _installationBloc; - final GetGameVersionListUseCase _getGameVersionListUseCase; - final DownloadServerFileUseCase _downloadServerFileUseCase; - - VanillaBloc( - this._installationBloc, - this._getGameVersionListUseCase, - this._downloadServerFileUseCase, - ) : super(const VanillaState.empty()) { + VanillaBloc(GetGameVersionListUseCase getGameVersionListUseCase) : super(const VanillaState.empty()) { on((_, emit) async { try { - final gameVersions = await _getGameVersionListUseCase(); + final gameVersions = await getGameVersionListUseCase(); emit( const VanillaState.empty().copyWith( gameVersions: gameVersions.map((entity) => GameVersionViewModel.fromEntity(entity)).toList(), @@ -29,31 +17,6 @@ class VanillaBloc extends Bloc { emit(const VanillaState.empty()); } }); - - on((event, emit) async { - final gameVersion = _installationBloc.state.gameVersion; - if (gameVersion == null) { - return; - } - - emit(state.copyWith(isLocked: true)); - await _downloadServerFileUseCase( - gameVersion.toEntity(), - path.join(event.savePath, Constants.serverFileName), - onProgressChanged: (progress) => add(_VanillaDownloadProgressChangedEvent(progress)), - ); - emit(state.copyWith(isLocked: false)); - }); - - on<_VanillaDownloadProgressChangedEvent>((event, emit) { - if (event.progress < 0) { - emit(state.copyWith(downloadProgress: 0)); - } else if (event.progress > 1) { - emit(state.copyWith(downloadProgress: 1)); - } else { - emit(state.copyWith(downloadProgress: event.progress)); - } - }); } } @@ -66,15 +29,3 @@ class VanillaGameVersionSelectedEvent extends VanillaEvent { VanillaGameVersionSelectedEvent(this.gameVersion); } - -class VanillaServerFileDownloadedEvent extends VanillaEvent { - final String savePath; - - VanillaServerFileDownloadedEvent(this.savePath); -} - -class _VanillaDownloadProgressChangedEvent extends VanillaEvent { - final double progress; - - _VanillaDownloadProgressChangedEvent(this.progress); -} diff --git a/lib/vanilla/adapter/presentation/vanilla_state.dart b/lib/vanilla/adapter/presentation/vanilla_state.dart index 697c4a4..77b73cc 100644 --- a/lib/vanilla/adapter/presentation/vanilla_state.dart +++ b/lib/vanilla/adapter/presentation/vanilla_state.dart @@ -2,32 +2,22 @@ import 'package:equatable/equatable.dart'; import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart'; class VanillaState with EquatableMixin { - final bool isLocked; - final double downloadProgress; final List gameVersions; const VanillaState({ - required this.isLocked, - required this.downloadProgress, required this.gameVersions, }); const VanillaState.empty() : this( - isLocked: false, - downloadProgress: 0, gameVersions: const [], ); @override List get props => [ - isLocked, - downloadProgress, gameVersions, ]; - bool get isDownloading => downloadProgress > 0 && downloadProgress < 1; - VanillaState copyWith({ bool? isLocked, double? downloadProgress, @@ -35,8 +25,6 @@ class VanillaState with EquatableMixin { GameVersionViewModel? selectedGameVersion, }) => VanillaState( - isLocked: isLocked ?? this.isLocked, - downloadProgress: downloadProgress ?? this.downloadProgress, gameVersions: gameVersions ?? this.gameVersions, ); } diff --git a/lib/vanilla/application/repository/vanilla_repository.dart b/lib/vanilla/application/repository/vanilla_repository.dart index d3e2ef6..af61651 100644 --- a/lib/vanilla/application/repository/vanilla_repository.dart +++ b/lib/vanilla/application/repository/vanilla_repository.dart @@ -1,12 +1,5 @@ -import 'package:minecraft_server_installer/vanilla/application/use_case/download_server_file_use_case.dart'; import 'package:minecraft_server_installer/vanilla/domain/entity/game_version.dart'; abstract interface class VanillaRepository { Future> getGameVersionList(); - - Future downloadServerFile( - GameVersion version, - String savePath, { - DownloadProgressCallback? onProgressChanged, - }); } diff --git a/lib/vanilla/application/use_case/download_server_file_use_case.dart b/lib/vanilla/application/use_case/download_server_file_use_case.dart deleted file mode 100644 index c5e848d..0000000 --- a/lib/vanilla/application/use_case/download_server_file_use_case.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:minecraft_server_installer/vanilla/application/repository/vanilla_repository.dart'; -import 'package:minecraft_server_installer/vanilla/domain/entity/game_version.dart'; - -typedef DownloadProgressCallback = void Function(double progress); - -class DownloadServerFileUseCase { - final VanillaRepository _gameVersionRepository; - - DownloadServerFileUseCase(this._gameVersionRepository); - - Future call( - GameVersion version, - String savePath, { - DownloadProgressCallback? onProgressChanged, - }) => - _gameVersionRepository.downloadServerFile( - version, - savePath, - onProgressChanged: onProgressChanged, - ); -} diff --git a/lib/vanilla/framework/api/vanilla_api_service_impl.dart b/lib/vanilla/framework/api/vanilla_api_service_impl.dart index d633312..23e1b62 100644 --- a/lib/vanilla/framework/api/vanilla_api_service_impl.dart +++ b/lib/vanilla/framework/api/vanilla_api_service_impl.dart @@ -1,10 +1,8 @@ import 'dart:async'; -import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:minecraft_server_installer/main/constants.dart'; import 'package:minecraft_server_installer/vanilla/adapter/gateway/vanilla_api_service.dart'; -import 'package:minecraft_server_installer/vanilla/application/use_case/download_server_file_use_case.dart'; import 'package:minecraft_server_installer/vanilla/domain/entity/game_version.dart'; class VanillaApiServiceImpl implements VanillaApiService { @@ -22,36 +20,4 @@ class VanillaApiServiceImpl implements VanillaApiService { return gameVersionList; } - - @override - Future fetchServerFile(Uri url, {DownloadProgressCallback? onProgressChanged}) async { - final client = http.Client(); - final request = http.Request('GET', url); - final response = await client.send(request); - - final contentLength = response.contentLength; - final completer = Completer(); - final bytes = []; - var receivedBytes = 0; - - response.stream.listen( - (chunk) { - bytes.addAll(chunk); - receivedBytes += chunk.length; - if (onProgressChanged != null && contentLength != null) { - onProgressChanged(receivedBytes / contentLength); - } - }, - onDone: () { - if (onProgressChanged != null) { - onProgressChanged(1); - } - completer.complete(Uint8List.fromList(bytes)); - }, - onError: completer.completeError, - cancelOnError: true, - ); - - return completer.future; - } } diff --git a/lib/vanilla/framework/storage/vanilla_file_storage_impl.dart b/lib/vanilla/framework/storage/vanilla_file_storage_impl.dart deleted file mode 100644 index 921aa92..0000000 --- a/lib/vanilla/framework/storage/vanilla_file_storage_impl.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:minecraft_server_installer/vanilla/adapter/gateway/vanilla_file_storage.dart'; - -class VanillaFileStorageImpl implements VanillaFileStorage { - @override - Future saveFile(Uint8List fileBytes, String savePath) async { - final file = File(savePath); - - if (!await file.parent.exists()) { - await file.parent.create(recursive: true); - } - - await file.create(); - await file.writeAsBytes(fileBytes, flush: true); - } -}