diff --git a/FLUTTER_VERSION b/FLUTTER_VERSION index d9b2ac5..b7bc73b 100644 --- a/FLUTTER_VERSION +++ b/FLUTTER_VERSION @@ -1 +1 @@ -3.22.3 \ No newline at end of file +3.24.0 \ No newline at end of file diff --git a/app/android/settings.gradle b/app/android/settings.gradle index ba46a4c..64d25b7 100644 --- a/app/android/settings.gradle +++ b/app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.5.0' apply false + id "com.android.application" version '8.5.1' apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/app/lib/bloc/board.dart b/app/lib/bloc/board.dart index 341a3c9..667027d 100644 --- a/app/lib/bloc/board.dart +++ b/app/lib/bloc/board.dart @@ -14,7 +14,11 @@ class BoardBloc extends Bloc { )); }); on((event, emit) { - emit(state.copyWith(selectedCell: event.cell)); + emit(state.copyWith( + selectedCell: event.cell, + selectedDeck: null, + showHand: true, + )); }); on((event, emit) { emit(state.copyWith.table.cells.replace( diff --git a/app/lib/board/game.dart b/app/lib/board/game.dart index b3aaf41..c7cf566 100644 --- a/app/lib/board/game.dart +++ b/app/lib/board/game.dart @@ -12,7 +12,7 @@ import 'package:quokka/board/grid.dart'; import 'package:quokka/board/hand/view.dart'; import 'package:quokka/helpers/asset.dart'; import 'package:quokka/helpers/scroll.dart'; -import 'package:quokka/services/pack.dart'; +import 'package:quokka/services/file_system.dart'; class BoardGame extends FlameGame with ScrollDetector { final AssetManager assetManager; @@ -22,9 +22,10 @@ class BoardGame extends FlameGame with ScrollDetector { final BoardBloc bloc; BoardGame({ - PackService? packService, + QuokkaFileSystem? fileSystem, required this.bloc, - }) : assetManager = AssetManager(packService: packService ?? PackService()); + }) : assetManager = + AssetManager(fileSystem: fileSystem ?? QuokkaFileSystem()); @override FutureOr onLoad() async { @@ -59,7 +60,5 @@ class BoardGame extends FlameGame with ScrollDetector { .whereType() .firstOrNull; component?.onScroll(info); - /*clampZoom(camera.viewfinder.zoom + - info.scrollDelta.global.y.sign * zoomPerScrollUnit);*/ } } diff --git a/app/lib/board/grid.dart b/app/lib/board/grid.dart index b7bd342..617079e 100644 --- a/app/lib/board/grid.dart +++ b/app/lib/board/grid.dart @@ -110,4 +110,10 @@ class BoardGrid extends PositionComponent with HasGameRef { super.update(dt); _updateGrid(); } + + @override + void onParentResize(Vector2 maxSize) { + super.onParentResize(maxSize); + _updateGrid(); + } } diff --git a/app/lib/board/hand/deck.dart b/app/lib/board/hand/deck.dart index e7f98f8..7a4d680 100644 --- a/app/lib/board/hand/deck.dart +++ b/app/lib/board/hand/deck.dart @@ -2,8 +2,8 @@ import 'package:flame/components.dart'; import 'package:quokka/bloc/board_event.dart'; import 'package:quokka/board/cell.dart'; import 'package:quokka/board/hand/item.dart'; -import 'package:quokka/models/definitions/deck.dart'; -import 'package:quokka/models/definitions/pack.dart'; +import 'package:quokka/models/deck.dart'; +import 'package:quokka/models/data.dart'; import 'package:quokka/models/table.dart'; class DeckDefinitionHandItem extends HandItem> { diff --git a/app/lib/board/hand/figure.dart b/app/lib/board/hand/figure.dart index 7706ec1..cf00029 100644 --- a/app/lib/board/hand/figure.dart +++ b/app/lib/board/hand/figure.dart @@ -2,8 +2,8 @@ import 'package:flame/widgets.dart'; import 'package:quokka/bloc/board_event.dart'; import 'package:quokka/board/cell.dart'; import 'package:quokka/board/hand/item.dart'; -import 'package:quokka/models/definitions/object.dart'; -import 'package:quokka/models/definitions/pack.dart'; +import 'package:quokka/models/object.dart'; +import 'package:quokka/models/data.dart'; import 'package:quokka/models/table.dart'; class FigureDefinitionHandItem diff --git a/app/lib/board/hand/view.dart b/app/lib/board/hand/view.dart index 0ab2088..571b2e3 100644 --- a/app/lib/board/hand/view.dart +++ b/app/lib/board/hand/view.dart @@ -14,9 +14,9 @@ import 'package:quokka/board/hand/figure.dart'; import 'package:quokka/board/hand/item.dart'; import 'package:quokka/board/hand/object.dart'; import 'package:quokka/helpers/scroll.dart'; -import 'package:quokka/models/definitions/deck.dart'; -import 'package:quokka/models/definitions/object.dart'; -import 'package:quokka/models/definitions/pack.dart'; +import 'package:quokka/models/deck.dart'; +import 'package:quokka/models/object.dart'; +import 'package:quokka/models/data.dart'; import 'package:quokka/models/table.dart'; import 'package:quokka/models/vector.dart'; diff --git a/app/lib/helpers/asset.dart b/app/lib/helpers/asset.dart index b27e20b..5b250a2 100644 --- a/app/lib/helpers/asset.dart +++ b/app/lib/helpers/asset.dart @@ -4,22 +4,23 @@ import 'package:flame/game.dart'; import 'package:flame/sprite.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:quokka/models/definitions/pack.dart'; +import 'package:quokka/models/data.dart'; import 'package:quokka/models/table.dart'; -import 'package:quokka/services/pack.dart'; +import 'package:quokka/services/file_system.dart'; class AssetManager { - final PackService packService; - final Map _loadedPacks = {}; + final QuokkaFileSystem fileSystem; + final Map _loadedPacks = {}; final Map _cachedImages = {}; - Iterable> get loadedPacks => _loadedPacks.entries; + Iterable> get loadedPacks => + _loadedPacks.entries; AssetManager({ - required this.packService, + required this.fileSystem, }); - Iterable> get packs => _loadedPacks.entries; + Iterable> get packs => _loadedPacks.entries; Uint8List? getTexture(String key) => getTextureFromLocation(ItemLocation.fromString(key)); @@ -76,13 +77,13 @@ class AssetManager { ); } - PackData? getPack(String key) => _loadedPacks[key]; + QuokkaData? getPack(String key) => _loadedPacks[key]; - Future loadPack(String key, - {PackData? pack, bool force = false}) async { + Future loadPack(String key, + {QuokkaData? pack, bool force = false}) async { final oldPack = _loadedPacks[key]; if (!force && oldPack != null) return oldPack; - pack ??= await packService.loadPack(key); + pack ??= await fileSystem.getPack(key); if (pack == null) return null; unloadPack(key); _loadedPacks[key] = pack; diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 46ffbd9..6137790 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -99,5 +99,6 @@ "welcome": "Hey, this is Linwood Quokka", "welcomeContent": "A free and open-source tabletop simulator", "objects": "Objects", - "figures": "Figures" + "figures": "Figures", + "noGames": "There are no games available" } diff --git a/app/lib/main.dart b/app/lib/main.dart index 1585091..5378f84 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -13,7 +13,7 @@ import 'package:quokka/pages/home/page.dart'; import 'package:quokka/pages/settings/data.dart'; import 'package:quokka/pages/settings/general.dart'; import 'package:quokka/pages/settings/personalization.dart'; -import 'package:quokka/services/pack.dart'; +import 'package:quokka/services/file_system.dart'; import 'package:quokka/theme.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_localized_locales/flutter_localized_locales.dart'; @@ -50,7 +50,7 @@ Future main(List args) async { ], child: MultiRepositoryProvider( providers: [ - RepositoryProvider(create: (context) => PackService()), + RepositoryProvider(create: (context) => QuokkaFileSystem()), ], child: QuokkaApp(), ), diff --git a/app/lib/models/definitions/pack.dart b/app/lib/models/data.dart similarity index 80% rename from app/lib/models/definitions/pack.dart rename to app/lib/models/data.dart index ce2d89a..b8c4d68 100644 --- a/app/lib/models/definitions/pack.dart +++ b/app/lib/models/data.dart @@ -3,9 +3,10 @@ import 'dart:convert'; import 'package:archive/archive.dart'; import 'package:collection/collection.dart'; import 'package:flutter/services.dart'; -import 'package:quokka/models/definitions/deck.dart'; -import 'package:quokka/models/definitions/meta.dart'; -import 'package:quokka/models/definitions/object.dart'; +import 'package:lw_file_system/lw_file_system.dart'; +import 'package:quokka/models/deck.dart'; +import 'package:quokka/models/meta.dart'; +import 'package:quokka/models/object.dart'; import 'package:quokka/models/table.dart'; const kPackMetadataPath = 'pack.json'; @@ -15,26 +16,38 @@ const kPackBoardsPath = 'boards'; const kPackTexturesPath = 'textures'; const kPackTranslationsPath = 'translations'; -class PackData { - final Archive archive; +const kGameTablePath = 'tables'; - PackData(this.archive); +class QuokkaData extends ArchiveData { + QuokkaData(super.archive, {super.state}); - factory PackData.fromData(Uint8List data) { - return PackData(ZipDecoder().decodeBytes(data)); + factory QuokkaData.fromData(Uint8List data) { + return QuokkaData(ZipDecoder().decodeBytes(data)); } - static Future getCorePack() async => PackData.fromData( + static Future getCorePack() async => QuokkaData.fromData( (await rootBundle.load('assets/pack.qka')).buffer.asUint8List()); Uint8List? getAsset(String path) => archive.findFile(path)?.content; + void setAsset(String path, Uint8List data) { + archive.addFile(ArchiveFile(path, data.length, data)); + } - PackMetadata? getMetadata() { + GameTable? getTable() { + final data = getAsset('$kGameTablePath/.json'); + if (data == null) return null; + final content = utf8.decode(data); + return GameTableMapper.fromJson(content); + } + + void setTable(GameTable table) {} + + FileMetadata? getMetadata() { final data = getAsset(kPackMetadataPath); if (data == null) { return null; } final content = utf8.decode(data); - return PackMetadataMapper.fromJson(content); + return FileMetadataMapper.fromJson(content); } Iterable getAssets(String path, [bool removeExtension = false]) => { @@ -121,12 +134,10 @@ class PackData { String getTranslationOrKey(String path, String key) => getTranslation(path, key) ?? key; - - Uint8List export() => Uint8List.fromList(ZipEncoder().encode(archive) ?? []); } final class PackItem { - final PackData pack; + final QuokkaData pack; final ItemLocation location; final T item; @@ -137,7 +148,7 @@ final class PackItem { }); factory PackItem.fromRaw( - {required PackData pack, + {required QuokkaData pack, required String namespace, required String path, required T item}) => @@ -148,7 +159,7 @@ final class PackItem { ); static PackItem? wrap( - {required PackData pack, + {required QuokkaData pack, required String namespace, T? item, String? id}) { diff --git a/app/lib/models/definitions/deck.dart b/app/lib/models/deck.dart similarity index 100% rename from app/lib/models/definitions/deck.dart rename to app/lib/models/deck.dart diff --git a/app/lib/models/definitions/deck.mapper.dart b/app/lib/models/deck.mapper.dart similarity index 100% rename from app/lib/models/definitions/deck.mapper.dart rename to app/lib/models/deck.mapper.dart diff --git a/app/lib/models/definitions/meta.mapper.dart b/app/lib/models/definitions/meta.mapper.dart deleted file mode 100644 index 68115a9..0000000 --- a/app/lib/models/definitions/meta.mapper.dart +++ /dev/null @@ -1,139 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// ignore_for_file: unused_element, unnecessary_cast, override_on_non_overriding_member -// ignore_for_file: strict_raw_type, inference_failure_on_untyped_parameter - -part of 'meta.dart'; - -class PackMetadataMapper extends ClassMapperBase { - PackMetadataMapper._(); - - static PackMetadataMapper? _instance; - static PackMetadataMapper ensureInitialized() { - if (_instance == null) { - MapperContainer.globals.use(_instance = PackMetadataMapper._()); - } - return _instance!; - } - - @override - final String id = 'PackMetadata'; - - static String _$name(PackMetadata v) => v.name; - static const Field _f$name = - Field('name', _$name, opt: true, def: ''); - static String _$description(PackMetadata v) => v.description; - static const Field _f$description = - Field('description', _$description, opt: true, def: ''); - static String _$author(PackMetadata v) => v.author; - static const Field _f$author = - Field('author', _$author, opt: true, def: ''); - static String _$version(PackMetadata v) => v.version; - static const Field _f$version = - Field('version', _$version, opt: true, def: ''); - - @override - final MappableFields fields = const { - #name: _f$name, - #description: _f$description, - #author: _f$author, - #version: _f$version, - }; - - static PackMetadata _instantiate(DecodingData data) { - return PackMetadata( - name: data.dec(_f$name), - description: data.dec(_f$description), - author: data.dec(_f$author), - version: data.dec(_f$version)); - } - - @override - final Function instantiate = _instantiate; - - static PackMetadata fromMap(Map map) { - return ensureInitialized().decodeMap(map); - } - - static PackMetadata fromJson(String json) { - return ensureInitialized().decodeJson(json); - } -} - -mixin PackMetadataMappable { - String toJson() { - return PackMetadataMapper.ensureInitialized() - .encodeJson(this as PackMetadata); - } - - Map toMap() { - return PackMetadataMapper.ensureInitialized() - .encodeMap(this as PackMetadata); - } - - PackMetadataCopyWith get copyWith => - _PackMetadataCopyWithImpl(this as PackMetadata, $identity, $identity); - @override - String toString() { - return PackMetadataMapper.ensureInitialized() - .stringifyValue(this as PackMetadata); - } - - @override - bool operator ==(Object other) { - return PackMetadataMapper.ensureInitialized() - .equalsValue(this as PackMetadata, other); - } - - @override - int get hashCode { - return PackMetadataMapper.ensureInitialized() - .hashValue(this as PackMetadata); - } -} - -extension PackMetadataValueCopy<$R, $Out> - on ObjectCopyWith<$R, PackMetadata, $Out> { - PackMetadataCopyWith<$R, PackMetadata, $Out> get $asPackMetadata => - $base.as((v, t, t2) => _PackMetadataCopyWithImpl(v, t, t2)); -} - -abstract class PackMetadataCopyWith<$R, $In extends PackMetadata, $Out> - implements ClassCopyWith<$R, $In, $Out> { - $R call({String? name, String? description, String? author, String? version}); - PackMetadataCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); -} - -class _PackMetadataCopyWithImpl<$R, $Out> - extends ClassCopyWithBase<$R, PackMetadata, $Out> - implements PackMetadataCopyWith<$R, PackMetadata, $Out> { - _PackMetadataCopyWithImpl(super.value, super.then, super.then2); - - @override - late final ClassMapperBase $mapper = - PackMetadataMapper.ensureInitialized(); - @override - $R call( - {String? name, - String? description, - String? author, - String? version}) => - $apply(FieldCopyWithData({ - if (name != null) #name: name, - if (description != null) #description: description, - if (author != null) #author: author, - if (version != null) #version: version - })); - @override - PackMetadata $make(CopyWithData data) => PackMetadata( - name: data.get(#name, or: $value.name), - description: data.get(#description, or: $value.description), - author: data.get(#author, or: $value.author), - version: data.get(#version, or: $value.version)); - - @override - PackMetadataCopyWith<$R2, PackMetadata, $Out2> $chain<$R2, $Out2>( - Then<$Out2, $R2> t) => - _PackMetadataCopyWithImpl($value, $cast, t); -} diff --git a/app/lib/models/definitions/meta.dart b/app/lib/models/meta.dart similarity index 52% rename from app/lib/models/definitions/meta.dart rename to app/lib/models/meta.dart index a9894e0..931612f 100644 --- a/app/lib/models/definitions/meta.dart +++ b/app/lib/models/meta.dart @@ -2,17 +2,28 @@ import 'package:dart_mappable/dart_mappable.dart'; part 'meta.mapper.dart'; +@MappableEnum() +enum FileType { + pack, + game, + template, +} + @MappableClass() -class PackMetadata with PackMetadataMappable { +final class FileMetadata with FileMetadataMappable { + final FileType type; final String name; final String description; final String author; final String version; + final Set dependencies; - PackMetadata({ + const FileMetadata({ + this.type = FileType.pack, this.name = '', this.description = '', this.author = '', this.version = '', + this.dependencies = const {}, }); } diff --git a/app/lib/models/meta.mapper.dart b/app/lib/models/meta.mapper.dart new file mode 100644 index 0000000..4696b6a --- /dev/null +++ b/app/lib/models/meta.mapper.dart @@ -0,0 +1,212 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, unnecessary_cast, override_on_non_overriding_member +// ignore_for_file: strict_raw_type, inference_failure_on_untyped_parameter + +part of 'meta.dart'; + +class FileTypeMapper extends EnumMapper { + FileTypeMapper._(); + + static FileTypeMapper? _instance; + static FileTypeMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = FileTypeMapper._()); + } + return _instance!; + } + + static FileType fromValue(dynamic value) { + ensureInitialized(); + return MapperContainer.globals.fromValue(value); + } + + @override + FileType decode(dynamic value) { + switch (value) { + case 'pack': + return FileType.pack; + case 'game': + return FileType.game; + case 'template': + return FileType.template; + default: + throw MapperException.unknownEnumValue(value); + } + } + + @override + dynamic encode(FileType self) { + switch (self) { + case FileType.pack: + return 'pack'; + case FileType.game: + return 'game'; + case FileType.template: + return 'template'; + } + } +} + +extension FileTypeMapperExtension on FileType { + String toValue() { + FileTypeMapper.ensureInitialized(); + return MapperContainer.globals.toValue(this) as String; + } +} + +class FileMetadataMapper extends ClassMapperBase { + FileMetadataMapper._(); + + static FileMetadataMapper? _instance; + static FileMetadataMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = FileMetadataMapper._()); + FileTypeMapper.ensureInitialized(); + } + return _instance!; + } + + @override + final String id = 'FileMetadata'; + + static FileType _$type(FileMetadata v) => v.type; + static const Field _f$type = + Field('type', _$type, opt: true, def: FileType.pack); + static String _$name(FileMetadata v) => v.name; + static const Field _f$name = + Field('name', _$name, opt: true, def: ''); + static String _$description(FileMetadata v) => v.description; + static const Field _f$description = + Field('description', _$description, opt: true, def: ''); + static String _$author(FileMetadata v) => v.author; + static const Field _f$author = + Field('author', _$author, opt: true, def: ''); + static String _$version(FileMetadata v) => v.version; + static const Field _f$version = + Field('version', _$version, opt: true, def: ''); + static Set _$dependencies(FileMetadata v) => v.dependencies; + static const Field> _f$dependencies = + Field('dependencies', _$dependencies, opt: true, def: const {}); + + @override + final MappableFields fields = const { + #type: _f$type, + #name: _f$name, + #description: _f$description, + #author: _f$author, + #version: _f$version, + #dependencies: _f$dependencies, + }; + + static FileMetadata _instantiate(DecodingData data) { + return FileMetadata( + type: data.dec(_f$type), + name: data.dec(_f$name), + description: data.dec(_f$description), + author: data.dec(_f$author), + version: data.dec(_f$version), + dependencies: data.dec(_f$dependencies)); + } + + @override + final Function instantiate = _instantiate; + + static FileMetadata fromMap(Map map) { + return ensureInitialized().decodeMap(map); + } + + static FileMetadata fromJson(String json) { + return ensureInitialized().decodeJson(json); + } +} + +mixin FileMetadataMappable { + String toJson() { + return FileMetadataMapper.ensureInitialized() + .encodeJson(this as FileMetadata); + } + + Map toMap() { + return FileMetadataMapper.ensureInitialized() + .encodeMap(this as FileMetadata); + } + + FileMetadataCopyWith get copyWith => + _FileMetadataCopyWithImpl(this as FileMetadata, $identity, $identity); + @override + String toString() { + return FileMetadataMapper.ensureInitialized() + .stringifyValue(this as FileMetadata); + } + + @override + bool operator ==(Object other) { + return FileMetadataMapper.ensureInitialized() + .equalsValue(this as FileMetadata, other); + } + + @override + int get hashCode { + return FileMetadataMapper.ensureInitialized() + .hashValue(this as FileMetadata); + } +} + +extension FileMetadataValueCopy<$R, $Out> + on ObjectCopyWith<$R, FileMetadata, $Out> { + FileMetadataCopyWith<$R, FileMetadata, $Out> get $asFileMetadata => + $base.as((v, t, t2) => _FileMetadataCopyWithImpl(v, t, t2)); +} + +abstract class FileMetadataCopyWith<$R, $In extends FileMetadata, $Out> + implements ClassCopyWith<$R, $In, $Out> { + $R call( + {FileType? type, + String? name, + String? description, + String? author, + String? version, + Set? dependencies}); + FileMetadataCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); +} + +class _FileMetadataCopyWithImpl<$R, $Out> + extends ClassCopyWithBase<$R, FileMetadata, $Out> + implements FileMetadataCopyWith<$R, FileMetadata, $Out> { + _FileMetadataCopyWithImpl(super.value, super.then, super.then2); + + @override + late final ClassMapperBase $mapper = + FileMetadataMapper.ensureInitialized(); + @override + $R call( + {FileType? type, + String? name, + String? description, + String? author, + String? version, + Set? dependencies}) => + $apply(FieldCopyWithData({ + if (type != null) #type: type, + if (name != null) #name: name, + if (description != null) #description: description, + if (author != null) #author: author, + if (version != null) #version: version, + if (dependencies != null) #dependencies: dependencies + })); + @override + FileMetadata $make(CopyWithData data) => FileMetadata( + type: data.get(#type, or: $value.type), + name: data.get(#name, or: $value.name), + description: data.get(#description, or: $value.description), + author: data.get(#author, or: $value.author), + version: data.get(#version, or: $value.version), + dependencies: data.get(#dependencies, or: $value.dependencies)); + + @override + FileMetadataCopyWith<$R2, FileMetadata, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t) => + _FileMetadataCopyWithImpl($value, $cast, t); +} diff --git a/app/lib/models/definitions/object.dart b/app/lib/models/object.dart similarity index 100% rename from app/lib/models/definitions/object.dart rename to app/lib/models/object.dart diff --git a/app/lib/models/definitions/object.mapper.dart b/app/lib/models/object.mapper.dart similarity index 100% rename from app/lib/models/definitions/object.mapper.dart rename to app/lib/models/object.mapper.dart diff --git a/app/lib/pages/game/page.dart b/app/lib/pages/game/page.dart index 3e898b9..c9bded1 100644 --- a/app/lib/pages/game/page.dart +++ b/app/lib/pages/game/page.dart @@ -10,7 +10,7 @@ import 'package:quokka/bloc/board.dart'; import 'package:quokka/bloc/board_event.dart'; import 'package:quokka/bloc/settings.dart'; import 'package:quokka/board/game.dart'; -import 'package:quokka/services/pack.dart'; +import 'package:quokka/services/file_system.dart'; class GamePage extends StatelessWidget { const GamePage({super.key}); @@ -62,7 +62,7 @@ class GamePage extends StatelessWidget { body: Builder( builder: (context) => GameWidget( game: BoardGame( - packService: PackService(), + fileSystem: context.read(), bloc: context.read(), ))), ), diff --git a/app/lib/pages/home/packs.dart b/app/lib/pages/home/packs.dart index b52d745..ddd9897 100644 --- a/app/lib/pages/home/packs.dart +++ b/app/lib/pages/home/packs.dart @@ -4,9 +4,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:material_leap/material_leap.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; -import 'package:quokka/models/definitions/meta.dart'; -import 'package:quokka/models/definitions/pack.dart'; -import 'package:quokka/services/pack.dart'; +import 'package:quokka/models/data.dart'; +import 'package:quokka/models/meta.dart'; +import 'package:quokka/services/file_system.dart'; import 'package:quokka/widgets/search.dart'; class PacksDialog extends StatefulWidget { @@ -24,10 +24,10 @@ class _PacksDialogState extends State vsync: this, duration: const Duration(milliseconds: 100), ); - late final PackService _service = context.read(); + late final QuokkaFileSystem _service = context.read(); late final TabController _tabController; - Future>? _packsFuture; - (PackData, String, bool)? _selectedPack; + Future>? _packsFuture; + (QuokkaData, String, bool)? _selectedPack; @override void initState() { @@ -58,7 +58,7 @@ class _PacksDialogState extends State } } - List _buildDetailsChildren(PackData pack, PackMetadata? metadata) { + List _buildDetailsChildren(QuokkaData pack, FileMetadata? metadata) { if (metadata == null) { return []; } @@ -71,7 +71,7 @@ class _PacksDialogState extends State } List _buildActionsChildren( - PackData pack, { + QuokkaData pack, { VoidCallback? onInstall, VoidCallback? onRemove, }) => @@ -104,7 +104,7 @@ class _PacksDialogState extends State _deselectPack(); final pack = _selectedPack?.$2; if (pack == null) return; - await _service.removePack(pack); + await _service.packSystem.deleteFile(pack); _reloadPacks(); } @@ -117,7 +117,7 @@ class _PacksDialogState extends State (_selectedPack?.$3 ?? false) && (_selectedPack?.$2.isNotEmpty ?? true) ? _removePack : null; - Future selectPack(PackData pack, String id, bool installed) async { + Future selectPack(QuokkaData pack, String id, bool installed) async { _controller.forward(); setState(() { _selectedPack = (pack, id, installed); @@ -165,7 +165,7 @@ class _PacksDialogState extends State ), const SizedBox(height: 8), Expanded( - child: FutureBuilder>( + child: FutureBuilder>( future: _packsFuture, builder: (context, snapshot) { final packs = snapshot.data?.entries.toList() ?? []; @@ -309,8 +309,8 @@ class _PacksDialogState extends State if (name.endsWith(qka)) { name = name.substring(0, name.length - qka.length); } - final pack = PackData.fromData(data); - await _service.fileSystem.updateFile( + final pack = QuokkaData.fromData(data); + await _service.packSystem.updateFile( name, pack, ); diff --git a/app/lib/pages/home/page.dart b/app/lib/pages/home/page.dart index d430871..1c901e3 100644 --- a/app/lib/pages/home/page.dart +++ b/app/lib/pages/home/page.dart @@ -4,7 +4,6 @@ import 'package:material_leap/material_leap.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:quokka/bloc/settings.dart'; import 'package:quokka/main.dart'; -import 'package:quokka/pages/home/connect.dart'; import 'package:quokka/pages/home/packs.dart'; import 'package:quokka/pages/home/play.dart'; @@ -57,14 +56,14 @@ class HomePage extends StatelessWidget { context: context, builder: (context) => const PlayDialog()), ), - ( + /* ( AppLocalizations.of(context).connect, PhosphorIconsLight.plugsConnected, () => showDialog( context: context, builder: (context) => const ConnectDialog()), - ), + ), */ ( AppLocalizations.of(context).packs, PhosphorIconsLight.package, diff --git a/app/lib/pages/home/play.dart b/app/lib/pages/home/play.dart index 412b0e7..3479a14 100644 --- a/app/lib/pages/home/play.dart +++ b/app/lib/pages/home/play.dart @@ -1,9 +1,13 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:go_router/go_router.dart'; +import 'package:lw_file_system/lw_file_system.dart'; import 'package:material_leap/material_leap.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; +import 'package:quokka/models/data.dart'; import 'package:quokka/pages/home/create.dart'; +import 'package:quokka/services/file_system.dart'; import 'package:quokka/widgets/loading.dart'; class PlayDialog extends StatefulWidget { @@ -14,11 +18,22 @@ class PlayDialog extends StatefulWidget { } class _PlayDialogState extends State with TickerProviderStateMixin { - int? _selectedGame; + String? _selectedGame; + late final TypedKeyFileSystem worldSystem; + late Stream> _gamesStream; + + @override + void initState() { + super.initState(); + worldSystem = context.read().worldSystem; + _gamesStream = () async* { + await worldSystem.initialize(); + yield* worldSystem.fetchFiles(); + }(); + } @override Widget build(BuildContext context) { - final games = List.generate(30, (index) => 'Game ${index + 1}'); return ResponsiveAlertDialog( title: Text(AppLocalizations.of(context).play), constraints: const BoxConstraints( @@ -31,17 +46,32 @@ class _PlayDialogState extends State with TickerProviderStateMixin { Flexible( child: Material( type: MaterialType.transparency, - child: ListView.builder( - itemCount: games.length, - itemBuilder: (context, index) { - return ListTile( - title: Text(games[index]), - selected: _selectedGame == index, - onTap: () => setState(() => - _selectedGame = index == _selectedGame ? null : index), - ); - }, - ), + child: StreamBuilder( + stream: _gamesStream, + builder: (context, snapshot) { + final games = snapshot.data?.entries.toList(); + if (games == null) { + return const Center(child: CircularProgressIndicator()); + } + if (games.isEmpty) { + return Center( + child: Text(AppLocalizations.of(context).noGames), + ); + } + return ListView.builder( + itemCount: games.length, + itemBuilder: (context, index) { + final entry = games[index]; + final name = entry.key; + final selected = _selectedGame == name; + return ListTile( + title: Text(name), + selected: selected, + onTap: () => setState(() => selected ? null : name), + ); + }, + ); + }), ), ), const Divider(), @@ -75,7 +105,7 @@ class _PlayDialogState extends State with TickerProviderStateMixin { GoRouter.of(context).go('/game'); } }, - label: Text('Play ${games[_selectedGame!]}'), + label: Text('Play $_selectedGame'), icon: const Icon(PhosphorIconsLight.play), ), ), diff --git a/app/lib/services/file_system.dart b/app/lib/services/file_system.dart new file mode 100644 index 0000000..be51066 --- /dev/null +++ b/app/lib/services/file_system.dart @@ -0,0 +1,56 @@ +import 'package:lw_file_system/lw_file_system.dart'; +import 'package:quokka/api/storage.dart'; +import 'package:quokka/models/data.dart'; + +class QuokkaFileSystem { + QuokkaData? _corePack; + final TypedKeyFileSystem packSystem, worldSystem; + + QuokkaFileSystem({ + QuokkaData? corePack, + }) : _corePack = corePack, + packSystem = TypedKeyFileSystem.build( + FileSystemConfig( + passwordStorage: SecureStoragePasswordStorage(), + storeName: 'packs', + getDirectory: (storage) async => + '${await getQuokkaDirectory()}/Packs', + database: 'quokka.db', + databaseVersion: 1, + keySuffix: '.qka', + ), + onDecode: QuokkaData.fromData, + onEncode: (data) => data.exportAsBytes(), + ), + worldSystem = TypedKeyFileSystem.build( + FileSystemConfig( + passwordStorage: SecureStoragePasswordStorage(), + storeName: 'worlds', + getDirectory: (storage) async => + '${await getQuokkaDirectory()}/Worlds', + database: 'quokka.db', + databaseVersion: 1, + keySuffix: '.qka', + ), + onDecode: QuokkaData.fromData, + onEncode: (data) => data.exportAsBytes(), + ); + + Future fetchCorePack() async => + _corePack ?? (_corePack = await QuokkaData.getCorePack()); + + Future> getPacks({ + bool fetchCore = true, + bool force = false, + }) async { + final corePack = fetchCore ? await fetchCorePack() : null; + await packSystem.initialize(); + return { + ...await packSystem.getFiles(), + if (corePack != null) '': corePack, + }; + } + + Future getPack(String packId) => + packId.isEmpty ? fetchCorePack() : packSystem.getFile(packId); +} diff --git a/app/lib/services/pack.dart b/app/lib/services/pack.dart deleted file mode 100644 index bd0bab0..0000000 --- a/app/lib/services/pack.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:lw_file_system/lw_file_system.dart'; -import 'package:quokka/api/storage.dart'; -import 'package:quokka/models/definitions/object.dart'; -import 'package:quokka/models/definitions/pack.dart'; - -class PackService { - PackData? _corePack; - final TypedKeyFileSystem fileSystem; - final Map _loadedPacks = {}; - - PackService({ - PackData? corePack, - }) : _corePack = corePack, - fileSystem = TypedKeyFileSystem.build( - FileSystemConfig( - passwordStorage: SecureStoragePasswordStorage(), - storeName: 'packs', - getDirectory: (storage) async => - '${await getQuokkaDirectory()}/Packs', - database: 'quokka.db', - databaseVersion: 1, - keySuffix: '.qka', - ), - onDecode: PackData.fromData, - onEncode: (data) => data.export(), - ); - - Future fetchCorePack() async => - _corePack ?? (_corePack = await PackData.getCorePack()); - - Future reloadPacks() async { - _loadedPacks.clear(); - _loadedPacks.addAll(await getPacks()); - } - - Future> getPacks({ - bool fetchCore = true, - bool force = false, - }) async { - final corePack = fetchCore ? await fetchCorePack() : null; - if (!force && _loadedPacks.isNotEmpty) { - return { - ..._loadedPacks, - if (corePack != null) '': corePack, - }; - } - await fileSystem.initialize(); - return { - ...await fileSystem.getFiles(), - if (corePack != null) '': corePack, - }; - } - - Future getPack(String packId) => - packId.isEmpty ? fetchCorePack() : fileSystem.getFile(packId); - - Set get loadedPacks => _loadedPacks.keys.toSet(); - - Future loadPack(String packId, {bool force = false}) async { - if (_loadedPacks.containsKey(packId) && !force) { - return _loadedPacks[packId]; - } - final pack = await getPack(packId); - if (pack != null) { - _loadedPacks[packId] = pack; - } - return pack; - } - - Future removePack(String packId) async { - await fileSystem.deleteFile(packId); - _loadedPacks.remove(packId); - } - - Future>> getFigures({ - Set filter = const {}, - Map? packs, - }) async { - final allPacks = (packs ?? await getPacks()) - .entries - .where((e) => filter.isEmpty || filter.contains(e.key)); - return allPacks - .expand((e) => e.value.getFigures().map((f) { - final item = e.value.getFigure(f); - if (item == null) return null; - return PackItem.fromRaw( - pack: e.value, - path: f, - namespace: e.key, - item: item, - ); - }).whereNotNull()) - .toList(); - } -} diff --git a/app/pubspec.lock b/app/pubspec.lock index d0c99bd..0fce3ce 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -5,18 +5,23 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" + sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 url: "https://pub.dev" source: hosted - version: "67.0.0" + version: "72.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.2" analyzer: dependency: transitive description: name: analyzer - sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" + sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 url: "https://pub.dev" source: hosted - version: "6.4.1" + version: "6.7.0" ansicolor: dependency: transitive description: @@ -109,18 +114,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" + sha256: dd09dd4e2b078992f42aac7f1a622f01882a8492fef08486b27ddde929c19f04 url: "https://pub.dev" source: hosted - version: "2.4.11" + version: "2.4.12" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 url: "https://pub.dev" source: hosted - version: "7.3.1" + version: "7.3.2" built_collection: dependency: transitive description: @@ -610,18 +615,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -650,8 +655,8 @@ packages: dependency: "direct main" description: path: "packages/lw_file_system" - ref: "509b5800dcf8bad400ab6ae12184631a3db1e189" - resolved-ref: "509b5800dcf8bad400ab6ae12184631a3db1e189" + ref: e5214800f59a8f719ed8ed7a695f8835f8454106 + resolved-ref: e5214800f59a8f719ed8ed7a695f8835f8454106 url: "https://github.com/LinwoodDev/dart_pkgs.git" source: git version: "1.0.0" @@ -659,8 +664,8 @@ packages: dependency: transitive description: path: "packages/lw_file_system_api" - ref: d0c9eb7d403eba898153fe2c03016aa83050cf69 - resolved-ref: d0c9eb7d403eba898153fe2c03016aa83050cf69 + ref: "02cd42c24b1c307ab12167b8b1b86cffd8aa0487" + resolved-ref: "02cd42c24b1c307ab12167b8b1b86cffd8aa0487" url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "1.0.0" @@ -668,11 +673,19 @@ packages: dependency: "direct main" description: path: "packages/lw_sysapi" - ref: bf247737e215187d1f643f76d0b3a29ed934ecbd - resolved-ref: bf247737e215187d1f643f76d0b3a29ed934ecbd + ref: "8bef88569885efb6901177e9074b88b693ed9fce" + resolved-ref: "8bef88569885efb6901177e9074b88b693ed9fce" url: "https://github.com/LinwoodDev/dart_pkgs.git" source: git version: "0.0.1" + macros: + dependency: transitive + description: + name: macros + sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" + url: "https://pub.dev" + source: hosted + version: "0.1.2-main.4" matcher: dependency: transitive description: @@ -685,10 +698,10 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" material_leap: dependency: "direct main" description: @@ -702,10 +715,10 @@ packages: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" mime: dependency: transitive description: @@ -856,10 +869,10 @@ packages: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" plugin_platform_interface: dependency: transitive description: @@ -1117,10 +1130,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.2" tiled: dependency: transitive description: @@ -1205,10 +1218,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: a36e2d7981122fa185006b216eb6b5b97ede3f9a54b7a511bc966971ab98d049 + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" url_launcher_windows: dependency: transitive description: @@ -1261,10 +1274,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.4" watcher: dependency: transitive description: @@ -1354,5 +1367,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.1 <4.0.0" + dart: ">=3.5.0-259.0.dev <4.0.0" flutter: ">=3.22.0" diff --git a/app/pubspec.yaml b/app/pubspec.yaml index c8b6f01..1813451 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -34,7 +34,7 @@ dependencies: lw_file_system: git: url: https://github.com/LinwoodDev/dart_pkgs.git - ref: 509b5800dcf8bad400ab6ae12184631a3db1e189 + ref: e5214800f59a8f719ed8ed7a695f8835f8454106 path: packages/lw_file_system material_leap: git: @@ -44,7 +44,7 @@ dependencies: lw_sysapi: git: url: https://github.com/LinwoodDev/dart_pkgs.git - ref: bf247737e215187d1f643f76d0b3a29ed934ecbd + ref: 8bef88569885efb6901177e9074b88b693ed9fce path: packages/lw_sysapi flex_color_scheme: git: diff --git a/docs/package.json b/docs/package.json index 3dc4468..4d12737 100644 --- a/docs/package.json +++ b/docs/package.json @@ -10,11 +10,11 @@ "astro": "astro" }, "dependencies": { - "@astrojs/check": "^0.9.1", - "@astrojs/starlight": "^0.25.3", + "@astrojs/check": "^0.9.2", + "@astrojs/starlight": "^0.25.4", "astro": "^4.13.1", "sharp": "^0.33.4", "typescript": "^5.5.4" }, - "packageManager": "pnpm@9.6.0" + "packageManager": "pnpm@9.7.0" } diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index 35b7c62..484ee57 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -9,11 +9,11 @@ importers: .: dependencies: '@astrojs/check': - specifier: ^0.9.1 - version: 0.9.1(typescript@5.5.4) + specifier: ^0.9.2 + version: 0.9.2(typescript@5.5.4) '@astrojs/starlight': - specifier: ^0.25.3 - version: 0.25.3(astro@4.13.1(typescript@5.5.4)) + specifier: ^0.25.4 + version: 0.25.4(astro@4.13.1(typescript@5.5.4)) astro: specifier: ^4.13.1 version: 4.13.1(typescript@5.5.4) @@ -30,20 +30,20 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@astrojs/check@0.9.1': - resolution: {integrity: sha512-VvN5ukVzg0IccKuZlI/pdsp4MSpHxWf9a36eOmS8Wpp+NM0MhJLYv3yvQC+qa472Kdf8DHEt/wmVZYwJUMFW+w==} + '@astrojs/check@0.9.2': + resolution: {integrity: sha512-6rWxtJTbd/ctdAlmla0CAvloGaai5IUTG0K21kctJHHGKJKnGH6Xana7m0zNOtHpVPEJi1SgC/TcsN+ltYt0Cg==} hasBin: true peerDependencies: typescript: ^5.0.0 - '@astrojs/compiler@2.10.1': - resolution: {integrity: sha512-XmM4j6BjvOVMag2xELq0JuG2yKOW8wgIu6dvb9BsjbGYmnvoStJn/pqEzVqc1EBszf2xYT7onIkftIOUz9AwrQ==} + '@astrojs/compiler@2.10.2': + resolution: {integrity: sha512-bvH+v8AirwpRWCkYJEyWYdc5Cs/BjG2ZTxIJzttHilXgfKJAdW2496KsUQKzf5j2tOHtaHXKKn9hb9WZiBGpEg==} '@astrojs/internal-helpers@0.4.1': resolution: {integrity: sha512-bMf9jFihO8YP940uD70SI/RDzIhUHJAolWVcO1v5PUivxGKvfLZTLTVVxEYzGYyPsA3ivdLNqMnL5VgmQySa+g==} - '@astrojs/language-server@2.13.1': - resolution: {integrity: sha512-Cl9ynfnge6+MaCpehYn7w9WrAE+sVS7onhxhMzCdqzPtIt/Yo5zIaiGZdu4QgvmOV/mdNBZCZgaTpAIeGjWwsQ==} + '@astrojs/language-server@2.13.2': + resolution: {integrity: sha512-l435EZLKjaUO/6iewJ7xqd3eHf3zAosVWG4woILbxluQcianBoNPepnnqAg7uUriZUaC44ae5v0Q+AfB8UI64g==} hasBin: true peerDependencies: prettier: ^3.0.0 @@ -70,8 +70,8 @@ packages: '@astrojs/sitemap@3.1.6': resolution: {integrity: sha512-1Qp2NvAzVImqA6y+LubKi1DVhve/hXXgFvB0szxiipzh7BvtuKe4oJJ9dXSqaubaTkt4nMa6dv6RCCAYeB6xaQ==} - '@astrojs/starlight@0.25.3': - resolution: {integrity: sha512-XNpGbZ54ungtzen4wQkPXn50D1ZquB51paWrZftA0jWxUkj4b/pP8PijAFrGFypydhvu7Dhl0DjD07lrnSSUhQ==} + '@astrojs/starlight@0.25.4': + resolution: {integrity: sha512-TRPgRsd5opi2tCXvh8rWizpLsJsRRXbYecULG5b/1x4BFyp40ZJVB77cLMjTj3lHwqWs0Sybtq5OBpOy6fuIEQ==} peerDependencies: astro: ^4.8.6 @@ -797,8 +797,8 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} - caniuse-lite@1.0.30001649: - resolution: {integrity: sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==} + caniuse-lite@1.0.30001650: + resolution: {integrity: sha512-fgEc7hP/LB7iicdXHUI9VsBsMZmUmlVJeQP2qqQW+3lkqVhbmjEU8zp+h5stWeilX+G7uXuIUIIlWlDw9jdt8g==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -947,8 +947,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.4: - resolution: {integrity: sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==} + electron-to-chromium@1.5.5: + resolution: {integrity: sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==} emmet@2.4.7: resolution: {integrity: sha512-O5O5QNqtdlnQM2bmKHtJgyChcrFMgQuulI+WdiOw2NArzprUqqxUW6bgYtKvzKgrsYpuLWalOkdhNP+1jluhCA==} @@ -1631,8 +1631,8 @@ packages: resolution: {integrity: sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==} engines: {node: '>=4'} - postcss@8.4.40: - resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} + postcss@8.4.41: + resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} engines: {node: ^10 || ^12 || >=14} preferred-pm@4.0.0: @@ -2127,9 +2127,9 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@astrojs/check@0.9.1(typescript@5.5.4)': + '@astrojs/check@0.9.2(typescript@5.5.4)': dependencies: - '@astrojs/language-server': 2.13.1(typescript@5.5.4) + '@astrojs/language-server': 2.13.2(typescript@5.5.4) chokidar: 3.6.0 fast-glob: 3.3.2 kleur: 4.1.5 @@ -2139,13 +2139,13 @@ snapshots: - prettier - prettier-plugin-astro - '@astrojs/compiler@2.10.1': {} + '@astrojs/compiler@2.10.2': {} '@astrojs/internal-helpers@0.4.1': {} - '@astrojs/language-server@2.13.1(typescript@5.5.4)': + '@astrojs/language-server@2.13.2(typescript@5.5.4)': dependencies: - '@astrojs/compiler': 2.10.1 + '@astrojs/compiler': 2.10.2 '@jridgewell/sourcemap-codec': 1.5.0 '@volar/kit': 2.4.0-alpha.18(typescript@5.5.4) '@volar/language-core': 2.4.0-alpha.18 @@ -2219,7 +2219,7 @@ snapshots: stream-replace-string: 2.0.0 zod: 3.23.8 - '@astrojs/starlight@0.25.3(astro@4.13.1(typescript@5.5.4))': + '@astrojs/starlight@0.25.4(astro@4.13.1(typescript@5.5.4))': dependencies: '@astrojs/mdx': 3.1.3(astro@4.13.1(typescript@5.5.4)) '@astrojs/sitemap': 3.1.6 @@ -2498,8 +2498,8 @@ snapshots: hast-util-to-html: 9.0.1 hast-util-to-text: 4.0.2 hastscript: 9.0.0 - postcss: 8.4.40 - postcss-nested: 6.2.0(postcss@8.4.40) + postcss: 8.4.41 + postcss-nested: 6.2.0(postcss@8.4.41) unist-util-visit: 5.0.0 unist-util-visit-parents: 6.0.1 @@ -2890,7 +2890,7 @@ snapshots: astro@4.13.1(typescript@5.5.4): dependencies: - '@astrojs/compiler': 2.10.1 + '@astrojs/compiler': 2.10.2 '@astrojs/internal-helpers': 0.4.1 '@astrojs/markdown-remark': 5.2.0 '@astrojs/telemetry': 3.1.0 @@ -2999,14 +2999,14 @@ snapshots: browserslist@4.23.3: dependencies: - caniuse-lite: 1.0.30001649 - electron-to-chromium: 1.5.4 + caniuse-lite: 1.0.30001650 + electron-to-chromium: 1.5.5 node-releases: 2.0.18 update-browserslist-db: 1.1.0(browserslist@4.23.3) camelcase@7.0.1: {} - caniuse-lite@1.0.30001649: {} + caniuse-lite@1.0.30001650: {} ccount@2.0.1: {} @@ -3130,7 +3130,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.4: {} + electron-to-chromium@1.5.5: {} emmet@2.4.7: dependencies: @@ -4195,9 +4195,9 @@ snapshots: dependencies: find-up: 4.1.0 - postcss-nested@6.2.0(postcss@8.4.40): + postcss-nested@6.2.0(postcss@8.4.41): dependencies: - postcss: 8.4.40 + postcss: 8.4.41 postcss-selector-parser: 6.1.1 postcss-selector-parser@6.1.1: @@ -4205,7 +4205,7 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss@8.4.40: + postcss@8.4.41: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 @@ -4635,7 +4635,7 @@ snapshots: vite@5.3.5: dependencies: esbuild: 0.21.5 - postcss: 8.4.40 + postcss: 8.4.41 rollup: 4.20.0 optionalDependencies: fsevents: 2.3.3