diff --git a/lib/main/adapter/gateway/installation_file_storage.dart b/lib/main/adapter/gateway/installation_file_storage.dart index 4d9de05..6744403 100644 --- a/lib/main/adapter/gateway/installation_file_storage.dart +++ b/lib/main/adapter/gateway/installation_file_storage.dart @@ -4,4 +4,6 @@ abstract interface class InstallationFileStorage { Future saveFile(Uint8List fileBytes, String path); Future writeFile(String path, String content); + + Future grantFileExecutePermission(String path); } diff --git a/lib/main/adapter/gateway/installation_repository_impl.dart b/lib/main/adapter/gateway/installation_repository_impl.dart index 65725b2..41abe61 100644 --- a/lib/main/adapter/gateway/installation_repository_impl.dart +++ b/lib/main/adapter/gateway/installation_repository_impl.dart @@ -16,4 +16,9 @@ class InstallationRepositoryImpl implements InstallationRepository { @override Future writeFile(String path, String content) => _fileStorage.writeFile(path, content); + + @override + Future grantFileExecutePermission(String path) { + return _fileStorage.grantFileExecutePermission(path); + } } diff --git a/lib/main/adapter/presentation/installation_bloc.dart b/lib/main/adapter/presentation/installation_bloc.dart index f498eec..3bf1abe 100644 --- a/lib/main/adapter/presentation/installation_bloc.dart +++ b/lib/main/adapter/presentation/installation_bloc.dart @@ -1,7 +1,10 @@ +import 'dart:io'; + 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/application/use_case/grant_file_permission_use_case.dart'; import 'package:minecraft_server_installer/main/application/use_case/write_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'; @@ -11,6 +14,7 @@ class InstallationBloc extends Bloc { InstallationBloc( DownloadFileUseCase downloadFileUseCase, WriteFileUseCase writeFileUseCase, + GrantFilePermissionUseCase grantFilePermissionUseCase, ) : super(const InstallationState.empty()) { on((_, emit) async { if (!state.canStartToInstall) { @@ -28,10 +32,12 @@ class InstallationBloc extends Bloc { onProgressChanged: (progressValue) => add(_InstallationProgressValueChangedEvent(progressValue)), ); - await writeFileUseCase( - path.join(savePath, Constants.startScriptFileName), - 'java -jar ${Constants.serverFileName}\n', - ); + final startScriptFilePath = path.join(savePath, Constants.startScriptFileName); + final startScriptContent = Platform.isWindows + ? 'java -jar .\\${Constants.serverFileName}\r\n' + : 'java -jar ./${Constants.serverFileName}\n'; + await writeFileUseCase(startScriptFilePath, startScriptContent); + await grantFilePermissionUseCase(startScriptFilePath); emit(state.copyWith(isLocked: false, downloadProgress: const ProgressViewModel.complete())); }); diff --git a/lib/main/application/repository/installation_repository.dart b/lib/main/application/repository/installation_repository.dart index f1930e7..17b6ec0 100644 --- a/lib/main/application/repository/installation_repository.dart +++ b/lib/main/application/repository/installation_repository.dart @@ -4,4 +4,6 @@ abstract interface class InstallationRepository { Future downloadFile(Uri url, String path, {DownloadProgressCallback? onProgressChanged}); Future writeFile(String path, String content); + + Future grantFileExecutePermission(String path); } diff --git a/lib/main/application/use_case/grant_file_permission_use_case.dart b/lib/main/application/use_case/grant_file_permission_use_case.dart new file mode 100644 index 0000000..771b41a --- /dev/null +++ b/lib/main/application/use_case/grant_file_permission_use_case.dart @@ -0,0 +1,9 @@ +import 'package:minecraft_server_installer/main/application/repository/installation_repository.dart'; + +class GrantFilePermissionUseCase { + final InstallationRepository _installationRepository; + + GrantFilePermissionUseCase(this._installationRepository); + + Future call(String path) => _installationRepository.grantFileExecutePermission(path); +} \ No newline at end of file diff --git a/lib/main/framework/storage/installation_file_storage_impl.dart b/lib/main/framework/storage/installation_file_storage_impl.dart index 60cdd1b..0cf0a02 100644 --- a/lib/main/framework/storage/installation_file_storage_impl.dart +++ b/lib/main/framework/storage/installation_file_storage_impl.dart @@ -17,4 +17,16 @@ class InstallationFileStorageImpl implements InstallationFileStorage { await file.create(recursive: true, exclusive: false); await file.writeAsString(content, flush: true); } + + @override + Future grantFileExecutePermission(String path) async { + File file = File(path); + await file.create(recursive: true, exclusive: false); + + if (Platform.isWindows) { + await Process.run('icacls', [path, '/grant', '%USERNAME%:(RX)']); + } else { + await Process.run('chmod', ['+x', path]); + } + } } diff --git a/lib/main/framework/ui/minecraft_server_installer.dart b/lib/main/framework/ui/minecraft_server_installer.dart index 11c9aff..e8c3d17 100644 --- a/lib/main/framework/ui/minecraft_server_installer.dart +++ b/lib/main/framework/ui/minecraft_server_installer.dart @@ -4,6 +4,7 @@ import 'package:minecraft_server_installer/main/adapter/gateway/installation_rep 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/application/use_case/grant_file_permission_use_case.dart'; import 'package:minecraft_server_installer/main/application/use_case/write_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'; @@ -30,6 +31,7 @@ class MinecraftServerInstaller extends StatelessWidget { final downloadFileUseCase = DownloadFileUseCase(installationRepository); final writeFileUseCase = WriteFileUseCase(installationRepository); + final grantFilePermissionUseCase = GrantFilePermissionUseCase(installationRepository); final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository); return MaterialApp( @@ -37,7 +39,13 @@ class MinecraftServerInstaller extends StatelessWidget { theme: ThemeData.light().copyWith(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade900)), home: MultiBlocProvider( providers: [ - BlocProvider(create: (_) => InstallationBloc(downloadFileUseCase, writeFileUseCase)), + BlocProvider( + create: (_) => InstallationBloc( + downloadFileUseCase, + writeFileUseCase, + grantFilePermissionUseCase, + ), + ), BlocProvider( create: (_) => VanillaBloc(getGameVersionListUseCase)..add(VanillaGameVersionListLoadedEvent()), ),