MCSI-7 Tab and navigation #26
BIN
assets/img/mcsi_logo.png
Normal file
BIN
assets/img/mcsi_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
22
lib/main/adapter/presentation/navigation_bloc.dart
Normal file
22
lib/main/adapter/presentation/navigation_bloc.dart
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class NavigationBloc extends Bloc<NavigationEvent, NavigationItem> {
|
||||||
|
NavigationBloc() : super(NavigationItem.basicConfiguration) {
|
||||||
|
on<NavigationChangedEvent>((event, emit) => emit(event.item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class NavigationEvent {}
|
||||||
|
|
||||||
|
class NavigationChangedEvent extends NavigationEvent {
|
||||||
|
final NavigationItem item;
|
||||||
|
|
||||||
|
NavigationChangedEvent(this.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NavigationItem {
|
||||||
|
basicConfiguration,
|
||||||
|
modConfiguration,
|
||||||
|
serverProperties,
|
||||||
|
about,
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
abstract class Constants {
|
abstract class Constants {
|
||||||
|
static const appName = 'Minecraft Server Installer';
|
||||||
static const gameVersionListUrl = 'https://www.dropbox.com/s/mtz3moc9dpjtz7s/GameVersions.txt?dl=1';
|
static const gameVersionListUrl = 'https://www.dropbox.com/s/mtz3moc9dpjtz7s/GameVersions.txt?dl=1';
|
||||||
static const serverFileName = 'server.jar';
|
static const serverFileName = 'server.jar';
|
||||||
static const eulaFileName = 'eula.txt';
|
static const eulaFileName = 'eula.txt';
|
||||||
|
@ -2,13 +2,15 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.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/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_bloc.dart';
|
||||||
import 'package:minecraft_server_installer/main/adapter/presentation/installation_state.dart';
|
import 'package:minecraft_server_installer/main/adapter/presentation/navigation_bloc.dart';
|
||||||
import 'package:minecraft_server_installer/main/application/use_case/download_file_use_case.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/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/application/use_case/write_file_use_case.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/constants.dart';
|
||||||
import 'package:minecraft_server_installer/main/framework/api/installation_api_service_impl.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/storage/installation_file_storage_impl.dart';
|
||||||
import 'package:minecraft_server_installer/main/framework/ui/basic_configuration_tab.dart';
|
import 'package:minecraft_server_installer/main/framework/ui/basic_configuration_tab.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/framework/ui/side_navigation_bar.dart';
|
||||||
import 'package:minecraft_server_installer/vanilla/adapter/gateway/vanilla_repository_impl.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_bloc.dart';
|
||||||
import 'package:minecraft_server_installer/vanilla/application/use_case/get_game_version_list_use_case.dart';
|
import 'package:minecraft_server_installer/vanilla/application/use_case/get_game_version_list_use_case.dart';
|
||||||
@ -17,9 +19,6 @@ import 'package:minecraft_server_installer/vanilla/framework/api/vanilla_api_ser
|
|||||||
class MinecraftServerInstaller extends StatelessWidget {
|
class MinecraftServerInstaller extends StatelessWidget {
|
||||||
const MinecraftServerInstaller({super.key});
|
const MinecraftServerInstaller({super.key});
|
||||||
|
|
||||||
Widget get _body =>
|
|
||||||
const Padding(padding: EdgeInsets.symmetric(horizontal: 24, vertical: 32), child: BasicConfigurationTab());
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final installationApiService = InstallationApiServiceImpl();
|
final installationApiService = InstallationApiServiceImpl();
|
||||||
@ -35,10 +34,16 @@ class MinecraftServerInstaller extends StatelessWidget {
|
|||||||
final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository);
|
final getGameVersionListUseCase = GetGameVersionListUseCase(gameVersionRepository);
|
||||||
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Minecraft Server Installer',
|
title: Constants.appName,
|
||||||
theme: ThemeData.light().copyWith(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade900)),
|
theme: ThemeData(
|
||||||
|
colorScheme: ColorScheme.fromSeed(
|
||||||
|
brightness: Brightness.light,
|
||||||
|
seedColor: Colors.blue.shade900,
|
||||||
|
),
|
||||||
|
),
|
||||||
home: MultiBlocProvider(
|
home: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
|
BlocProvider(create: (_) => NavigationBloc()),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => InstallationBloc(
|
create: (_) => InstallationBloc(
|
||||||
downloadFileUseCase,
|
downloadFileUseCase,
|
||||||
@ -51,18 +56,52 @@ class MinecraftServerInstaller extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: BlocConsumer<InstallationBloc, InstallationState>(
|
body: Row(
|
||||||
listener: (_, __) {},
|
children: [
|
||||||
builder: (_, state) {
|
const SideNavigationBar(),
|
||||||
if (state.isLocked) {
|
Expanded(
|
||||||
return MouseRegion(cursor: SystemMouseCursors.forbidden, child: AbsorbPointer(child: _body));
|
child: Builder(
|
||||||
}
|
builder: (context) {
|
||||||
|
if (context.watch<InstallationBloc>().state.isLocked) {
|
||||||
|
return MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.forbidden,
|
||||||
|
child: AbsorbPointer(child: _body),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return _body;
|
return _body;
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget get _body => BlocConsumer<NavigationBloc, NavigationItem>(
|
||||||
|
listener: (_, __) {},
|
||||||
|
builder: (_, state) => Padding(
|
||||||
|
padding: const EdgeInsets.all(32),
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: SizedBox(
|
||||||
|
key: ValueKey('tab${state.toString()}'),
|
||||||
|
child: _tabContent(state),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _tabContent(NavigationItem navigationItem) {
|
||||||
|
switch (navigationItem) {
|
||||||
|
case NavigationItem.basicConfiguration:
|
||||||
|
return const BasicConfigurationTab();
|
||||||
|
case NavigationItem.modConfiguration:
|
||||||
|
case NavigationItem.serverProperties:
|
||||||
|
case NavigationItem.about:
|
||||||
|
return const Placeholder();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
202
lib/main/framework/ui/side_navigation_bar.dart
Normal file
202
lib/main/framework/ui/side_navigation_bar.dart
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
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/navigation_bloc.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/constants.dart';
|
||||||
|
import 'package:minecraft_server_installer/main/framework/ui/strings.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
|
class SideNavigationBar extends StatefulWidget {
|
||||||
|
const SideNavigationBar({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SideNavigationBar> createState() => _SideNavigationBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SideNavigationBarState extends State<SideNavigationBar> {
|
||||||
|
bool _isExpanded = false;
|
||||||
|
PackageInfo? _packageInfo;
|
||||||
|
|
||||||
|
double get width => _isExpanded ? 360 : 80;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
PackageInfo.fromPlatform().then((packageInfo) =>
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() => _packageInfo = packageInfo)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
width: width,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey.shade200,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topRight: Radius.circular(16),
|
||||||
|
bottomRight: Radius.circular(16),
|
||||||
|
),
|
||||||
|
boxShadow: [
|
||||||
|
const BoxShadow(color: Colors.black26, offset: Offset(0, 0), blurRadius: 8),
|
||||||
|
]),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
_animatedText(
|
||||||
|
text: Constants.appName,
|
||||||
|
leading: SizedBox.square(
|
||||||
|
dimension: 36,
|
||||||
|
child: Image.asset('assets/img/mcsi_logo.png', width: 2048, height: 2048),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(left: 4),
|
||||||
|
expandedKey: const ValueKey('expandedTitle'),
|
||||||
|
collapsedKey: const ValueKey('collapsedTitle'),
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.titleMedium
|
||||||
|
?.copyWith(fontWeight: FontWeight.w900, color: Colors.blueGrey.shade900),
|
||||||
|
),
|
||||||
|
Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: InkWell(
|
||||||
|
key: ValueKey(_isExpanded),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
onTap: _toggleIsExpanded,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: Icon(_isExpanded ? Icons.menu_open : Icons.menu, color: Colors.blueGrey.shade600),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Gap(32),
|
||||||
|
_navigationButton(NavigationItem.basicConfiguration),
|
||||||
|
const Gap(8),
|
||||||
|
_navigationButton(NavigationItem.modConfiguration),
|
||||||
|
const Gap(8),
|
||||||
|
_navigationButton(NavigationItem.serverProperties),
|
||||||
|
const Gap(8),
|
||||||
|
_navigationButton(NavigationItem.about),
|
||||||
|
const Spacer(),
|
||||||
|
_animatedText(
|
||||||
|
text: 'Version ${_packageInfo?.version ?? ''}',
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
expandedKey: const ValueKey('expandedVersion'),
|
||||||
|
collapsedKey: const ValueKey('collapsedVersion'),
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
void _toggleIsExpanded() => setState(() => _isExpanded = !_isExpanded);
|
||||||
|
|
||||||
|
Widget _animatedText({
|
||||||
|
required String text,
|
||||||
|
required Key expandedKey,
|
||||||
|
required Key collapsedKey,
|
||||||
|
EdgeInsetsGeometry padding = const EdgeInsets.only(left: 8),
|
||||||
|
TextStyle? style,
|
||||||
|
AlignmentGeometry alignment = Alignment.centerLeft,
|
||||||
|
Widget? leading,
|
||||||
|
}) =>
|
||||||
|
Expanded(
|
||||||
|
child: ClipRect(
|
||||||
|
child: Container(
|
||||||
|
alignment: alignment,
|
||||||
|
padding: padding,
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: _isExpanded
|
||||||
|
? Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (leading != null)
|
||||||
|
Flexible(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8),
|
||||||
|
child: leading,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
key: expandedKey,
|
||||||
|
style: style,
|
||||||
|
softWrap: false,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: SizedBox.shrink(key: collapsedKey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _navigationButton(NavigationItem navigationItem) {
|
||||||
|
final selectedNavigationItem = context.watch<NavigationBloc>().state;
|
||||||
|
final isSelected = selectedNavigationItem == navigationItem;
|
||||||
|
final color = isSelected ? Colors.blue.shade900 : Colors.blueGrey.shade600;
|
||||||
|
return Material(
|
||||||
|
color: isSelected ? Colors.blueGrey.shade100 : Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
onTap: () => context.read<NavigationBloc>().add(NavigationChangedEvent(navigationItem)),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: Icon(navigationItem.iconData, color: color),
|
||||||
|
),
|
||||||
|
_animatedText(
|
||||||
|
text: navigationItem.title,
|
||||||
|
expandedKey: ValueKey('expanded${navigationItem.toString()}'),
|
||||||
|
collapsedKey: ValueKey('collapsed${navigationItem.toString()}'),
|
||||||
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w500, color: color),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension _NavigationItemContent on NavigationItem {
|
||||||
|
String get title {
|
||||||
|
switch (this) {
|
||||||
|
case NavigationItem.basicConfiguration:
|
||||||
|
return Strings.tabBasicConfiguration;
|
||||||
|
case NavigationItem.modConfiguration:
|
||||||
|
return Strings.tabModConfiguration;
|
||||||
|
case NavigationItem.serverProperties:
|
||||||
|
return Strings.tabServerProperties;
|
||||||
|
case NavigationItem.about:
|
||||||
|
return Strings.tabAbout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconData get iconData {
|
||||||
|
switch (this) {
|
||||||
|
case NavigationItem.basicConfiguration:
|
||||||
|
return Icons.dashboard_rounded;
|
||||||
|
case NavigationItem.modConfiguration:
|
||||||
|
return Icons.extension;
|
||||||
|
case NavigationItem.serverProperties:
|
||||||
|
return Icons.settings;
|
||||||
|
case NavigationItem.about:
|
||||||
|
return Icons.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,11 @@ abstract class Strings {
|
|||||||
static const fieldMaxRamSize = '最大 RAM 大小';
|
static const fieldMaxRamSize = '最大 RAM 大小';
|
||||||
static const buttonStartToInstall = '開始安裝';
|
static const buttonStartToInstall = '開始安裝';
|
||||||
static const buttonBrowse = '瀏覽';
|
static const buttonBrowse = '瀏覽';
|
||||||
|
static const tabBasicConfiguration = '基本設定';
|
||||||
|
static const tabModConfiguration = '模組設定';
|
||||||
|
static const tabServerProperties = '伺服器選項';
|
||||||
|
static const tabAbout = '關於與說明';
|
||||||
|
static const tabInstallationProgress = '安裝進度';
|
||||||
static const tooltipEulaInfo = '點擊查看 EULA 條款';
|
static const tooltipEulaInfo = '點擊查看 EULA 條款';
|
||||||
static const dialogTitleSelectDirectory = '選擇安裝目錄';
|
static const dialogTitleSelectDirectory = '選擇安裝目錄';
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ Future<void> main() async {
|
|||||||
await windowManager.ensureInitialized();
|
await windowManager.ensureInitialized();
|
||||||
|
|
||||||
final windowOptions = const WindowOptions(
|
final windowOptions = const WindowOptions(
|
||||||
size: Size(400, 600),
|
size: Size(800, 600),
|
||||||
minimumSize: Size(400, 600),
|
minimumSize: Size(800, 600),
|
||||||
center: true,
|
center: true,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
skipTaskbar: false,
|
skipTaskbar: false,
|
||||||
|
@ -22,7 +22,7 @@ static void my_application_activate(GApplication* application) {
|
|||||||
|
|
||||||
gtk_window_set_decorated(window, FALSE);
|
gtk_window_set_decorated(window, FALSE);
|
||||||
|
|
||||||
gtk_window_set_default_size(window, 400, 600);
|
gtk_window_set_default_size(window, 800, 600);
|
||||||
gtk_widget_show(GTK_WIDGET(window));
|
gtk_widget_show(GTK_WIDGET(window));
|
||||||
|
|
||||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||||
|
16
pubspec.lock
16
pubspec.lock
@ -232,6 +232,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
package_info_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: package_info_plus
|
||||||
|
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.3.0"
|
||||||
|
package_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_info_plus_platform_interface
|
||||||
|
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.0"
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.0+1
|
version: "6.0.0-pre.1"
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.6.0 <4.0.0"
|
sdk: ">=3.6.0 <4.0.0"
|
||||||
@ -39,6 +39,7 @@ dependencies:
|
|||||||
flutter_bloc: ^9.1.1
|
flutter_bloc: ^9.1.1
|
||||||
gap: ^3.0.1
|
gap: ^3.0.1
|
||||||
http: ^1.4.0
|
http: ^1.4.0
|
||||||
|
package_info_plus: ^8.3.0
|
||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
url_launcher: ^6.3.1
|
url_launcher: ^6.3.1
|
||||||
window_manager: ^0.5.0
|
window_manager: ^0.5.0
|
||||||
@ -68,6 +69,8 @@ flutter:
|
|||||||
# assets:
|
# assets:
|
||||||
# - images/a_dot_burr.jpeg
|
# - images/a_dot_burr.jpeg
|
||||||
# - images/a_dot_ham.jpeg
|
# - images/a_dot_ham.jpeg
|
||||||
|
assets:
|
||||||
|
- assets/img/
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/to/resolution-aware-images
|
# https://flutter.dev/to/resolution-aware-images
|
||||||
|
Loading…
x
Reference in New Issue
Block a user