MCSI-4 EULA Agreement #23
@ -62,6 +62,7 @@ class InstallationBloc extends Bloc<InstallationEvent, InstallationState> {
|
|||||||
final newState = state.copyWith(
|
final newState = state.copyWith(
|
||||||
gameVersion: event.gameVersion,
|
gameVersion: event.gameVersion,
|
||||||
savePath: event.savePath,
|
savePath: event.savePath,
|
||||||
|
isEulaAgreed: event.isEulaAgreed,
|
||||||
);
|
);
|
||||||
emit(newState);
|
emit(newState);
|
||||||
});
|
});
|
||||||
@ -81,9 +82,11 @@ class _InstallationProgressValueChangedEvent extends InstallationEvent {
|
|||||||
class InstallationConfigurationUpdatedEvent extends InstallationEvent {
|
class InstallationConfigurationUpdatedEvent extends InstallationEvent {
|
||||||
final GameVersionViewModel? gameVersion;
|
final GameVersionViewModel? gameVersion;
|
||||||
final String? savePath;
|
final String? savePath;
|
||||||
|
final bool? isEulaAgreed;
|
||||||
|
|
||||||
InstallationConfigurationUpdatedEvent({
|
InstallationConfigurationUpdatedEvent({
|
||||||
this.gameVersion,
|
this.gameVersion,
|
||||||
this.savePath,
|
this.savePath,
|
||||||
|
this.isEulaAgreed,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,14 @@ import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_ver
|
|||||||
class InstallationState with EquatableMixin {
|
class InstallationState with EquatableMixin {
|
||||||
final GameVersionViewModel? gameVersion;
|
final GameVersionViewModel? gameVersion;
|
||||||
final String? savePath;
|
final String? savePath;
|
||||||
|
final bool isEulaAgreed;
|
||||||
final ProgressViewModel downloadProgress;
|
final ProgressViewModel downloadProgress;
|
||||||
final bool isLocked;
|
final bool isLocked;
|
||||||
|
|
||||||
const InstallationState({
|
const InstallationState({
|
||||||
required this.gameVersion,
|
required this.gameVersion,
|
||||||
required this.savePath,
|
required this.savePath,
|
||||||
|
required this.isEulaAgreed,
|
||||||
required this.downloadProgress,
|
required this.downloadProgress,
|
||||||
required this.isLocked,
|
required this.isLocked,
|
||||||
});
|
});
|
||||||
@ -19,6 +21,7 @@ class InstallationState with EquatableMixin {
|
|||||||
: this(
|
: this(
|
||||||
gameVersion: null,
|
gameVersion: null,
|
||||||
savePath: null,
|
savePath: null,
|
||||||
|
isEulaAgreed: false,
|
||||||
downloadProgress: const ProgressViewModel.zero(),
|
downloadProgress: const ProgressViewModel.zero(),
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
);
|
);
|
||||||
@ -27,6 +30,7 @@ class InstallationState with EquatableMixin {
|
|||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
gameVersion,
|
gameVersion,
|
||||||
savePath,
|
savePath,
|
||||||
|
isEulaAgreed,
|
||||||
downloadProgress,
|
downloadProgress,
|
||||||
isLocked,
|
isLocked,
|
||||||
];
|
];
|
||||||
@ -34,12 +38,14 @@ class InstallationState with EquatableMixin {
|
|||||||
InstallationState copyWith({
|
InstallationState copyWith({
|
||||||
GameVersionViewModel? gameVersion,
|
GameVersionViewModel? gameVersion,
|
||||||
String? savePath,
|
String? savePath,
|
||||||
|
bool? isEulaAgreed,
|
||||||
ProgressViewModel? downloadProgress,
|
ProgressViewModel? downloadProgress,
|
||||||
bool? isLocked,
|
bool? isLocked,
|
||||||
}) =>
|
}) =>
|
||||||
InstallationState(
|
InstallationState(
|
||||||
gameVersion: gameVersion ?? this.gameVersion,
|
gameVersion: gameVersion ?? this.gameVersion,
|
||||||
savePath: savePath ?? this.savePath,
|
savePath: savePath ?? this.savePath,
|
||||||
|
isEulaAgreed: isEulaAgreed ?? this.isEulaAgreed,
|
||||||
downloadProgress: downloadProgress ?? this.downloadProgress,
|
downloadProgress: downloadProgress ?? this.downloadProgress,
|
||||||
isLocked: isLocked ?? this.isLocked,
|
isLocked: isLocked ?? this.isLocked,
|
||||||
);
|
);
|
||||||
@ -48,5 +54,5 @@ class InstallationState with EquatableMixin {
|
|||||||
|
|
||||||
bool get isSavePathSelected => savePath != null && savePath!.isNotEmpty;
|
bool get isSavePathSelected => savePath != null && savePath!.isNotEmpty;
|
||||||
|
|
||||||
bool get canStartToInstall => isGameVersionSelected && isSavePathSelected && !isLocked;
|
bool get canStartToInstall => isGameVersionSelected && isSavePathSelected && isEulaAgreed && !isLocked;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ abstract class Constants {
|
|||||||
static const eulaFileName = 'eula.txt';
|
static const eulaFileName = 'eula.txt';
|
||||||
static const eulaFileContent =
|
static const eulaFileContent =
|
||||||
'#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\neula=true';
|
'#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\neula=true';
|
||||||
|
static const eulaUrl = 'https://account.mojang.com/documents/minecraft_eula';
|
||||||
|
|
||||||
static final startScriptFileName = Platform.isWindows ? 'start.bat' : 'start.sh';
|
static final startScriptFileName = Platform.isWindows ? 'start.bat' : 'start.sh';
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,55 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:gap/gap.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_bloc.dart';
|
||||||
import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart';
|
import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/constants.dart';
|
||||||
import 'package:minecraft_server_installer/main/framework/ui/path_browsing_field.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/main/framework/ui/strings.dart';
|
||||||
import 'package:minecraft_server_installer/vanilla/adapter/presentation/game_version_view_model.dart';
|
|
||||||
import 'package:minecraft_server_installer/vanilla/framework/ui/game_version_dropdown.dart';
|
import 'package:minecraft_server_installer/vanilla/framework/ui/game_version_dropdown.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class BasicConfigurationTab extends StatefulWidget {
|
class BasicConfigurationTab extends StatelessWidget {
|
||||||
const BasicConfigurationTab({super.key});
|
const BasicConfigurationTab({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<BasicConfigurationTab> createState() => _BasicConfigurationTabState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BasicConfigurationTabState extends State<BasicConfigurationTab> {
|
|
||||||
GameVersionViewModel? selectedGameVersion;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Column(
|
Widget build(BuildContext context) => Column(
|
||||||
children: [
|
children: [
|
||||||
const GameVersionDropdown(),
|
const GameVersionDropdown(),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
const PathBrowsingField(),
|
const PathBrowsingField(),
|
||||||
|
const Gap(16),
|
||||||
|
_eulaCheckbox,
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
_bottomControl,
|
_bottomControl,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Widget get _eulaCheckbox => Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: BlocConsumer<InstallationBloc, InstallationState>(
|
||||||
|
listener: (_, __) {},
|
||||||
|
builder: (context, state) => CheckboxListTile(
|
||||||
|
title: const Text('${Strings.fieldEula} *'),
|
||||||
|
value: state.isEulaAgreed,
|
||||||
|
onChanged: (value) => context
|
||||||
|
.read<InstallationBloc>()
|
||||||
|
.add(InstallationConfigurationUpdatedEvent(isEulaAgreed: value ?? false)),
|
||||||
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => launchUrl(Uri.parse(Constants.eulaUrl)),
|
||||||
|
tooltip: Strings.tooltipEulaInfo,
|
||||||
|
icon: const Icon(Icons.info_outline),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
Widget get _bottomControl => BlocConsumer<InstallationBloc, InstallationState>(
|
Widget get _bottomControl => BlocConsumer<InstallationBloc, InstallationState>(
|
||||||
listener: (_, __) {},
|
listener: (_, __) {},
|
||||||
builder: (_, state) => Row(
|
builder: (context, state) => Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
if (state.downloadProgress.isInProgress)
|
if (state.downloadProgress.isInProgress)
|
||||||
@ -39,7 +59,8 @@ class _BasicConfigurationTabState extends State<BasicConfigurationTab> {
|
|||||||
const Gap(32),
|
const Gap(32),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
style: ElevatedButton.styleFrom(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4))),
|
style: ElevatedButton.styleFrom(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4))),
|
||||||
onPressed: context.watch<InstallationBloc>().state.canStartToInstall ? _downloadServerFile : null,
|
onPressed:
|
||||||
|
context.watch<InstallationBloc>().state.canStartToInstall ? () => _downloadServerFile(context) : null,
|
||||||
icon: const Icon(Icons.download),
|
icon: const Icon(Icons.download),
|
||||||
label: const Padding(
|
label: const Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 12),
|
padding: EdgeInsets.symmetric(vertical: 12),
|
||||||
@ -50,7 +71,7 @@ class _BasicConfigurationTabState extends State<BasicConfigurationTab> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
void _downloadServerFile() {
|
void _downloadServerFile(BuildContext context) {
|
||||||
context.read<InstallationBloc>().add((InstallationStartedEvent()));
|
context.read<InstallationBloc>().add((InstallationStartedEvent()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
abstract class Strings {
|
abstract class Strings {
|
||||||
static const fieldGameVersion = '遊戲版本';
|
static const fieldGameVersion = '遊戲版本';
|
||||||
static const fieldPath = '安裝路徑';
|
static const fieldPath = '安裝路徑';
|
||||||
|
static const fieldEula = '我同意 EULA 條款';
|
||||||
static const buttonStartToInstall = '開始安裝';
|
static const buttonStartToInstall = '開始安裝';
|
||||||
static const buttonBrowse = '瀏覽';
|
static const buttonBrowse = '瀏覽';
|
||||||
|
static const tooltipEulaInfo = '點擊查看 EULA 條款';
|
||||||
static const dialogTitleSelectDirectory = '選擇安裝目錄';
|
static const dialogTitleSelectDirectory = '選擇安裝目錄';
|
||||||
}
|
}
|
||||||
|
64
pubspec.lock
64
pubspec.lock
@ -357,6 +357,70 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
|
url_launcher:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: url_launcher
|
||||||
|
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.1"
|
||||||
|
url_launcher_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_android
|
||||||
|
sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.16"
|
||||||
|
url_launcher_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_ios
|
||||||
|
sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.3"
|
||||||
|
url_launcher_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_linux
|
||||||
|
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
|
url_launcher_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_macos
|
||||||
|
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.2"
|
||||||
|
url_launcher_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_platform_interface
|
||||||
|
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
url_launcher_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_web
|
||||||
|
sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
url_launcher_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_windows
|
||||||
|
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.4"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -40,6 +40,7 @@ dependencies:
|
|||||||
gap: ^3.0.1
|
gap: ^3.0.1
|
||||||
http: ^1.4.0
|
http: ^1.4.0
|
||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
|
url_launcher: ^6.3.1
|
||||||
window_manager: ^0.5.0
|
window_manager: ^0.5.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user