diff --git a/api/lib/src/converter/color.dart b/api/lib/src/converter/color.dart new file mode 100644 index 000000000000..d6385895105e --- /dev/null +++ b/api/lib/src/converter/color.dart @@ -0,0 +1,16 @@ +import 'package:dart_leap/dart_leap.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +class ColorJsonConverter extends JsonConverter { + const ColorJsonConverter(); + + @override + SRGBColor fromJson(int json) { + return SRGBColor(json); + } + + @override + int toJson(SRGBColor object) { + return object.value; + } +} diff --git a/api/lib/src/converter/note.dart b/api/lib/src/converter/note.dart index 952c31a68283..e78006761476 100644 --- a/api/lib/src/converter/note.dart +++ b/api/lib/src/converter/note.dart @@ -7,19 +7,19 @@ import '../../butterfly_api.dart'; const kArchiveSignature = 0x50; -NoteData noteDataMigrator(Uint8List data) { +NoteData noteDataMigrator(Uint8List data, {String? password}) { Archive archive; if (data.isNotEmpty && data[0] != kArchiveSignature) { final map = json.decode(utf8.decode(data)) as Map; archive = convertLegacyDataToArchive(map); } else { - archive = ZipDecoder().decodeBytes(data); + archive = ZipDecoder().decodeBytes(data, password: password); } - return archiveNoteDataMigrator(archive); + return archiveNoteDataMigrator(archive, password: password); } -NoteData archiveNoteDataMigrator(Archive archive) { - var noteData = NoteData(archive); +NoteData archiveNoteDataMigrator(Archive archive, {String? password}) { + var noteData = NoteData.build(archive, password: password); var metadata = noteData.getMetadata(); if (metadata != null && (metadata.fileVersion ?? kFileVersion) < kFileVersion) { @@ -52,7 +52,7 @@ NoteData _migrate(NoteData noteData, FileMetadata metadata) { } } if (version < 10) { - for (final page in noteData.getAssets(kPagesArchiveDirectory)) { + for (final page in noteData.getAssets('$kPagesArchiveDirectory/')) { final data = noteData.getAsset('$kPagesArchiveDirectory/$page'); if (data == null) continue; final pageData = json.decode(utf8.decode(data)) as Map; @@ -89,7 +89,7 @@ NoteData _migrate(NoteData noteData, FileMetadata metadata) { } } if (version < 11) { - for (final page in noteData.getAssets(kPagesArchiveDirectory)) { + for (final page in noteData.getAssets('$kPagesArchiveDirectory/')) { final data = noteData.getAsset('$kPagesArchiveDirectory/$page'); if (data == null) continue; final pageData = json.decode(utf8.decode(data)) as Map; diff --git a/api/lib/src/converter/xopp.dart b/api/lib/src/converter/xopp.dart index e327bd906d2c..4d5841713110 100644 --- a/api/lib/src/converter/xopp.dart +++ b/api/lib/src/converter/xopp.dart @@ -5,6 +5,7 @@ import 'dart:typed_data'; import 'package:archive/archive.dart'; import 'package:butterfly_api/butterfly_api.dart'; import 'package:butterfly_api/butterfly_text.dart' as text; +import 'package:dart_leap/dart_leap.dart'; import 'package:xml/xml.dart'; List toPoints(List data) { @@ -20,14 +21,12 @@ List toPoints(List data) { return points; } -int _importColor(String value) { - final number = int.parse(value.substring(1), radix: 16); - return (number >> 8 | number << 24); +SRGBColor _importColor(String value) { + return SRGBColor.parse(value); } -String _exportColor(int value) { - final number = (value >> 8 | value << 24); - return '#${number.toRadixString(16)}'; +String _exportColor(SRGBColor value) { + return value.toHexString(); } (NoteData, PadElement?) getElement( @@ -161,8 +160,8 @@ Uint8List xoppExporter(NoteData document) { builder.element('page', nest: () { builder.element('background', attributes: { 'type': 'solid', - 'color': - _exportColor(page.backgrounds.firstOrNull?.defaultColor ?? 0), + 'color': _exportColor( + page.backgrounds.firstOrNull?.defaultColor ?? SRGBColor.white), 'style': 'plain', }); builder.element('layer', nest: () { @@ -185,7 +184,7 @@ Uint8List xoppExporter(NoteData document) { ?.span : styleSheet?.getParagraphProperty('p')?.span; builder.element('text', attributes: { - 'color': _exportColor(style?.color ?? 0), + 'color': _exportColor(style?.color ?? SRGBColor.black), 'size': (style?.size ?? 12).toString(), 'x': e.position.x.toString(), 'y': e.position.y.toString(), diff --git a/api/lib/src/models/asset.dart b/api/lib/src/models/asset.dart index 30dd4690bd73..a9eea32b22fd 100644 --- a/api/lib/src/models/asset.dart +++ b/api/lib/src/models/asset.dart @@ -1,16 +1,8 @@ -import 'dart:typed_data'; - import 'package:butterfly_api/butterfly_api.dart'; import 'package:lw_file_system_api/lw_file_system_api.dart'; enum AssetFileType { note, page, image, markdown, pdf, svg, xopp, archive } -extension AppDocumentLoadExtension on FileSystemFile { - NoteData load({bool disableMigrations = false}) => - NoteData.fromData(Uint8List.fromList(data), - disableMigrations: disableMigrations); -} - extension AssetLocationFileTypeExtension on AssetLocation { AssetFileType? get fileType => AssetFileTypeHelper.fromFileExtension(fileExtension); diff --git a/api/lib/src/models/background.dart b/api/lib/src/models/background.dart index c993d27a82f7..f2dd08e459aa 100644 --- a/api/lib/src/models/background.dart +++ b/api/lib/src/models/background.dart @@ -1,6 +1,6 @@ +import 'package:dart_leap/dart_leap.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'colors.dart'; import 'texture.dart'; part 'background.g.dart'; @@ -36,8 +36,8 @@ sealed class Background with _$Background { factory Background.fromJson(Map json) => _$BackgroundFromJson(json); - int get defaultColor => switch (this) { + SRGBColor get defaultColor => switch (this) { TextureBackground e => e.texture.boxColor, - _ => BasicColors.white + _ => SRGBColor.white }; } diff --git a/api/lib/src/models/colors.dart b/api/lib/src/models/colors.dart index b48c0532868e..ad8ec94cb21d 100644 --- a/api/lib/src/models/colors.dart +++ b/api/lib/src/models/colors.dart @@ -1,11 +1,10 @@ +import 'package:dart_leap/dart_leap.dart'; + class BasicColors { - static const white = 0xFFFFFFFF; - static const light = 0xFFD9D9D9; - static const black = 0xFF000000; - static const dark = 0xFF1A1A1A; - static const red = 0xFFF44336; - static const blue = 0xFF2196F3; - static const transparent = 0x00000000; + static const light = SRGBColor(0xFFD9D9D9); + static const dark = SRGBColor(0xFF1A1A1A); + static const red = SRGBColor(0xFFF44336); + static const blue = SRGBColor(0xFF2196F3); const BasicColors._(); } diff --git a/api/lib/src/models/data.dart b/api/lib/src/models/data.dart index 4509dd10c6fc..cf71e179656a 100644 --- a/api/lib/src/models/data.dart +++ b/api/lib/src/models/data.dart @@ -18,28 +18,56 @@ import 'palette.dart'; final Set validAssetPaths = {kImagesArchiveDirectory}; -@immutable +final class NoteFile { + final Uint8List data; + + NoteFile(this.data); + + bool isEncrypted() => isZipEncrypted(data); + + (String?, NoteData)? _data; + + NoteData? load({String? password}) { + if (_data != null && _data?.$1 == password) { + return _data?.$2; + } + try { + final data = NoteData.fromData(this.data, password: password); + _data = (password, data); + return data; + } catch (_) { + return null; + } + } +} + final class NoteData extends ArchiveData { NoteData(super.archive, {super.state}); + NoteData.build(super.archive, {super.password}) : super.build(); - factory NoteData.fromData(Uint8List data, {bool disableMigrations = false}) { + factory NoteData.fromData(Uint8List data, + {bool disableMigrations = false, String? password}) { if (disableMigrations) { - final archive = ZipDecoder().decodeBytes(data); - return NoteData(archive); + final archive = ZipDecoder().decodeBytes(data, password: password); + return NoteData.build(archive, password: password); } - return noteDataMigrator(data); + return noteDataMigrator(data, password: password); } factory NoteData.fromArchive(Archive archive, - {bool disableMigrations = false}) { + {bool disableMigrations = false, String? password}) { if (disableMigrations) { - return NoteData(archive); + return NoteData.build(archive, password: password); } return archiveNoteDataMigrator(archive); } - factory NoteData.fromJson(dynamic json) => NoteData.fromData( + factory NoteData.fromJson(dynamic json, + {bool disableMigrations = false, String? password}) => + NoteData.fromData( base64Decode(json as String), + disableMigrations: disableMigrations, + password: password, ); NoteFileType? get type => getMetadata()?.type; @@ -71,7 +99,7 @@ final class NoteData extends ArchiveData { '$name${fileExtension.isNotEmpty ? '.$fileExtension' : ''}'; String findUniqueName(String path, String fileExtension, [String name = '']) { - final assets = getAssets(path); + final assets = getAssets('$path/'); if (!assets.contains(_getFileName(name, fileExtension)) && name.trim().isNotEmpty) { return _getFileName(name, fileExtension); @@ -238,7 +266,7 @@ final class NoteData extends ArchiveData { @useResult List<(int, String, String)> _getPagesOrder() => - getAssets(kPagesArchiveDirectory, true).map((e) { + getAssets('$kPagesArchiveDirectory/', true).map((e) { if (e.contains('.')) { final split = e.split('.'); return ( @@ -319,13 +347,13 @@ final class NoteData extends ArchiveData { removeAsset('$kPacksArchiveDirectory/$name.bfly'); @useResult - Iterable getPacks() => getAssets(kPacksArchiveDirectory, true); + Iterable getPacks() => getAssets('$kPacksArchiveDirectory/', true); // Pack specific @useResult Iterable getComponents() => - getAssets(kComponentsArchiveDirectory, true); + getAssets('$kComponentsArchiveDirectory/', true); @useResult ButterflyComponent? getComponent(String componentName) { @@ -348,7 +376,7 @@ final class NoteData extends ArchiveData { removeAsset('$kComponentsArchiveDirectory/$name.json'); @useResult - Iterable getStyles() => getAssets(kStylesArchiveDirectory, true); + Iterable getStyles() => getAssets('$kStylesArchiveDirectory/', true); @useResult TextStyleSheet? getStyle(String styleName) { @@ -383,7 +411,8 @@ final class NoteData extends ArchiveData { } @useResult - Iterable getPalettes() => getAssets(kPalettesArchiveDirectory, true); + Iterable getPalettes() => + getAssets('$kPalettesArchiveDirectory/', true); @useResult ColorPalette? getPalette(String paletteName) { @@ -425,4 +454,6 @@ final class NoteData extends ArchiveData { final removed = Set.from(state.removed)..remove(path); return updateState(state.copyWith(removed: removed)); } + + NoteFile toFile() => NoteFile(exportAsBytes()); } diff --git a/api/lib/src/models/element.dart b/api/lib/src/models/element.dart index f4337c94c16d..1dcc7ec893f5 100644 --- a/api/lib/src/models/element.dart +++ b/api/lib/src/models/element.dart @@ -1,10 +1,12 @@ import 'dart:math'; +import 'package:butterfly_api/src/converter/color.dart'; +import 'package:dart_leap/dart_leap.dart'; + import '../converter/core.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import '../converter/id.dart'; -import 'colors.dart'; import 'pack.dart'; import 'point.dart'; import 'property.dart'; @@ -60,7 +62,7 @@ mixin LabelElement { double get scale; PackAssetLocation get styleSheet; ElementConstraint get constraint; - int get foreground; + SRGBColor get foreground; AreaProperty get areaProperty => switch (this) { MarkdownElement e => e.areaProperty, @@ -102,7 +104,7 @@ sealed class PadElement with _$PadElement { @Default(PackAssetLocation()) PackAssetLocation styleSheet, required TextArea area, @Default(ElementConstraint(size: 1000)) ElementConstraint constraint, - @Default(BasicColors.black) int foreground, + @Default(SRGBColor.black) @ColorJsonConverter() SRGBColor foreground, @Default({}) Map extra, }) = TextElement; @@ -119,7 +121,7 @@ sealed class PadElement with _$PadElement { @Default(AreaProperty()) AreaProperty areaProperty, required String text, @Default(ElementConstraint(size: 1000)) ElementConstraint constraint, - @Default(BasicColors.black) int foreground, + @Default(SRGBColor.black) @ColorJsonConverter() SRGBColor foreground, @Default({}) Map extra, }) = MarkdownElement; diff --git a/api/lib/src/models/element.freezed.dart b/api/lib/src/models/element.freezed.dart index ad8188395f6c..500792a17646 100644 --- a/api/lib/src/models/element.freezed.dart +++ b/api/lib/src/models/element.freezed.dart @@ -910,7 +910,7 @@ abstract class _$$TextElementImplCopyWith<$Res> PackAssetLocation styleSheet, TextArea area, ElementConstraint constraint, - int foreground, + @ColorJsonConverter() SRGBColor foreground, Map extra}); $PackAssetLocationCopyWith<$Res> get styleSheet; @@ -978,7 +978,7 @@ class __$$TextElementImplCopyWithImpl<$Res> foreground: null == foreground ? _value.foreground : foreground // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, extra: null == extra ? _value._extra : extra // ignore: cast_nullable_to_non_nullable @@ -1029,7 +1029,7 @@ class _$TextElementImpl extends TextElement with LabelElement { this.styleSheet = const PackAssetLocation(), required this.area, this.constraint = const ElementConstraint(size: 1000), - this.foreground = BasicColors.black, + @ColorJsonConverter() this.foreground = SRGBColor.black, final Map extra = const {}, final String? $type}) : _extra = extra, @@ -1065,7 +1065,8 @@ class _$TextElementImpl extends TextElement with LabelElement { final ElementConstraint constraint; @override @JsonKey() - final int foreground; + @ColorJsonConverter() + final SRGBColor foreground; final Map _extra; @override @JsonKey() @@ -1109,7 +1110,7 @@ abstract class TextElement extends PadElement implements LabelElement { final PackAssetLocation styleSheet, required final TextArea area, final ElementConstraint constraint, - final int foreground, + @ColorJsonConverter() final SRGBColor foreground, final Map extra}) = _$TextElementImpl; TextElement._() : super._(); @@ -1129,7 +1130,8 @@ abstract class TextElement extends PadElement implements LabelElement { PackAssetLocation get styleSheet; TextArea get area; ElementConstraint get constraint; - int get foreground; + @ColorJsonConverter() + SRGBColor get foreground; @override Map get extra; @@ -1159,7 +1161,7 @@ abstract class _$$MarkdownElementImplCopyWith<$Res> AreaProperty areaProperty, String text, ElementConstraint constraint, - int foreground, + @ColorJsonConverter() SRGBColor foreground, Map extra}); $PackAssetLocationCopyWith<$Res> get styleSheet; @@ -1232,7 +1234,7 @@ class __$$MarkdownElementImplCopyWithImpl<$Res> foreground: null == foreground ? _value.foreground : foreground // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, extra: null == extra ? _value._extra : extra // ignore: cast_nullable_to_non_nullable @@ -1284,7 +1286,7 @@ class _$MarkdownElementImpl extends MarkdownElement with LabelElement { this.areaProperty = const AreaProperty(), required this.text, this.constraint = const ElementConstraint(size: 1000), - this.foreground = BasicColors.black, + @ColorJsonConverter() this.foreground = SRGBColor.black, final Map extra = const {}, final String? $type}) : _extra = extra, @@ -1323,7 +1325,8 @@ class _$MarkdownElementImpl extends MarkdownElement with LabelElement { final ElementConstraint constraint; @override @JsonKey() - final int foreground; + @ColorJsonConverter() + final SRGBColor foreground; final Map _extra; @override @JsonKey() @@ -1369,7 +1372,7 @@ abstract class MarkdownElement extends PadElement implements LabelElement { final AreaProperty areaProperty, required final String text, final ElementConstraint constraint, - final int foreground, + @ColorJsonConverter() final SRGBColor foreground, final Map extra}) = _$MarkdownElementImpl; MarkdownElement._() : super._(); @@ -1390,7 +1393,8 @@ abstract class MarkdownElement extends PadElement implements LabelElement { AreaProperty get areaProperty; String get text; ElementConstraint get constraint; - int get foreground; + @ColorJsonConverter() + SRGBColor get foreground; @override Map get extra; diff --git a/api/lib/src/models/element.g.dart b/api/lib/src/models/element.g.dart index 4bcd229a9bcd..2e2f95c90fd0 100644 --- a/api/lib/src/models/element.g.dart +++ b/api/lib/src/models/element.g.dart @@ -123,7 +123,10 @@ _$TextElementImpl _$$TextElementImplFromJson(Map json) => _$TextElementImpl( ? const ElementConstraint(size: 1000) : ElementConstraint.fromJson( Map.from(json['constraint'] as Map)), - foreground: (json['foreground'] as num?)?.toInt() ?? BasicColors.black, + foreground: json['foreground'] == null + ? SRGBColor.black + : const ColorJsonConverter() + .fromJson((json['foreground'] as num).toInt()), extra: (json['extra'] as Map?)?.map( (k, e) => MapEntry(k as String, e), ) ?? @@ -141,7 +144,7 @@ Map _$$TextElementImplToJson(_$TextElementImpl instance) => 'styleSheet': instance.styleSheet.toJson(), 'area': instance.area.toJson(), 'constraint': instance.constraint.toJson(), - 'foreground': instance.foreground, + 'foreground': const ColorJsonConverter().toJson(instance.foreground), 'extra': instance.extra, 'type': instance.$type, }; @@ -168,7 +171,10 @@ _$MarkdownElementImpl _$$MarkdownElementImplFromJson(Map json) => ? const ElementConstraint(size: 1000) : ElementConstraint.fromJson( Map.from(json['constraint'] as Map)), - foreground: (json['foreground'] as num?)?.toInt() ?? BasicColors.black, + foreground: json['foreground'] == null + ? SRGBColor.black + : const ColorJsonConverter() + .fromJson((json['foreground'] as num).toInt()), extra: (json['extra'] as Map?)?.map( (k, e) => MapEntry(k as String, e), ) ?? @@ -188,7 +194,7 @@ Map _$$MarkdownElementImplToJson( 'areaProperty': instance.areaProperty.toJson(), 'text': instance.text, 'constraint': instance.constraint.toJson(), - 'foreground': instance.foreground, + 'foreground': const ColorJsonConverter().toJson(instance.foreground), 'extra': instance.extra, 'type': instance.$type, }; diff --git a/api/lib/src/models/palette.dart b/api/lib/src/models/palette.dart index e233060100ba..ee9dcb0d6c41 100644 --- a/api/lib/src/models/palette.dart +++ b/api/lib/src/models/palette.dart @@ -1,3 +1,5 @@ +import 'package:butterfly_api/src/converter/color.dart'; +import 'package:dart_leap/dart_leap.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'palette.g.dart'; @@ -6,7 +8,9 @@ part 'palette.freezed.dart'; @freezed sealed class ColorPalette with _$ColorPalette { const factory ColorPalette( - {required String name, @Default([]) List colors}) = _ColorPalette; + {required String name, + @Default([]) @ColorJsonConverter() List colors}) = + _ColorPalette; factory ColorPalette.fromJson(Map json) => _$ColorPaletteFromJson(json); } diff --git a/api/lib/src/models/palette.freezed.dart b/api/lib/src/models/palette.freezed.dart index 5b494696517e..42481a0bce1c 100644 --- a/api/lib/src/models/palette.freezed.dart +++ b/api/lib/src/models/palette.freezed.dart @@ -21,7 +21,8 @@ ColorPalette _$ColorPaletteFromJson(Map json) { /// @nodoc mixin _$ColorPalette { String get name => throw _privateConstructorUsedError; - List get colors => throw _privateConstructorUsedError; + @ColorJsonConverter() + List get colors => throw _privateConstructorUsedError; /// Serializes this ColorPalette to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -39,7 +40,7 @@ abstract class $ColorPaletteCopyWith<$Res> { ColorPalette value, $Res Function(ColorPalette) then) = _$ColorPaletteCopyWithImpl<$Res, ColorPalette>; @useResult - $Res call({String name, List colors}); + $Res call({String name, @ColorJsonConverter() List colors}); } /// @nodoc @@ -68,7 +69,7 @@ class _$ColorPaletteCopyWithImpl<$Res, $Val extends ColorPalette> colors: null == colors ? _value.colors : colors // ignore: cast_nullable_to_non_nullable - as List, + as List, ) as $Val); } } @@ -81,7 +82,7 @@ abstract class _$$ColorPaletteImplCopyWith<$Res> __$$ColorPaletteImplCopyWithImpl<$Res>; @override @useResult - $Res call({String name, List colors}); + $Res call({String name, @ColorJsonConverter() List colors}); } /// @nodoc @@ -108,7 +109,7 @@ class __$$ColorPaletteImplCopyWithImpl<$Res> colors: null == colors ? _value._colors : colors // ignore: cast_nullable_to_non_nullable - as List, + as List, )); } } @@ -117,7 +118,8 @@ class __$$ColorPaletteImplCopyWithImpl<$Res> @JsonSerializable() class _$ColorPaletteImpl implements _ColorPalette { const _$ColorPaletteImpl( - {required this.name, final List colors = const []}) + {required this.name, + @ColorJsonConverter() final List colors = const []}) : _colors = colors; factory _$ColorPaletteImpl.fromJson(Map json) => @@ -125,10 +127,11 @@ class _$ColorPaletteImpl implements _ColorPalette { @override final String name; - final List _colors; + final List _colors; @override @JsonKey() - List get colors { + @ColorJsonConverter() + List get colors { if (_colors is EqualUnmodifiableListView) return _colors; // ignore: implicit_dynamic_type return EqualUnmodifiableListView(_colors); @@ -172,7 +175,7 @@ class _$ColorPaletteImpl implements _ColorPalette { abstract class _ColorPalette implements ColorPalette { const factory _ColorPalette( {required final String name, - final List colors}) = _$ColorPaletteImpl; + @ColorJsonConverter() final List colors}) = _$ColorPaletteImpl; factory _ColorPalette.fromJson(Map json) = _$ColorPaletteImpl.fromJson; @@ -180,7 +183,8 @@ abstract class _ColorPalette implements ColorPalette { @override String get name; @override - List get colors; + @ColorJsonConverter() + List get colors; /// Create a copy of ColorPalette /// with the given fields replaced by the non-null parameter values. diff --git a/api/lib/src/models/palette.g.dart b/api/lib/src/models/palette.g.dart index 5058d9ff23a6..42af1e28819f 100644 --- a/api/lib/src/models/palette.g.dart +++ b/api/lib/src/models/palette.g.dart @@ -9,7 +9,8 @@ part of 'palette.dart'; _$ColorPaletteImpl _$$ColorPaletteImplFromJson(Map json) => _$ColorPaletteImpl( name: json['name'] as String, colors: (json['colors'] as List?) - ?.map((e) => (e as num).toInt()) + ?.map((e) => + const ColorJsonConverter().fromJson((e as num).toInt())) .toList() ?? const [], ); @@ -17,5 +18,5 @@ _$ColorPaletteImpl _$$ColorPaletteImplFromJson(Map json) => _$ColorPaletteImpl( Map _$$ColorPaletteImplToJson(_$ColorPaletteImpl instance) => { 'name': instance.name, - 'colors': instance.colors, + 'colors': instance.colors.map(const ColorJsonConverter().toJson).toList(), }; diff --git a/api/lib/src/models/property.dart b/api/lib/src/models/property.dart index 611f56fb9e4d..8da98d363a70 100644 --- a/api/lib/src/models/property.dart +++ b/api/lib/src/models/property.dart @@ -1,4 +1,6 @@ -import 'colors.dart'; +import 'package:butterfly_api/src/converter/color.dart'; +import 'package:dart_leap/dart_leap.dart'; + import 'package:freezed_annotation/freezed_annotation.dart'; part 'property.g.dart'; @@ -22,7 +24,7 @@ sealed class Property with _$Property { const factory Property.pen({ @Default(5) double strokeWidth, @Default(0.4) double thinning, - @Default(BasicColors.black) int color, + @Default(SRGBColor.black) @ColorJsonConverter() SRGBColor color, @Default(false) bool fill, @Default(0.5) double smoothing, @Default(0.3) double streamline, @@ -31,7 +33,7 @@ sealed class Property with _$Property { const factory Property.shape({ @Default(5) double strokeWidth, required PathShape shape, - @Default(BasicColors.black) int color, + @Default(SRGBColor.black) @ColorJsonConverter() SRGBColor color, }) = ShapeProperty; factory Property.fromJson(Map json) => @@ -42,16 +44,20 @@ sealed class Property with _$Property { sealed class PathShape with _$PathShape { const PathShape._(); const factory PathShape.circle( - {@Default(BasicColors.transparent) int fillColor}) = CircleShape; + {@Default(SRGBColor.transparent) + @ColorJsonConverter() + SRGBColor fillColor}) = CircleShape; const factory PathShape.rectangle( - {@Default(BasicColors.transparent) int fillColor, + {@Default(SRGBColor.transparent) + @ColorJsonConverter() + SRGBColor fillColor, @Default(0) double topLeftCornerRadius, @Default(0) double topRightCornerRadius, @Default(0) double bottomLeftCornerRadius, @Default(0) double bottomRightCornerRadius}) = RectangleShape; const factory PathShape.line() = LineShape; const factory PathShape.triangle({ - @Default(BasicColors.transparent) int fillColor, + @Default(SRGBColor.transparent) @ColorJsonConverter() SRGBColor fillColor, }) = TriangleShape; factory PathShape.fromJson(Map json) => diff --git a/api/lib/src/models/property.freezed.dart b/api/lib/src/models/property.freezed.dart index c83f244db0ce..3f06f4bb386c 100644 --- a/api/lib/src/models/property.freezed.dart +++ b/api/lib/src/models/property.freezed.dart @@ -30,7 +30,8 @@ Property _$PropertyFromJson(Map json) { /// @nodoc mixin _$Property { double get strokeWidth => throw _privateConstructorUsedError; - int get color => throw _privateConstructorUsedError; + @ColorJsonConverter() + SRGBColor get color => throw _privateConstructorUsedError; /// Serializes this Property to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -47,7 +48,7 @@ abstract class $PropertyCopyWith<$Res> { factory $PropertyCopyWith(Property value, $Res Function(Property) then) = _$PropertyCopyWithImpl<$Res, Property>; @useResult - $Res call({double strokeWidth, int color}); + $Res call({double strokeWidth, @ColorJsonConverter() SRGBColor color}); } /// @nodoc @@ -76,7 +77,7 @@ class _$PropertyCopyWithImpl<$Res, $Val extends Property> color: null == color ? _value.color : color // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, ) as $Val); } } @@ -92,7 +93,7 @@ abstract class _$$PenPropertyImplCopyWith<$Res> $Res call( {double strokeWidth, double thinning, - int color, + @ColorJsonConverter() SRGBColor color, bool fill, double smoothing, double streamline}); @@ -130,7 +131,7 @@ class __$$PenPropertyImplCopyWithImpl<$Res> color: null == color ? _value.color : color // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, fill: null == fill ? _value.fill : fill // ignore: cast_nullable_to_non_nullable @@ -153,7 +154,7 @@ class _$PenPropertyImpl implements PenProperty { const _$PenPropertyImpl( {this.strokeWidth = 5, this.thinning = 0.4, - this.color = BasicColors.black, + @ColorJsonConverter() this.color = SRGBColor.black, this.fill = false, this.smoothing = 0.5, this.streamline = 0.3, @@ -171,7 +172,8 @@ class _$PenPropertyImpl implements PenProperty { final double thinning; @override @JsonKey() - final int color; + @ColorJsonConverter() + final SRGBColor color; @override @JsonKey() final bool fill; @@ -232,7 +234,7 @@ abstract class PenProperty implements Property, PathProperty { const factory PenProperty( {final double strokeWidth, final double thinning, - final int color, + @ColorJsonConverter() final SRGBColor color, final bool fill, final double smoothing, final double streamline}) = _$PenPropertyImpl; @@ -244,7 +246,8 @@ abstract class PenProperty implements Property, PathProperty { double get strokeWidth; double get thinning; @override - int get color; + @ColorJsonConverter() + SRGBColor get color; bool get fill; double get smoothing; double get streamline; @@ -265,7 +268,10 @@ abstract class _$$ShapePropertyImplCopyWith<$Res> __$$ShapePropertyImplCopyWithImpl<$Res>; @override @useResult - $Res call({double strokeWidth, PathShape shape, int color}); + $Res call( + {double strokeWidth, + PathShape shape, + @ColorJsonConverter() SRGBColor color}); $PathShapeCopyWith<$Res> get shape; } @@ -299,7 +305,7 @@ class __$$ShapePropertyImplCopyWithImpl<$Res> color: null == color ? _value.color : color // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, )); } @@ -320,7 +326,7 @@ class _$ShapePropertyImpl implements ShapeProperty { const _$ShapePropertyImpl( {this.strokeWidth = 5, required this.shape, - this.color = BasicColors.black, + @ColorJsonConverter() this.color = SRGBColor.black, final String? $type}) : $type = $type ?? 'shape'; @@ -334,7 +340,8 @@ class _$ShapePropertyImpl implements ShapeProperty { final PathShape shape; @override @JsonKey() - final int color; + @ColorJsonConverter() + final SRGBColor color; @JsonKey(name: 'type') final String $type; @@ -379,7 +386,7 @@ abstract class ShapeProperty implements Property { const factory ShapeProperty( {final double strokeWidth, required final PathShape shape, - final int color}) = _$ShapePropertyImpl; + @ColorJsonConverter() final SRGBColor color}) = _$ShapePropertyImpl; factory ShapeProperty.fromJson(Map json) = _$ShapePropertyImpl.fromJson; @@ -388,7 +395,8 @@ abstract class ShapeProperty implements Property { double get strokeWidth; PathShape get shape; @override - int get color; + @ColorJsonConverter() + SRGBColor get color; /// Create a copy of Property /// with the given fields replaced by the non-null parameter values. @@ -447,7 +455,7 @@ abstract class _$$CircleShapeImplCopyWith<$Res> { _$CircleShapeImpl value, $Res Function(_$CircleShapeImpl) then) = __$$CircleShapeImplCopyWithImpl<$Res>; @useResult - $Res call({int fillColor}); + $Res call({@ColorJsonConverter() SRGBColor fillColor}); } /// @nodoc @@ -469,7 +477,7 @@ class __$$CircleShapeImplCopyWithImpl<$Res> fillColor: null == fillColor ? _value.fillColor : fillColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, )); } } @@ -478,7 +486,8 @@ class __$$CircleShapeImplCopyWithImpl<$Res> @JsonSerializable() class _$CircleShapeImpl extends CircleShape { const _$CircleShapeImpl( - {this.fillColor = BasicColors.transparent, final String? $type}) + {@ColorJsonConverter() this.fillColor = SRGBColor.transparent, + final String? $type}) : $type = $type ?? 'circle', super._(); @@ -487,7 +496,8 @@ class _$CircleShapeImpl extends CircleShape { @override @JsonKey() - final int fillColor; + @ColorJsonConverter() + final SRGBColor fillColor; @JsonKey(name: 'type') final String $type; @@ -527,13 +537,15 @@ class _$CircleShapeImpl extends CircleShape { } abstract class CircleShape extends PathShape { - const factory CircleShape({final int fillColor}) = _$CircleShapeImpl; + const factory CircleShape({@ColorJsonConverter() final SRGBColor fillColor}) = + _$CircleShapeImpl; const CircleShape._() : super._(); factory CircleShape.fromJson(Map json) = _$CircleShapeImpl.fromJson; - int get fillColor; + @ColorJsonConverter() + SRGBColor get fillColor; /// Create a copy of PathShape /// with the given fields replaced by the non-null parameter values. @@ -549,7 +561,7 @@ abstract class _$$RectangleShapeImplCopyWith<$Res> { __$$RectangleShapeImplCopyWithImpl<$Res>; @useResult $Res call( - {int fillColor, + {@ColorJsonConverter() SRGBColor fillColor, double topLeftCornerRadius, double topRightCornerRadius, double bottomLeftCornerRadius, @@ -579,7 +591,7 @@ class __$$RectangleShapeImplCopyWithImpl<$Res> fillColor: null == fillColor ? _value.fillColor : fillColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, topLeftCornerRadius: null == topLeftCornerRadius ? _value.topLeftCornerRadius : topLeftCornerRadius // ignore: cast_nullable_to_non_nullable @@ -604,7 +616,7 @@ class __$$RectangleShapeImplCopyWithImpl<$Res> @JsonSerializable() class _$RectangleShapeImpl extends RectangleShape { const _$RectangleShapeImpl( - {this.fillColor = BasicColors.transparent, + {@ColorJsonConverter() this.fillColor = SRGBColor.transparent, this.topLeftCornerRadius = 0, this.topRightCornerRadius = 0, this.bottomLeftCornerRadius = 0, @@ -618,7 +630,8 @@ class _$RectangleShapeImpl extends RectangleShape { @override @JsonKey() - final int fillColor; + @ColorJsonConverter() + final SRGBColor fillColor; @override @JsonKey() final double topLeftCornerRadius; @@ -682,7 +695,7 @@ class _$RectangleShapeImpl extends RectangleShape { abstract class RectangleShape extends PathShape { const factory RectangleShape( - {final int fillColor, + {@ColorJsonConverter() final SRGBColor fillColor, final double topLeftCornerRadius, final double topRightCornerRadius, final double bottomLeftCornerRadius, @@ -692,7 +705,8 @@ abstract class RectangleShape extends PathShape { factory RectangleShape.fromJson(Map json) = _$RectangleShapeImpl.fromJson; - int get fillColor; + @ColorJsonConverter() + SRGBColor get fillColor; double get topLeftCornerRadius; double get topRightCornerRadius; double get bottomLeftCornerRadius; @@ -774,7 +788,7 @@ abstract class _$$TriangleShapeImplCopyWith<$Res> { _$TriangleShapeImpl value, $Res Function(_$TriangleShapeImpl) then) = __$$TriangleShapeImplCopyWithImpl<$Res>; @useResult - $Res call({int fillColor}); + $Res call({@ColorJsonConverter() SRGBColor fillColor}); } /// @nodoc @@ -796,7 +810,7 @@ class __$$TriangleShapeImplCopyWithImpl<$Res> fillColor: null == fillColor ? _value.fillColor : fillColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, )); } } @@ -805,7 +819,8 @@ class __$$TriangleShapeImplCopyWithImpl<$Res> @JsonSerializable() class _$TriangleShapeImpl extends TriangleShape { const _$TriangleShapeImpl( - {this.fillColor = BasicColors.transparent, final String? $type}) + {@ColorJsonConverter() this.fillColor = SRGBColor.transparent, + final String? $type}) : $type = $type ?? 'triangle', super._(); @@ -814,7 +829,8 @@ class _$TriangleShapeImpl extends TriangleShape { @override @JsonKey() - final int fillColor; + @ColorJsonConverter() + final SRGBColor fillColor; @JsonKey(name: 'type') final String $type; @@ -854,13 +870,15 @@ class _$TriangleShapeImpl extends TriangleShape { } abstract class TriangleShape extends PathShape { - const factory TriangleShape({final int fillColor}) = _$TriangleShapeImpl; + const factory TriangleShape( + {@ColorJsonConverter() final SRGBColor fillColor}) = _$TriangleShapeImpl; const TriangleShape._() : super._(); factory TriangleShape.fromJson(Map json) = _$TriangleShapeImpl.fromJson; - int get fillColor; + @ColorJsonConverter() + SRGBColor get fillColor; /// Create a copy of PathShape /// with the given fields replaced by the non-null parameter values. diff --git a/api/lib/src/models/property.g.dart b/api/lib/src/models/property.g.dart index a2e3a4e3d04f..8cbcc2818830 100644 --- a/api/lib/src/models/property.g.dart +++ b/api/lib/src/models/property.g.dart @@ -9,7 +9,9 @@ part of 'property.dart'; _$PenPropertyImpl _$$PenPropertyImplFromJson(Map json) => _$PenPropertyImpl( strokeWidth: (json['strokeWidth'] as num?)?.toDouble() ?? 5, thinning: (json['thinning'] as num?)?.toDouble() ?? 0.4, - color: (json['color'] as num?)?.toInt() ?? BasicColors.black, + color: json['color'] == null + ? SRGBColor.black + : const ColorJsonConverter().fromJson((json['color'] as num).toInt()), fill: json['fill'] as bool? ?? false, smoothing: (json['smoothing'] as num?)?.toDouble() ?? 0.5, streamline: (json['streamline'] as num?)?.toDouble() ?? 0.3, @@ -20,7 +22,7 @@ Map _$$PenPropertyImplToJson(_$PenPropertyImpl instance) => { 'strokeWidth': instance.strokeWidth, 'thinning': instance.thinning, - 'color': instance.color, + 'color': const ColorJsonConverter().toJson(instance.color), 'fill': instance.fill, 'smoothing': instance.smoothing, 'streamline': instance.streamline, @@ -32,7 +34,9 @@ _$ShapePropertyImpl _$$ShapePropertyImplFromJson(Map json) => strokeWidth: (json['strokeWidth'] as num?)?.toDouble() ?? 5, shape: PathShape.fromJson(Map.from(json['shape'] as Map)), - color: (json['color'] as num?)?.toInt() ?? BasicColors.black, + color: json['color'] == null + ? SRGBColor.black + : const ColorJsonConverter().fromJson((json['color'] as num).toInt()), $type: json['type'] as String?, ); @@ -40,26 +44,30 @@ Map _$$ShapePropertyImplToJson(_$ShapePropertyImpl instance) => { 'strokeWidth': instance.strokeWidth, 'shape': instance.shape.toJson(), - 'color': instance.color, + 'color': const ColorJsonConverter().toJson(instance.color), 'type': instance.$type, }; _$CircleShapeImpl _$$CircleShapeImplFromJson(Map json) => _$CircleShapeImpl( - fillColor: - (json['fillColor'] as num?)?.toInt() ?? BasicColors.transparent, + fillColor: json['fillColor'] == null + ? SRGBColor.transparent + : const ColorJsonConverter() + .fromJson((json['fillColor'] as num).toInt()), $type: json['type'] as String?, ); Map _$$CircleShapeImplToJson(_$CircleShapeImpl instance) => { - 'fillColor': instance.fillColor, + 'fillColor': const ColorJsonConverter().toJson(instance.fillColor), 'type': instance.$type, }; _$RectangleShapeImpl _$$RectangleShapeImplFromJson(Map json) => _$RectangleShapeImpl( - fillColor: - (json['fillColor'] as num?)?.toInt() ?? BasicColors.transparent, + fillColor: json['fillColor'] == null + ? SRGBColor.transparent + : const ColorJsonConverter() + .fromJson((json['fillColor'] as num).toInt()), topLeftCornerRadius: (json['topLeftCornerRadius'] as num?)?.toDouble() ?? 0, topRightCornerRadius: @@ -74,7 +82,7 @@ _$RectangleShapeImpl _$$RectangleShapeImplFromJson(Map json) => Map _$$RectangleShapeImplToJson( _$RectangleShapeImpl instance) => { - 'fillColor': instance.fillColor, + 'fillColor': const ColorJsonConverter().toJson(instance.fillColor), 'topLeftCornerRadius': instance.topLeftCornerRadius, 'topRightCornerRadius': instance.topRightCornerRadius, 'bottomLeftCornerRadius': instance.bottomLeftCornerRadius, @@ -93,13 +101,15 @@ Map _$$LineShapeImplToJson(_$LineShapeImpl instance) => _$TriangleShapeImpl _$$TriangleShapeImplFromJson(Map json) => _$TriangleShapeImpl( - fillColor: - (json['fillColor'] as num?)?.toInt() ?? BasicColors.transparent, + fillColor: json['fillColor'] == null + ? SRGBColor.transparent + : const ColorJsonConverter() + .fromJson((json['fillColor'] as num).toInt()), $type: json['type'] as String?, ); Map _$$TriangleShapeImplToJson(_$TriangleShapeImpl instance) => { - 'fillColor': instance.fillColor, + 'fillColor': const ColorJsonConverter().toJson(instance.fillColor), 'type': instance.$type, }; diff --git a/api/lib/src/models/text.dart b/api/lib/src/models/text.dart index 5f53abc7a4da..aee98262ae25 100644 --- a/api/lib/src/models/text.dart +++ b/api/lib/src/models/text.dart @@ -1,10 +1,10 @@ import 'dart:math'; +import 'package:butterfly_api/src/converter/color.dart'; import 'package:collection/collection.dart'; +import 'package:dart_leap/dart_leap.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'colors.dart'; - part 'text.g.dart'; part 'text.freezed.dart'; @@ -24,32 +24,32 @@ enum TextDecorationStyle { solid, double, dotted, dashed, wavy } sealed class SpanProperty with _$SpanProperty { const factory SpanProperty.defined({ double? size, - int? color, + @ColorJsonConverter() SRGBColor? color, int? fontWeight, bool? lineThrough, bool? underline, bool? overline, bool? italic, double? letterSpacing, - int? decorationColor, + @ColorJsonConverter() SRGBColor? decorationColor, TextDecorationStyle? decorationStyle, double? decorationThickness, - int? backgroundColor, + @ColorJsonConverter() SRGBColor? backgroundColor, }) = DefinedSpanProperty; static const kDefault = DefinedSpanProperty( size: 12, - color: BasicColors.black, + color: SRGBColor.black, fontWeight: kFontWeightNormal, lineThrough: false, underline: false, overline: false, italic: false, letterSpacing: 0, - decorationColor: BasicColors.black, + decorationColor: SRGBColor.black, decorationStyle: TextDecorationStyle.solid, decorationThickness: 1, - backgroundColor: BasicColors.transparent, + backgroundColor: SRGBColor.transparent, ); const factory SpanProperty.named(String name) = NamedSpanProperty; @@ -385,8 +385,9 @@ extension ResolveProperty on TextStyleSheet? { extension SpanPropertyGetter on DefinedSpanProperty { double getSize([DefinedParagraphProperty? paragraphProperty]) => size ?? paragraphProperty?.span.size ?? SpanProperty.kDefault.size!; - int getColor( - [DefinedParagraphProperty? paragraphProperty, int? foreground]) => + SRGBColor getColor( + [DefinedParagraphProperty? paragraphProperty, + SRGBColor? foreground]) => color ?? paragraphProperty?.span.color ?? foreground ?? @@ -413,7 +414,7 @@ extension SpanPropertyGetter on DefinedSpanProperty { letterSpacing ?? paragraphProperty?.span.letterSpacing ?? SpanProperty.kDefault.letterSpacing!; - int getDecorationColor([DefinedParagraphProperty? paragraphProperty]) => + SRGBColor getDecorationColor([DefinedParagraphProperty? paragraphProperty]) => decorationColor ?? paragraphProperty?.span.decorationColor ?? SpanProperty.kDefault.decorationColor!; @@ -427,7 +428,7 @@ extension SpanPropertyGetter on DefinedSpanProperty { decorationThickness ?? paragraphProperty?.span.decorationThickness ?? SpanProperty.kDefault.decorationThickness!; - int getBackgroundColor([DefinedParagraphProperty? paragraphProperty]) => + SRGBColor getBackgroundColor([DefinedParagraphProperty? paragraphProperty]) => backgroundColor ?? paragraphProperty?.span.backgroundColor ?? SpanProperty.kDefault.backgroundColor!; diff --git a/api/lib/src/models/text.freezed.dart b/api/lib/src/models/text.freezed.dart index d13639024f19..7fdb6f7e3eaa 100644 --- a/api/lib/src/models/text.freezed.dart +++ b/api/lib/src/models/text.freezed.dart @@ -64,17 +64,17 @@ abstract class _$$DefinedSpanPropertyImplCopyWith<$Res> { @useResult $Res call( {double? size, - int? color, + @ColorJsonConverter() SRGBColor? color, int? fontWeight, bool? lineThrough, bool? underline, bool? overline, bool? italic, double? letterSpacing, - int? decorationColor, + @ColorJsonConverter() SRGBColor? decorationColor, TextDecorationStyle? decorationStyle, double? decorationThickness, - int? backgroundColor}); + @ColorJsonConverter() SRGBColor? backgroundColor}); } /// @nodoc @@ -111,7 +111,7 @@ class __$$DefinedSpanPropertyImplCopyWithImpl<$Res> color: freezed == color ? _value.color : color // ignore: cast_nullable_to_non_nullable - as int?, + as SRGBColor?, fontWeight: freezed == fontWeight ? _value.fontWeight : fontWeight // ignore: cast_nullable_to_non_nullable @@ -139,7 +139,7 @@ class __$$DefinedSpanPropertyImplCopyWithImpl<$Res> decorationColor: freezed == decorationColor ? _value.decorationColor : decorationColor // ignore: cast_nullable_to_non_nullable - as int?, + as SRGBColor?, decorationStyle: freezed == decorationStyle ? _value.decorationStyle : decorationStyle // ignore: cast_nullable_to_non_nullable @@ -151,7 +151,7 @@ class __$$DefinedSpanPropertyImplCopyWithImpl<$Res> backgroundColor: freezed == backgroundColor ? _value.backgroundColor : backgroundColor // ignore: cast_nullable_to_non_nullable - as int?, + as SRGBColor?, )); } } @@ -161,17 +161,17 @@ class __$$DefinedSpanPropertyImplCopyWithImpl<$Res> class _$DefinedSpanPropertyImpl implements DefinedSpanProperty { const _$DefinedSpanPropertyImpl( {this.size, - this.color, + @ColorJsonConverter() this.color, this.fontWeight, this.lineThrough, this.underline, this.overline, this.italic, this.letterSpacing, - this.decorationColor, + @ColorJsonConverter() this.decorationColor, this.decorationStyle, this.decorationThickness, - this.backgroundColor, + @ColorJsonConverter() this.backgroundColor, final String? $type}) : $type = $type ?? 'defined'; @@ -181,7 +181,8 @@ class _$DefinedSpanPropertyImpl implements DefinedSpanProperty { @override final double? size; @override - final int? color; + @ColorJsonConverter() + final SRGBColor? color; @override final int? fontWeight; @override @@ -195,13 +196,15 @@ class _$DefinedSpanPropertyImpl implements DefinedSpanProperty { @override final double? letterSpacing; @override - final int? decorationColor; + @ColorJsonConverter() + final SRGBColor? decorationColor; @override final TextDecorationStyle? decorationStyle; @override final double? decorationThickness; @override - final int? backgroundColor; + @ColorJsonConverter() + final SRGBColor? backgroundColor; @JsonKey(name: 'type') final String $type; @@ -275,34 +278,38 @@ class _$DefinedSpanPropertyImpl implements DefinedSpanProperty { abstract class DefinedSpanProperty implements SpanProperty { const factory DefinedSpanProperty( - {final double? size, - final int? color, - final int? fontWeight, - final bool? lineThrough, - final bool? underline, - final bool? overline, - final bool? italic, - final double? letterSpacing, - final int? decorationColor, - final TextDecorationStyle? decorationStyle, - final double? decorationThickness, - final int? backgroundColor}) = _$DefinedSpanPropertyImpl; + {final double? size, + @ColorJsonConverter() final SRGBColor? color, + final int? fontWeight, + final bool? lineThrough, + final bool? underline, + final bool? overline, + final bool? italic, + final double? letterSpacing, + @ColorJsonConverter() final SRGBColor? decorationColor, + final TextDecorationStyle? decorationStyle, + final double? decorationThickness, + @ColorJsonConverter() final SRGBColor? backgroundColor}) = + _$DefinedSpanPropertyImpl; factory DefinedSpanProperty.fromJson(Map json) = _$DefinedSpanPropertyImpl.fromJson; double? get size; - int? get color; + @ColorJsonConverter() + SRGBColor? get color; int? get fontWeight; bool? get lineThrough; bool? get underline; bool? get overline; bool? get italic; double? get letterSpacing; - int? get decorationColor; + @ColorJsonConverter() + SRGBColor? get decorationColor; TextDecorationStyle? get decorationStyle; double? get decorationThickness; - int? get backgroundColor; + @ColorJsonConverter() + SRGBColor? get backgroundColor; /// Create a copy of SpanProperty /// with the given fields replaced by the non-null parameter values. diff --git a/api/lib/src/models/text.g.dart b/api/lib/src/models/text.g.dart index 9700985911d6..5aed03060e7c 100644 --- a/api/lib/src/models/text.g.dart +++ b/api/lib/src/models/text.g.dart @@ -9,18 +9,21 @@ part of 'text.dart'; _$DefinedSpanPropertyImpl _$$DefinedSpanPropertyImplFromJson(Map json) => _$DefinedSpanPropertyImpl( size: (json['size'] as num?)?.toDouble(), - color: (json['color'] as num?)?.toInt(), + color: _$JsonConverterFromJson( + json['color'], const ColorJsonConverter().fromJson), fontWeight: (json['fontWeight'] as num?)?.toInt(), lineThrough: json['lineThrough'] as bool?, underline: json['underline'] as bool?, overline: json['overline'] as bool?, italic: json['italic'] as bool?, letterSpacing: (json['letterSpacing'] as num?)?.toDouble(), - decorationColor: (json['decorationColor'] as num?)?.toInt(), + decorationColor: _$JsonConverterFromJson( + json['decorationColor'], const ColorJsonConverter().fromJson), decorationStyle: $enumDecodeNullable( _$TextDecorationStyleEnumMap, json['decorationStyle']), decorationThickness: (json['decorationThickness'] as num?)?.toDouble(), - backgroundColor: (json['backgroundColor'] as num?)?.toInt(), + backgroundColor: _$JsonConverterFromJson( + json['backgroundColor'], const ColorJsonConverter().fromJson), $type: json['type'] as String?, ); @@ -28,20 +31,29 @@ Map _$$DefinedSpanPropertyImplToJson( _$DefinedSpanPropertyImpl instance) => { 'size': instance.size, - 'color': instance.color, + 'color': _$JsonConverterToJson( + instance.color, const ColorJsonConverter().toJson), 'fontWeight': instance.fontWeight, 'lineThrough': instance.lineThrough, 'underline': instance.underline, 'overline': instance.overline, 'italic': instance.italic, 'letterSpacing': instance.letterSpacing, - 'decorationColor': instance.decorationColor, + 'decorationColor': _$JsonConverterToJson( + instance.decorationColor, const ColorJsonConverter().toJson), 'decorationStyle': _$TextDecorationStyleEnumMap[instance.decorationStyle], 'decorationThickness': instance.decorationThickness, - 'backgroundColor': instance.backgroundColor, + 'backgroundColor': _$JsonConverterToJson( + instance.backgroundColor, const ColorJsonConverter().toJson), 'type': instance.$type, }; +Value? _$JsonConverterFromJson( + Object? json, + Value? Function(Json json) fromJson, +) => + json == null ? null : fromJson(json as Json); + const _$TextDecorationStyleEnumMap = { TextDecorationStyle.solid: 'solid', TextDecorationStyle.double: 'double', @@ -50,6 +62,12 @@ const _$TextDecorationStyleEnumMap = { TextDecorationStyle.wavy: 'wavy', }; +Json? _$JsonConverterToJson( + Value? value, + Json? Function(Value value) toJson, +) => + value == null ? null : toJson(value); + _$NamedSpanPropertyImpl _$$NamedSpanPropertyImplFromJson(Map json) => _$NamedSpanPropertyImpl( json['name'] as String, diff --git a/api/lib/src/models/texture.dart b/api/lib/src/models/texture.dart index aa5b97103df4..30371b85e52a 100644 --- a/api/lib/src/models/texture.dart +++ b/api/lib/src/models/texture.dart @@ -1,3 +1,5 @@ +import 'package:butterfly_api/src/converter/color.dart'; +import 'package:dart_leap/dart_leap.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'colors.dart'; @@ -49,7 +51,7 @@ extension PatternTemplateExtension on PatternTemplate { return const PatternTexture( boxColor: BasicColors.light, boxHeight: 40, - boxYColor: BasicColors.black, + boxYColor: SRGBColor.black, boxYSpace: 80, boxYCount: 5); case PatternTemplate.plainDark: @@ -67,7 +69,7 @@ extension PatternTemplateExtension on PatternTemplate { case PatternTemplate.musicDark: return const PatternTexture( boxColor: BasicColors.dark, - boxYColor: BasicColors.white, + boxYColor: SRGBColor.white, boxHeight: 40, boxYSpace: 80, boxYCount: 5); @@ -84,9 +86,9 @@ sealed class SurfaceTexture with _$SurfaceTexture { @Default(1) int boxYCount, @Default(0) double boxXSpace, @Default(0) double boxYSpace, - @Default(BasicColors.blue) int boxXColor, - @Default(BasicColors.red) int boxYColor, - @Default(BasicColors.white) int boxColor, + @Default(BasicColors.blue) @ColorJsonConverter() SRGBColor boxXColor, + @Default(BasicColors.red) @ColorJsonConverter() SRGBColor boxYColor, + @Default(SRGBColor.white) @ColorJsonConverter() SRGBColor boxColor, @Default(0.5) double boxXStroke, @Default(0.5) double boxYStroke}) = PatternTexture; diff --git a/api/lib/src/models/texture.freezed.dart b/api/lib/src/models/texture.freezed.dart index dc614f954fcc..20ed5520b9b6 100644 --- a/api/lib/src/models/texture.freezed.dart +++ b/api/lib/src/models/texture.freezed.dart @@ -26,9 +26,12 @@ mixin _$SurfaceTexture { int get boxYCount => throw _privateConstructorUsedError; double get boxXSpace => throw _privateConstructorUsedError; double get boxYSpace => throw _privateConstructorUsedError; - int get boxXColor => throw _privateConstructorUsedError; - int get boxYColor => throw _privateConstructorUsedError; - int get boxColor => throw _privateConstructorUsedError; + @ColorJsonConverter() + SRGBColor get boxXColor => throw _privateConstructorUsedError; + @ColorJsonConverter() + SRGBColor get boxYColor => throw _privateConstructorUsedError; + @ColorJsonConverter() + SRGBColor get boxColor => throw _privateConstructorUsedError; double get boxXStroke => throw _privateConstructorUsedError; double get boxYStroke => throw _privateConstructorUsedError; @@ -55,9 +58,9 @@ abstract class $SurfaceTextureCopyWith<$Res> { int boxYCount, double boxXSpace, double boxYSpace, - int boxXColor, - int boxYColor, - int boxColor, + @ColorJsonConverter() SRGBColor boxXColor, + @ColorJsonConverter() SRGBColor boxYColor, + @ColorJsonConverter() SRGBColor boxColor, double boxXStroke, double boxYStroke}); } @@ -117,15 +120,15 @@ class _$SurfaceTextureCopyWithImpl<$Res, $Val extends SurfaceTexture> boxXColor: null == boxXColor ? _value.boxXColor : boxXColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, boxYColor: null == boxYColor ? _value.boxYColor : boxYColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, boxColor: null == boxColor ? _value.boxColor : boxColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, boxXStroke: null == boxXStroke ? _value.boxXStroke : boxXStroke // ignore: cast_nullable_to_non_nullable @@ -153,9 +156,9 @@ abstract class _$$PatternTextureImplCopyWith<$Res> int boxYCount, double boxXSpace, double boxYSpace, - int boxXColor, - int boxYColor, - int boxColor, + @ColorJsonConverter() SRGBColor boxXColor, + @ColorJsonConverter() SRGBColor boxYColor, + @ColorJsonConverter() SRGBColor boxColor, double boxXStroke, double boxYStroke}); } @@ -213,15 +216,15 @@ class __$$PatternTextureImplCopyWithImpl<$Res> boxXColor: null == boxXColor ? _value.boxXColor : boxXColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, boxYColor: null == boxYColor ? _value.boxYColor : boxYColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, boxColor: null == boxColor ? _value.boxColor : boxColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, boxXStroke: null == boxXStroke ? _value.boxXStroke : boxXStroke // ignore: cast_nullable_to_non_nullable @@ -244,9 +247,9 @@ class _$PatternTextureImpl implements PatternTexture { this.boxYCount = 1, this.boxXSpace = 0, this.boxYSpace = 0, - this.boxXColor = BasicColors.blue, - this.boxYColor = BasicColors.red, - this.boxColor = BasicColors.white, + @ColorJsonConverter() this.boxXColor = BasicColors.blue, + @ColorJsonConverter() this.boxYColor = BasicColors.red, + @ColorJsonConverter() this.boxColor = SRGBColor.white, this.boxXStroke = 0.5, this.boxYStroke = 0.5}); @@ -273,13 +276,16 @@ class _$PatternTextureImpl implements PatternTexture { final double boxYSpace; @override @JsonKey() - final int boxXColor; + @ColorJsonConverter() + final SRGBColor boxXColor; @override @JsonKey() - final int boxYColor; + @ColorJsonConverter() + final SRGBColor boxYColor; @override @JsonKey() - final int boxColor; + @ColorJsonConverter() + final SRGBColor boxColor; @override @JsonKey() final double boxXStroke; @@ -362,9 +368,9 @@ abstract class PatternTexture implements SurfaceTexture { final int boxYCount, final double boxXSpace, final double boxYSpace, - final int boxXColor, - final int boxYColor, - final int boxColor, + @ColorJsonConverter() final SRGBColor boxXColor, + @ColorJsonConverter() final SRGBColor boxYColor, + @ColorJsonConverter() final SRGBColor boxColor, final double boxXStroke, final double boxYStroke}) = _$PatternTextureImpl; @@ -384,11 +390,14 @@ abstract class PatternTexture implements SurfaceTexture { @override double get boxYSpace; @override - int get boxXColor; + @ColorJsonConverter() + SRGBColor get boxXColor; @override - int get boxYColor; + @ColorJsonConverter() + SRGBColor get boxYColor; @override - int get boxColor; + @ColorJsonConverter() + SRGBColor get boxColor; @override double get boxXStroke; @override diff --git a/api/lib/src/models/texture.g.dart b/api/lib/src/models/texture.g.dart index 1e2e38a544de..15d14576d1e1 100644 --- a/api/lib/src/models/texture.g.dart +++ b/api/lib/src/models/texture.g.dart @@ -14,9 +14,18 @@ _$PatternTextureImpl _$$PatternTextureImplFromJson(Map json) => boxYCount: (json['boxYCount'] as num?)?.toInt() ?? 1, boxXSpace: (json['boxXSpace'] as num?)?.toDouble() ?? 0, boxYSpace: (json['boxYSpace'] as num?)?.toDouble() ?? 0, - boxXColor: (json['boxXColor'] as num?)?.toInt() ?? BasicColors.blue, - boxYColor: (json['boxYColor'] as num?)?.toInt() ?? BasicColors.red, - boxColor: (json['boxColor'] as num?)?.toInt() ?? BasicColors.white, + boxXColor: json['boxXColor'] == null + ? BasicColors.blue + : const ColorJsonConverter() + .fromJson((json['boxXColor'] as num).toInt()), + boxYColor: json['boxYColor'] == null + ? BasicColors.red + : const ColorJsonConverter() + .fromJson((json['boxYColor'] as num).toInt()), + boxColor: json['boxColor'] == null + ? SRGBColor.white + : const ColorJsonConverter() + .fromJson((json['boxColor'] as num).toInt()), boxXStroke: (json['boxXStroke'] as num?)?.toDouble() ?? 0.5, boxYStroke: (json['boxYStroke'] as num?)?.toDouble() ?? 0.5, ); @@ -30,9 +39,9 @@ Map _$$PatternTextureImplToJson( 'boxYCount': instance.boxYCount, 'boxXSpace': instance.boxXSpace, 'boxYSpace': instance.boxYSpace, - 'boxXColor': instance.boxXColor, - 'boxYColor': instance.boxYColor, - 'boxColor': instance.boxColor, + 'boxXColor': const ColorJsonConverter().toJson(instance.boxXColor), + 'boxYColor': const ColorJsonConverter().toJson(instance.boxYColor), + 'boxColor': const ColorJsonConverter().toJson(instance.boxColor), 'boxXStroke': instance.boxXStroke, 'boxYStroke': instance.boxYStroke, }; diff --git a/api/lib/src/models/tool.dart b/api/lib/src/models/tool.dart index 71e6e1905462..2eb4ba4ca787 100644 --- a/api/lib/src/models/tool.dart +++ b/api/lib/src/models/tool.dart @@ -1,5 +1,7 @@ import 'dart:math'; +import 'package:butterfly_api/src/converter/color.dart'; +import 'package:dart_leap/dart_leap.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'area.dart'; @@ -78,7 +80,7 @@ sealed class Tool with _$Tool { @Default('') String displayIcon, @Default(LabelMode.text) LabelMode mode, @Default(false) bool zoomDependent, - @Default(BasicColors.black) int foreground, + @Default(SRGBColor.black) @ColorJsonConverter() SRGBColor foreground, @Default(PackAssetLocation()) PackAssetLocation styleSheet, @Default(2.0) double scale, }) = LabelTool; @@ -128,7 +130,7 @@ sealed class Tool with _$Tool { @Default(0.5) double hideDuration, @Default(5) double strokeWidth, @Default(0.4) double thinning, - @Default(BasicColors.red) int color, + @Default(BasicColors.red) @ColorJsonConverter() SRGBColor color, @Default(LaserAnimation.fade) LaserAnimation animation, }) = LaserTool; diff --git a/api/lib/src/models/tool.freezed.dart b/api/lib/src/models/tool.freezed.dart index 0fb08e085edb..f60eba4d63c2 100644 --- a/api/lib/src/models/tool.freezed.dart +++ b/api/lib/src/models/tool.freezed.dart @@ -691,7 +691,7 @@ abstract class _$$LabelToolImplCopyWith<$Res> implements $ToolCopyWith<$Res> { String displayIcon, LabelMode mode, bool zoomDependent, - int foreground, + @ColorJsonConverter() SRGBColor foreground, PackAssetLocation styleSheet, double scale}); @@ -739,7 +739,7 @@ class __$$LabelToolImplCopyWithImpl<$Res> foreground: null == foreground ? _value.foreground : foreground // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, styleSheet: null == styleSheet ? _value.styleSheet : styleSheet // ignore: cast_nullable_to_non_nullable @@ -770,7 +770,7 @@ class _$LabelToolImpl extends LabelTool { this.displayIcon = '', this.mode = LabelMode.text, this.zoomDependent = false, - this.foreground = BasicColors.black, + @ColorJsonConverter() this.foreground = SRGBColor.black, this.styleSheet = const PackAssetLocation(), this.scale = 2.0, final String? $type}) @@ -794,7 +794,8 @@ class _$LabelToolImpl extends LabelTool { final bool zoomDependent; @override @JsonKey() - final int foreground; + @ColorJsonConverter() + final SRGBColor foreground; @override @JsonKey() final PackAssetLocation styleSheet; @@ -832,7 +833,7 @@ abstract class LabelTool extends Tool { final String displayIcon, final LabelMode mode, final bool zoomDependent, - final int foreground, + @ColorJsonConverter() final SRGBColor foreground, final PackAssetLocation styleSheet, final double scale}) = _$LabelToolImpl; LabelTool._() : super._(); @@ -846,7 +847,8 @@ abstract class LabelTool extends Tool { String get displayIcon; LabelMode get mode; bool get zoomDependent; - int get foreground; + @ColorJsonConverter() + SRGBColor get foreground; PackAssetLocation get styleSheet; double get scale; @@ -1563,7 +1565,7 @@ abstract class _$$LaserToolImplCopyWith<$Res> implements $ToolCopyWith<$Res> { double hideDuration, double strokeWidth, double thinning, - int color, + @ColorJsonConverter() SRGBColor color, LaserAnimation animation}); } @@ -1617,7 +1619,7 @@ class __$$LaserToolImplCopyWithImpl<$Res> color: null == color ? _value.color : color // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, animation: null == animation ? _value.animation : animation // ignore: cast_nullable_to_non_nullable @@ -1636,7 +1638,7 @@ class _$LaserToolImpl extends LaserTool { this.hideDuration = 0.5, this.strokeWidth = 5, this.thinning = 0.4, - this.color = BasicColors.red, + @ColorJsonConverter() this.color = BasicColors.red, this.animation = LaserAnimation.fade, final String? $type}) : $type = $type ?? 'laser', @@ -1665,7 +1667,8 @@ class _$LaserToolImpl extends LaserTool { final double thinning; @override @JsonKey() - final int color; + @ColorJsonConverter() + final SRGBColor color; @override @JsonKey() final LaserAnimation animation; @@ -1702,7 +1705,7 @@ abstract class LaserTool extends Tool { final double hideDuration, final double strokeWidth, final double thinning, - final int color, + @ColorJsonConverter() final SRGBColor color, final LaserAnimation animation}) = _$LaserToolImpl; LaserTool._() : super._(); @@ -1717,7 +1720,8 @@ abstract class LaserTool extends Tool { double get hideDuration; double get strokeWidth; double get thinning; - int get color; + @ColorJsonConverter() + SRGBColor get color; LaserAnimation get animation; /// Create a copy of Tool diff --git a/api/lib/src/models/tool.g.dart b/api/lib/src/models/tool.g.dart index 95a0b5b33cb1..b9e66350ce09 100644 --- a/api/lib/src/models/tool.g.dart +++ b/api/lib/src/models/tool.g.dart @@ -93,7 +93,10 @@ _$LabelToolImpl _$$LabelToolImplFromJson(Map json) => _$LabelToolImpl( mode: $enumDecodeNullable(_$LabelModeEnumMap, json['mode']) ?? LabelMode.text, zoomDependent: json['zoomDependent'] as bool? ?? false, - foreground: (json['foreground'] as num?)?.toInt() ?? BasicColors.black, + foreground: json['foreground'] == null + ? SRGBColor.black + : const ColorJsonConverter() + .fromJson((json['foreground'] as num).toInt()), styleSheet: json['styleSheet'] == null ? const PackAssetLocation() : PackAssetLocation.fromJson( @@ -108,7 +111,7 @@ Map _$$LabelToolImplToJson(_$LabelToolImpl instance) => 'displayIcon': instance.displayIcon, 'mode': _$LabelModeEnumMap[instance.mode]!, 'zoomDependent': instance.zoomDependent, - 'foreground': instance.foreground, + 'foreground': const ColorJsonConverter().toJson(instance.foreground), 'styleSheet': instance.styleSheet.toJson(), 'scale': instance.scale, 'type': instance.$type, @@ -226,7 +229,9 @@ _$LaserToolImpl _$$LaserToolImplFromJson(Map json) => _$LaserToolImpl( hideDuration: (json['hideDuration'] as num?)?.toDouble() ?? 0.5, strokeWidth: (json['strokeWidth'] as num?)?.toDouble() ?? 5, thinning: (json['thinning'] as num?)?.toDouble() ?? 0.4, - color: (json['color'] as num?)?.toInt() ?? BasicColors.red, + color: json['color'] == null + ? BasicColors.red + : const ColorJsonConverter().fromJson((json['color'] as num).toInt()), animation: $enumDecodeNullable(_$LaserAnimationEnumMap, json['animation']) ?? LaserAnimation.fade, @@ -241,7 +246,7 @@ Map _$$LaserToolImplToJson(_$LaserToolImpl instance) => 'hideDuration': instance.hideDuration, 'strokeWidth': instance.strokeWidth, 'thinning': instance.thinning, - 'color': instance.color, + 'color': const ColorJsonConverter().toJson(instance.color), 'animation': _$LaserAnimationEnumMap[instance.animation]!, 'type': instance.$type, }; diff --git a/api/lib/src/models/view.dart b/api/lib/src/models/view.dart index 57d5d6782eaa..856f0f311eb7 100644 --- a/api/lib/src/models/view.dart +++ b/api/lib/src/models/view.dart @@ -1,14 +1,14 @@ +import 'package:butterfly_api/src/converter/color.dart'; +import 'package:dart_leap/dart_leap.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'colors.dart'; - part 'view.freezed.dart'; part 'view.g.dart'; @freezed sealed class ViewOption with _$ViewOption { const factory ViewOption({ - @Default(BasicColors.black) int gridColor, + @Default(SRGBColor.black) @ColorJsonConverter() SRGBColor gridColor, @Default(20) double gridXSize, @Default(20) double gridYSize, }) = _ViewOption; diff --git a/api/lib/src/models/view.freezed.dart b/api/lib/src/models/view.freezed.dart index 594d696a2597..46e8ee9913b6 100644 --- a/api/lib/src/models/view.freezed.dart +++ b/api/lib/src/models/view.freezed.dart @@ -20,7 +20,8 @@ ViewOption _$ViewOptionFromJson(Map json) { /// @nodoc mixin _$ViewOption { - int get gridColor => throw _privateConstructorUsedError; + @ColorJsonConverter() + SRGBColor get gridColor => throw _privateConstructorUsedError; double get gridXSize => throw _privateConstructorUsedError; double get gridYSize => throw _privateConstructorUsedError; @@ -40,7 +41,10 @@ abstract class $ViewOptionCopyWith<$Res> { ViewOption value, $Res Function(ViewOption) then) = _$ViewOptionCopyWithImpl<$Res, ViewOption>; @useResult - $Res call({int gridColor, double gridXSize, double gridYSize}); + $Res call( + {@ColorJsonConverter() SRGBColor gridColor, + double gridXSize, + double gridYSize}); } /// @nodoc @@ -66,7 +70,7 @@ class _$ViewOptionCopyWithImpl<$Res, $Val extends ViewOption> gridColor: null == gridColor ? _value.gridColor : gridColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, gridXSize: null == gridXSize ? _value.gridXSize : gridXSize // ignore: cast_nullable_to_non_nullable @@ -87,7 +91,10 @@ abstract class _$$ViewOptionImplCopyWith<$Res> __$$ViewOptionImplCopyWithImpl<$Res>; @override @useResult - $Res call({int gridColor, double gridXSize, double gridYSize}); + $Res call( + {@ColorJsonConverter() SRGBColor gridColor, + double gridXSize, + double gridYSize}); } /// @nodoc @@ -111,7 +118,7 @@ class __$$ViewOptionImplCopyWithImpl<$Res> gridColor: null == gridColor ? _value.gridColor : gridColor // ignore: cast_nullable_to_non_nullable - as int, + as SRGBColor, gridXSize: null == gridXSize ? _value.gridXSize : gridXSize // ignore: cast_nullable_to_non_nullable @@ -128,7 +135,7 @@ class __$$ViewOptionImplCopyWithImpl<$Res> @JsonSerializable() class _$ViewOptionImpl implements _ViewOption { const _$ViewOptionImpl( - {this.gridColor = BasicColors.black, + {@ColorJsonConverter() this.gridColor = SRGBColor.black, this.gridXSize = 20, this.gridYSize = 20}); @@ -137,7 +144,8 @@ class _$ViewOptionImpl implements _ViewOption { @override @JsonKey() - final int gridColor; + @ColorJsonConverter() + final SRGBColor gridColor; @override @JsonKey() final double gridXSize; @@ -185,7 +193,7 @@ class _$ViewOptionImpl implements _ViewOption { abstract class _ViewOption implements ViewOption { const factory _ViewOption( - {final int gridColor, + {@ColorJsonConverter() final SRGBColor gridColor, final double gridXSize, final double gridYSize}) = _$ViewOptionImpl; @@ -193,7 +201,8 @@ abstract class _ViewOption implements ViewOption { _$ViewOptionImpl.fromJson; @override - int get gridColor; + @ColorJsonConverter() + SRGBColor get gridColor; @override double get gridXSize; @override diff --git a/api/lib/src/models/view.g.dart b/api/lib/src/models/view.g.dart index c937886fb3bd..fd3cea5707eb 100644 --- a/api/lib/src/models/view.g.dart +++ b/api/lib/src/models/view.g.dart @@ -7,14 +7,17 @@ part of 'view.dart'; // ************************************************************************** _$ViewOptionImpl _$$ViewOptionImplFromJson(Map json) => _$ViewOptionImpl( - gridColor: (json['gridColor'] as num?)?.toInt() ?? BasicColors.black, + gridColor: json['gridColor'] == null + ? SRGBColor.black + : const ColorJsonConverter() + .fromJson((json['gridColor'] as num).toInt()), gridXSize: (json['gridXSize'] as num?)?.toDouble() ?? 20, gridYSize: (json['gridYSize'] as num?)?.toDouble() ?? 20, ); Map _$$ViewOptionImplToJson(_$ViewOptionImpl instance) => { - 'gridColor': instance.gridColor, + 'gridColor': const ColorJsonConverter().toJson(instance.gridColor), 'gridXSize': instance.gridXSize, 'gridYSize': instance.gridYSize, }; diff --git a/api/lib/src/protocol/event.dart b/api/lib/src/protocol/event.dart index d425f17125aa..26c51d3e5857 100644 --- a/api/lib/src/protocol/event.dart +++ b/api/lib/src/protocol/event.dart @@ -234,6 +234,9 @@ class DocumentEvent extends ReplayEvent with _$DocumentEvent { const factory DocumentEvent.elementsLayerConverted(List elements, [@Default('') String name]) = ElementsLayerConverted; + const factory DocumentEvent.encryptionChanged(String? password) = + EncryptionChanged; + factory DocumentEvent.fromJson(Map json) => _$DocumentEventFromJson(json); diff --git a/api/lib/src/protocol/event.freezed.dart b/api/lib/src/protocol/event.freezed.dart index 1475ec278c20..e9be0c83a8e8 100644 --- a/api/lib/src/protocol/event.freezed.dart +++ b/api/lib/src/protocol/event.freezed.dart @@ -122,6 +122,8 @@ DocumentEvent _$DocumentEventFromJson(Map json) { return AssetUpdated.fromJson(json); case 'elementsLayerConverted': return ElementsLayerConverted.fromJson(json); + case 'encryptionChanged': + return EncryptionChanged.fromJson(json); default: throw CheckedFromJsonException(json, 'type', 'DocumentEvent', @@ -5908,3 +5910,104 @@ abstract class ElementsLayerConverted extends DocumentEvent { _$$ElementsLayerConvertedImplCopyWith<_$ElementsLayerConvertedImpl> get copyWith => throw _privateConstructorUsedError; } + +/// @nodoc +abstract class _$$EncryptionChangedImplCopyWith<$Res> { + factory _$$EncryptionChangedImplCopyWith(_$EncryptionChangedImpl value, + $Res Function(_$EncryptionChangedImpl) then) = + __$$EncryptionChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String? password}); +} + +/// @nodoc +class __$$EncryptionChangedImplCopyWithImpl<$Res> + extends _$DocumentEventCopyWithImpl<$Res, _$EncryptionChangedImpl> + implements _$$EncryptionChangedImplCopyWith<$Res> { + __$$EncryptionChangedImplCopyWithImpl(_$EncryptionChangedImpl _value, + $Res Function(_$EncryptionChangedImpl) _then) + : super(_value, _then); + + /// Create a copy of DocumentEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? password = freezed, + }) { + return _then(_$EncryptionChangedImpl( + freezed == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$EncryptionChangedImpl extends EncryptionChanged { + const _$EncryptionChangedImpl(this.password, {final String? $type}) + : $type = $type ?? 'encryptionChanged', + super._(); + + factory _$EncryptionChangedImpl.fromJson(Map json) => + _$$EncryptionChangedImplFromJson(json); + + @override + final String? password; + + @JsonKey(name: 'type') + final String $type; + + @override + String toString() { + return 'DocumentEvent.encryptionChanged(password: $password)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$EncryptionChangedImpl && + (identical(other.password, password) || + other.password == password)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, password); + + /// Create a copy of DocumentEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$EncryptionChangedImplCopyWith<_$EncryptionChangedImpl> get copyWith => + __$$EncryptionChangedImplCopyWithImpl<_$EncryptionChangedImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$EncryptionChangedImplToJson( + this, + ); + } +} + +abstract class EncryptionChanged extends DocumentEvent { + const factory EncryptionChanged(final String? password) = + _$EncryptionChangedImpl; + const EncryptionChanged._() : super._(); + + factory EncryptionChanged.fromJson(Map json) = + _$EncryptionChangedImpl.fromJson; + + String? get password; + + /// Create a copy of DocumentEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$EncryptionChangedImplCopyWith<_$EncryptionChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/api/lib/src/protocol/event.g.dart b/api/lib/src/protocol/event.g.dart index 14247aab3d32..85edcc82811d 100644 --- a/api/lib/src/protocol/event.g.dart +++ b/api/lib/src/protocol/event.g.dart @@ -739,3 +739,16 @@ Map _$$ElementsLayerConvertedImplToJson( 'name': instance.name, 'type': instance.$type, }; + +_$EncryptionChangedImpl _$$EncryptionChangedImplFromJson(Map json) => + _$EncryptionChangedImpl( + json['password'] as String?, + $type: json['type'] as String?, + ); + +Map _$$EncryptionChangedImplToJson( + _$EncryptionChangedImpl instance) => + { + 'password': instance.password, + 'type': instance.$type, + }; diff --git a/api/pubspec.lock b/api/pubspec.lock index 15e17c050075..407151a00bef 100644 --- a/api/pubspec.lock +++ b/api/pubspec.lock @@ -174,6 +174,15 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.6" + dart_leap: + dependency: "direct main" + description: + path: "packages/dart_leap" + ref: db69a03082e6811c58dc2d0e5c23d04305e1623f + resolved-ref: db69a03082e6811c58dc2d0e5c23d04305e1623f + url: "https://github.com/LinwoodDev/dart_pkgs" + source: git + version: "1.0.0" dart_mappable: dependency: transitive description: @@ -322,8 +331,8 @@ packages: dependency: "direct main" description: path: "packages/lw_file_system_api" - ref: b9d6c6173bf75247ce5a4d47fab0e48b730a9696 - resolved-ref: b9d6c6173bf75247ce5a4d47fab0e48b730a9696 + ref: a0752f136913f64a975cb8b20ccb16fb6ce37737 + resolved-ref: a0752f136913f64a975cb8b20ccb16fb6ce37737 url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "1.0.0" diff --git a/api/pubspec.yaml b/api/pubspec.yaml index 20a36dcc4de6..f7c905ef61cc 100644 --- a/api/pubspec.yaml +++ b/api/pubspec.yaml @@ -19,7 +19,12 @@ dependencies: git: url: https://github.com/LinwoodDev/dart_pkgs path: packages/lw_file_system_api - ref: b9d6c6173bf75247ce5a4d47fab0e48b730a9696 + ref: a0752f136913f64a975cb8b20ccb16fb6ce37737 + dart_leap: + git: + url: https://github.com/LinwoodDev/dart_pkgs + path: packages/dart_leap + ref: db69a03082e6811c58dc2d0e5c23d04305e1623f dev_dependencies: test: ^1.25.3 diff --git a/app/android/Gemfile.lock b/app/android/Gemfile.lock index b0b7f14cb20a..9de345f10c70 100644 --- a/app/android/Gemfile.lock +++ b/app/android/Gemfile.lock @@ -10,7 +10,7 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.1026.0) + aws-partitions (1.1029.0) aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) @@ -155,7 +155,7 @@ GEM httpclient (2.8.3) jmespath (1.6.2) json (2.9.1) - jwt (2.9.3) + jwt (2.10.1) base64 mini_magick (4.13.2) mini_mime (1.1.5) @@ -167,7 +167,7 @@ GEM nkf (0.2.0) optparse (0.6.0) os (1.1.4) - plist (3.7.1) + plist (3.7.2) public_suffix (6.0.1) rake (13.2.1) representable (3.2.0) @@ -224,4 +224,4 @@ DEPENDENCIES screengrab BUNDLED WITH - 2.6.1 + 2.6.2 diff --git a/app/lib/api/changes.dart b/app/lib/api/changes.dart index b32b2cc8c613..ecec09882b1a 100644 --- a/app/lib/api/changes.dart +++ b/app/lib/api/changes.dart @@ -4,14 +4,9 @@ import 'package:butterfly/api/open.dart'; import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:lw_file_system/lw_file_system.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; -Future checkFileChanges( - BuildContext context, FileSystemEntity? entity) async { - if (entity is! FileSystemFile) return null; - final data = entity.data; - if (data == null) return null; +Future checkFileChanges(BuildContext context, NoteData data) async { final metadata = data.getMetadata(); if (metadata == null) return null; final version = metadata.fileVersion; @@ -42,10 +37,10 @@ Future checkFileChanges( actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: Text(AppLocalizations.of(context).cancel)), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel)), TextButton( onPressed: () => Navigator.of(context).pop(true), - child: Text(AppLocalizations.of(context).ok)), + child: Text(MaterialLocalizations.of(context).okButtonLabel)), ], ), ); diff --git a/app/lib/api/close_io.dart b/app/lib/api/close_io.dart index a740ff7850fb..350bdd1727d9 100644 --- a/app/lib/api/close_io.dart +++ b/app/lib/api/close_io.dart @@ -42,11 +42,11 @@ class IOCloseSubscription extends CloseSubscription with WindowListener { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), - child: Text(AppLocalizations.of(context).close), + child: Text(MaterialLocalizations.of(context).closeButtonLabel), ), ], ), diff --git a/app/lib/api/file_system.dart b/app/lib/api/file_system.dart index 0fc437fea52c..a48b4ac1ef04 100644 --- a/app/lib/api/file_system.dart +++ b/app/lib/api/file_system.dart @@ -15,6 +15,9 @@ import 'package:shared_preferences/shared_preferences.dart'; Uint8List _encode(NoteData data) => Uint8List.fromList(data.exportAsBytes()); NoteData _decode(Uint8List data) => NoteData.fromData(data); +Uint8List _encodeFile(NoteFile file) => file.data; +NoteFile _decodeFile(Uint8List data) => NoteFile(data); + const butterflySubDirectory = '/Linwood/Butterfly'; String? overrideButterflyDirectory; @@ -61,7 +64,7 @@ Future Function(ExternalStorage? storage) _getRemoteDirectory( Future getButterflyDocumentsDirectory([ExternalStorage? storage]) => _getRemoteDirectory('Documents')(storage); -typedef DocumentFileSystem = TypedDirectoryFileSystem; +typedef DocumentFileSystem = TypedDirectoryFileSystem; typedef TemplateFileSystem = TypedKeyFileSystem; typedef PackFileSystem = TypedKeyFileSystem; @@ -170,12 +173,12 @@ class ButterflyFileSystem { await fs.createFile('${pack.name}.bfly', pack); } - TypedDirectoryFileSystem buildDocumentSystem( + TypedDirectoryFileSystem buildDocumentSystem( [ExternalStorage? storage]) => TypedDirectoryFileSystem.build( _documentConfig, - onEncode: _encode, - onDecode: _decode, + onEncode: _encodeFile, + onDecode: _decodeFile, storage: storage, ); TypedKeyFileSystem buildTemplateSystem( diff --git a/app/lib/bloc/document_bloc.dart b/app/lib/bloc/document_bloc.dart index 238d85a58301..a7cb26e980b4 100644 --- a/app/lib/bloc/document_bloc.dart +++ b/app/lib/bloc/document_bloc.dart @@ -1008,6 +1008,14 @@ class DocumentBloc extends ReplayBloc { reset: true, ); }); + on((event, emit) { + final current = state; + if (current is! DocumentLoadSuccess) return; + var data = current.data; + final password = event.password; + data = data.changePassword(password); + _saveState(emit, state: current.copyWith(data: data)); + }); } void _saveState( diff --git a/app/lib/cubits/current_index.dart b/app/lib/cubits/current_index.dart index a5b198f13c29..f263f0fc0ead 100644 --- a/app/lib/cubits/current_index.dart +++ b/app/lib/cubits/current_index.dart @@ -976,10 +976,10 @@ class CurrentIndexCubit extends Cubit { state.absolute || location.fileType != AssetFileType.note) { final document = await fileSystem.createFileWithName( - name: currentData.name, suffix: '.bfly', currentData); + name: currentData.name, suffix: '.bfly', currentData.toFile()); location = document.location; } else { - await fileSystem.updateFile(location.path, currentData); + await fileSystem.updateFile(location.path, currentData.toFile()); } state.settingsCubit.addRecentHistory(location); emit(state.copyWith(location: location, saved: SaveState.saved)); diff --git a/app/lib/cubits/settings.dart b/app/lib/cubits/settings.dart index 3145e3d5391c..3b55b32772b6 100644 --- a/app/lib/cubits/settings.dart +++ b/app/lib/cubits/settings.dart @@ -226,7 +226,7 @@ class ButterflySettings with _$ButterflySettings, LeapSettings { @Default(0.5) double imageScale, @Default(2) double pdfQuality, @Default(PlatformTheme.system) PlatformTheme platformTheme, - @Default([]) List recentColors, + @Default([]) List recentColors, @Default([]) List flags, @Default(false) bool spreadPages, @Default(false) bool highContrast, @@ -311,8 +311,11 @@ class ButterflySettings with _$ButterflySettings, LeapSettings { platformTheme: prefs.containsKey('platform_theme') ? PlatformTheme.values.byName(prefs.getString('platform_theme')!) : PlatformTheme.system, - recentColors: - prefs.getStringList('recent_colors')?.map(int.parse).toList() ?? [], + recentColors: prefs + .getStringList('recent_colors') + ?.map((e) => SRGBColor(int.parse(e))) + .toList() ?? + [], flags: prefs.getStringList('flags') ?? [], spreadPages: prefs.getBool('spread_pages') ?? false, highContrast: prefs.getBool('high_contrast') ?? false, @@ -399,7 +402,7 @@ class ButterflySettings with _$ButterflySettings, LeapSettings { await prefs.setDouble('pdf_quality', pdfQuality); await prefs.setString('platform_theme', platformTheme.name); await prefs.setStringList( - 'recent_colors', recentColors.map((e) => e.toString()).toList()); + 'recent_colors', recentColors.map((e) => e.value.toString()).toList()); await prefs.setStringList('flags', flags); await prefs.setBool('spread_pages', spreadPages); await prefs.setBool('high_contrast', highContrast); @@ -834,7 +837,7 @@ class SettingsCubit extends Cubit Future resetPlatformTheme() => changePlatformTheme(PlatformTheme.system); - Future addRecentColors(int color) async { + Future addRecentColors(SRGBColor color) async { final recentColors = state.recentColors.toList(); recentColors.remove(color); recentColors.insert(0, color); @@ -845,7 +848,7 @@ class SettingsCubit extends Cubit return save(); } - Future removeRecentColors(int color) async { + Future removeRecentColors(SRGBColor color) async { final recentColors = state.recentColors.toList(); recentColors.remove(color); emit(state.copyWith(recentColors: recentColors)); diff --git a/app/lib/cubits/settings.freezed.dart b/app/lib/cubits/settings.freezed.dart index 3646342c5e9f..5ecc571ed70d 100644 --- a/app/lib/cubits/settings.freezed.dart +++ b/app/lib/cubits/settings.freezed.dart @@ -353,7 +353,7 @@ mixin _$ButterflySettings { double get imageScale => throw _privateConstructorUsedError; double get pdfQuality => throw _privateConstructorUsedError; PlatformTheme get platformTheme => throw _privateConstructorUsedError; - List get recentColors => throw _privateConstructorUsedError; + List get recentColors => throw _privateConstructorUsedError; List get flags => throw _privateConstructorUsedError; bool get spreadPages => throw _privateConstructorUsedError; bool get highContrast => throw _privateConstructorUsedError; @@ -418,7 +418,7 @@ abstract class $ButterflySettingsCopyWith<$Res> { double imageScale, double pdfQuality, PlatformTheme platformTheme, - List recentColors, + List recentColors, List flags, bool spreadPages, bool highContrast, @@ -646,7 +646,7 @@ class _$ButterflySettingsCopyWithImpl<$Res, $Val extends ButterflySettings> recentColors: null == recentColors ? _value.recentColors : recentColors // ignore: cast_nullable_to_non_nullable - as List, + as List, flags: null == flags ? _value.flags : flags // ignore: cast_nullable_to_non_nullable @@ -768,7 +768,7 @@ abstract class _$$ButterflySettingsImplCopyWith<$Res> double imageScale, double pdfQuality, PlatformTheme platformTheme, - List recentColors, + List recentColors, List flags, bool spreadPages, bool highContrast, @@ -996,7 +996,7 @@ class __$$ButterflySettingsImplCopyWithImpl<$Res> recentColors: null == recentColors ? _value._recentColors : recentColors // ignore: cast_nullable_to_non_nullable - as List, + as List, flags: null == flags ? _value._flags : flags // ignore: cast_nullable_to_non_nullable @@ -1093,7 +1093,7 @@ class _$ButterflySettingsImpl extends _ButterflySettings this.imageScale = 0.5, this.pdfQuality = 2, this.platformTheme = PlatformTheme.system, - final List recentColors = const [], + final List recentColors = const [], final List flags = const [], this.spreadPages = false, this.highContrast = false, @@ -1236,10 +1236,10 @@ class _$ButterflySettingsImpl extends _ButterflySettings @override @JsonKey() final PlatformTheme platformTheme; - final List _recentColors; + final List _recentColors; @override @JsonKey() - List get recentColors { + List get recentColors { if (_recentColors is EqualUnmodifiableListView) return _recentColors; // ignore: implicit_dynamic_type return EqualUnmodifiableListView(_recentColors); @@ -1552,7 +1552,7 @@ abstract class _ButterflySettings extends ButterflySettings { final double imageScale, final double pdfQuality, final PlatformTheme platformTheme, - final List recentColors, + final List recentColors, final List flags, final bool spreadPages, final bool highContrast, @@ -1639,7 +1639,7 @@ abstract class _ButterflySettings extends ButterflySettings { @override PlatformTheme get platformTheme; @override - List get recentColors; + List get recentColors; @override List get flags; @override diff --git a/app/lib/dialogs/area/context.dart b/app/lib/dialogs/area/context.dart index 2cf3bd0c8a20..ed3fa5c83cc7 100644 --- a/app/lib/dialogs/area/context.dart +++ b/app/lib/dialogs/area/context.dart @@ -1,6 +1,5 @@ import 'package:butterfly/bloc/document_bloc.dart'; import 'package:butterfly/cubits/settings.dart'; -import 'package:butterfly/dialogs/name.dart'; import 'package:butterfly/helpers/point.dart'; import 'package:butterfly/helpers/rect.dart'; import 'package:butterfly/widgets/context_menu.dart'; @@ -8,6 +7,7 @@ import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; 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 '../export/general.dart'; diff --git a/app/lib/dialogs/background/dialog.dart b/app/lib/dialogs/background/dialog.dart index 186b05a347ec..885627ca7af9 100644 --- a/app/lib/dialogs/background/dialog.dart +++ b/app/lib/dialogs/background/dialog.dart @@ -100,11 +100,12 @@ class BackgroundDialog extends StatelessWidget { ), actions: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: + Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ElevatedButton( - child: Text(AppLocalizations.of(context).ok), + child: Text(MaterialLocalizations.of(context).okButtonLabel), onPressed: () { context.read().add(DocumentBackgroundsChanged( [if (background != null) background!])); diff --git a/app/lib/dialogs/collaboration/start.dart b/app/lib/dialogs/collaboration/start.dart index fb036ae800cb..888889ebb1b4 100644 --- a/app/lib/dialogs/collaboration/start.dart +++ b/app/lib/dialogs/collaboration/start.dart @@ -52,7 +52,7 @@ class _StartCollaborationDialogState extends State controller: _addressController, validator: (value) { if (value?.isEmpty ?? true) { - return AppLocalizations.of(context).shouldNotEmpty; + return LeapLocalizations.of(context).shouldNotEmpty; } final address = InternetAddress.tryParse(value!); if (address == null) { @@ -72,7 +72,7 @@ class _StartCollaborationDialogState extends State keyboardType: TextInputType.number, validator: (value) { if (value?.isEmpty ?? true) { - return AppLocalizations.of(context).shouldNotEmpty; + return LeapLocalizations.of(context).shouldNotEmpty; } final number = int.tryParse(value!); if (number == null) { @@ -95,7 +95,7 @@ class _StartCollaborationDialogState extends State ), TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).close), + child: Text(MaterialLocalizations.of(context).closeButtonLabel), ), ], ), diff --git a/app/lib/dialogs/collaboration/view.dart b/app/lib/dialogs/collaboration/view.dart index e0b3fee2549a..8fdba4b9fd05 100644 --- a/app/lib/dialogs/collaboration/view.dart +++ b/app/lib/dialogs/collaboration/view.dart @@ -50,7 +50,7 @@ class ViewCollaborationDialog extends StatelessWidget { }, ), TextButton( - child: Text(AppLocalizations.of(context).close), + child: Text(MaterialLocalizations.of(context).closeButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ], diff --git a/app/lib/dialogs/collections.dart b/app/lib/dialogs/collections.dart index 701a3e8ed9da..9b194914fa39 100644 --- a/app/lib/dialogs/collections.dart +++ b/app/lib/dialogs/collections.dart @@ -1,6 +1,5 @@ import 'package:butterfly/bloc/document_bloc.dart'; import 'package:butterfly/dialogs/delete.dart'; -import 'package:butterfly/dialogs/name.dart'; import 'package:butterfly/handlers/handler.dart'; import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; diff --git a/app/lib/dialogs/export/general.dart b/app/lib/dialogs/export/general.dart index ceca11c2bf87..dd1540e2dc01 100644 --- a/app/lib/dialogs/export/general.dart +++ b/app/lib/dialogs/export/general.dart @@ -208,7 +208,8 @@ class _GeneralExportDialogState extends State { children: [ Expanded(child: Container()), TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context) + .cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), if (supportsShare()) diff --git a/app/lib/dialogs/export/pdf.dart b/app/lib/dialogs/export/pdf.dart index 31c813980332..145198e90dfe 100644 --- a/app/lib/dialogs/export/pdf.dart +++ b/app/lib/dialogs/export/pdf.dart @@ -11,7 +11,6 @@ import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:printing/printing.dart'; import '../../bloc/document_bloc.dart'; -import '../name.dart'; class PdfExportDialog extends StatefulWidget { final List areas; @@ -276,7 +275,8 @@ class _PdfExportDialogState extends State { Expanded(child: Container()), TextButton( child: Text( - AppLocalizations.of(context).cancel), + MaterialLocalizations.of(context) + .cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), @@ -498,7 +498,7 @@ class _AreaSelectionDialogState extends State<_AreaSelectionDialog> { Padding( padding: const EdgeInsets.all(8.0), child: TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ), @@ -544,7 +544,7 @@ class _ExportPresetsDialogState extends State { bloc.add(ExportPresetCreated(name, widget.areas!)); }, icon: const PhosphorIcon(PhosphorIconsLight.plus), - tooltip: AppLocalizations.of(context).create, + tooltip: LeapLocalizations.of(context).create, ) ]), Padding( @@ -601,7 +601,7 @@ class _ExportPresetsDialogState extends State { Padding( padding: const EdgeInsets.all(8.0), child: TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ), diff --git a/app/lib/dialogs/file_system/create.dart b/app/lib/dialogs/file_system/create.dart index bd75d5fd1e01..dcc07fa00fbe 100644 --- a/app/lib/dialogs/file_system/create.dart +++ b/app/lib/dialogs/file_system/create.dart @@ -1,7 +1,7 @@ import 'package:butterfly/api/file_system.dart'; import 'package:butterfly/models/defaults.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; class FileSystemAssetCreateDialog extends StatefulWidget { final bool isFolder; @@ -37,13 +37,13 @@ class _FileSystemAssetCreateDialogState key: _formKey, child: AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - title: Text(AppLocalizations.of(context).create), + title: Text(LeapLocalizations.of(context).create), content: TextFormField( decoration: InputDecoration( - filled: true, labelText: AppLocalizations.of(context).name), + filled: true, labelText: LeapLocalizations.of(context).name), validator: (value) { if (value?.isEmpty ?? true) { - return AppLocalizations.of(context).shouldNotEmpty; + return LeapLocalizations.of(context).shouldNotEmpty; } return null; }, @@ -52,18 +52,18 @@ class _FileSystemAssetCreateDialogState ), actions: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ElevatedButton( - child: Text(AppLocalizations.of(context).create), + child: Text(LeapLocalizations.of(context).create), onPressed: () async { final navigator = Navigator.of(context); if (_formKey.currentState?.validate() ?? false) { final newPath = '${widget.path}/${_nameController.text}'; if (!widget.isFolder) { - await widget.fileSystem - .createFile(newPath, DocumentDefaults.createDocument()); + await widget.fileSystem.createFile( + newPath, DocumentDefaults.createDocument().toFile()); } else { await widget.fileSystem.createDirectory(newPath); } diff --git a/app/lib/dialogs/file_system/move.dart b/app/lib/dialogs/file_system/move.dart index b234fe53f239..2412dd8e9e6c 100644 --- a/app/lib/dialogs/file_system/move.dart +++ b/app/lib/dialogs/file_system/move.dart @@ -2,6 +2,7 @@ import 'package:butterfly/api/file_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:lw_file_system/lw_file_system.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'tree.dart'; @@ -73,12 +74,12 @@ class _FileSystemAssetMoveDialogState extends State { return AlertDialog( actions: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(null), ), if (widget.moveMode != null) ElevatedButton( - child: Text(AppLocalizations.of(context).ok), + child: Text(MaterialLocalizations.of(context).okButtonLabel), onPressed: () => _move(widget.moveMode == MoveMode.duplicate), ), if (widget.moveMode == null) ...[ @@ -105,7 +106,7 @@ class _FileSystemAssetMoveDialogState extends State { const SizedBox(height: 16), TextField( decoration: InputDecoration( - filled: true, hintText: AppLocalizations.of(context).name), + filled: true, hintText: LeapLocalizations.of(context).name), autofocus: true, controller: _nameController, ), diff --git a/app/lib/dialogs/file_system/tree.dart b/app/lib/dialogs/file_system/tree.dart index 3ec14d9f43a0..8d2efd7e5080 100644 --- a/app/lib/dialogs/file_system/tree.dart +++ b/app/lib/dialogs/file_system/tree.dart @@ -1,6 +1,7 @@ import 'package:butterfly/api/file_system.dart'; import 'package:flutter/material.dart'; import 'package:lw_file_system/lw_file_system.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -139,7 +140,7 @@ class FileSystemDirectoryTreeViewState autofocus: true, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: AppLocalizations.of(context).name, + labelText: LeapLocalizations.of(context).name, ), onChanged: (value) => name = value, onFieldSubmitted: (value) { @@ -149,10 +150,11 @@ class FileSystemDirectoryTreeViewState actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: Text(AppLocalizations.of(context).cancel)), + child: Text( + MaterialLocalizations.of(context).cancelButtonLabel)), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), - child: Text(AppLocalizations.of(context).create)) + child: Text(LeapLocalizations.of(context).create)) ], ); }) ?? diff --git a/app/lib/dialogs/import/add.dart b/app/lib/dialogs/import/add.dart index 51a95155b576..fe09191b9707 100644 --- a/app/lib/dialogs/import/add.dart +++ b/app/lib/dialogs/import/add.dart @@ -39,7 +39,7 @@ class _AddDialogState extends State { final state = bloc.state; if (state is! DocumentLoaded) return; final background = - state.page.backgrounds.firstOrNull?.defaultColor ?? BasicColors.white; + state.page.backgrounds.firstOrNull?.defaultColor ?? SRGBColor.white; final defaultTool = updateToolDefaultColor(tool, background); bloc.add(ToolCreated(defaultTool)); if (!defaultTool.isAction()) { @@ -99,7 +99,7 @@ class _AddDialogState extends State { IconButton.outlined( onPressed: () => Navigator.of(context).pop(), icon: const PhosphorIcon(PhosphorIconsLight.x), - tooltip: AppLocalizations.of(context).close, + tooltip: MaterialLocalizations.of(context).closeButtonLabel, ), const SizedBox(width: 16), Text( diff --git a/app/lib/dialogs/import/camera.dart b/app/lib/dialogs/import/camera.dart index 20bebbd0fd0e..12508c7a3848 100644 --- a/app/lib/dialogs/import/camera.dart +++ b/app/lib/dialogs/import/camera.dart @@ -162,12 +162,13 @@ class _CameraDialogState extends State mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( - child: - Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context) + .cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ElevatedButton( - child: Text(AppLocalizations.of(context).ok), + child: Text(MaterialLocalizations.of(context) + .okButtonLabel), // Capture image on button press. onPressed: () async { final navigator = Navigator.of(context); diff --git a/app/lib/dialogs/import/confirmation.dart b/app/lib/dialogs/import/confirmation.dart index cf557d132e59..2bee12c60359 100644 --- a/app/lib/dialogs/import/confirmation.dart +++ b/app/lib/dialogs/import/confirmation.dart @@ -23,7 +23,7 @@ class PackImportConfirmationDialog extends StatelessWidget { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), @@ -54,7 +54,7 @@ class TemplateImportConfirmationDialog extends StatelessWidget { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), @@ -78,7 +78,7 @@ class UnknownImportConfirmationDialog extends StatelessWidget { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).close), + child: Text(MaterialLocalizations.of(context).closeButtonLabel), ), ], ); diff --git a/app/lib/dialogs/import/note.dart b/app/lib/dialogs/import/note.dart index 379e8d565497..8ae2d15ac804 100644 --- a/app/lib/dialogs/import/note.dart +++ b/app/lib/dialogs/import/note.dart @@ -107,11 +107,13 @@ class _NoteImportDialogState extends State { mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: Text( + MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ElevatedButton( - child: Text(AppLocalizations.of(context).ok), + child: + Text(MaterialLocalizations.of(context).okButtonLabel), onPressed: () => Navigator.of(context).pop( NoteDialogCallback(_selectedPages, _selectedPacks)), ), diff --git a/app/lib/dialogs/import/pages.dart b/app/lib/dialogs/import/pages.dart index e77e5ca9648b..f6345e83262e 100644 --- a/app/lib/dialogs/import/pages.dart +++ b/app/lib/dialogs/import/pages.dart @@ -137,11 +137,12 @@ class _PagesDialogState extends State { mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: + Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ElevatedButton( - child: Text(AppLocalizations.of(context).ok), + child: Text(MaterialLocalizations.of(context).okButtonLabel), onPressed: () => Navigator.of(context).pop(PageDialogCallback( _selected, _quality, diff --git a/app/lib/dialogs/name.dart b/app/lib/dialogs/name.dart deleted file mode 100644 index 637a600497c1..000000000000 --- a/app/lib/dialogs/name.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:lw_file_system/lw_file_system.dart'; - -class NameDialog extends StatelessWidget { - final GlobalKey _formKey = GlobalKey(); - final FormFieldValidator Function(String?)? validator; - final String? value, title, hint, button; - - NameDialog({ - super.key, - this.validator, - this.value, - this.title, - this.hint, - this.button, - }); - - @override - Widget build(BuildContext context) { - String value = this.value ?? ''; - void submit() { - if (_formKey.currentState!.validate()) { - Navigator.of(context).pop(value); - } - } - - return Form( - key: _formKey, - child: AlertDialog( - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).cancel)), - ElevatedButton( - onPressed: submit, - child: Text(button ?? AppLocalizations.of(context).create)), - ], - title: Text(title ?? AppLocalizations.of(context).enterName), - content: TextFormField( - decoration: InputDecoration( - filled: true, - hintText: hint ?? AppLocalizations.of(context).name, - ), - autofocus: true, - initialValue: value, - onChanged: (e) => value = e, - validator: validator?.call(value), - onFieldSubmitted: (value) => submit(), - ), - ), - ); - } -} - -FormFieldValidator Function(String?) defaultNameValidator( - BuildContext context, - [List existingNames = const []]) { - return (oldName) => (value) { - if (value == null || value.isEmpty) { - return AppLocalizations.of(context).shouldNotEmpty; - } - if (value == oldName) return null; - if (existingNames.contains(value)) { - return AppLocalizations.of(context).alreadyExists; - } - return null; - }; -} - -FormFieldValidator Function(String?) defaultFileNameValidator( - BuildContext context, [ - List existingNames = const [], -]) { - final nameValidator = defaultNameValidator(context, existingNames); - return (oldName) => (value) { - final nameError = nameValidator(oldName)(value); - if (nameError != null) return nameError; - if (value == null || value.isEmpty) { - return AppLocalizations.of(context).shouldNotEmpty; - } - if (hasInvalidFileName(value)) { - return AppLocalizations.of(context).invalidName; - } - return null; - }; -} diff --git a/app/lib/dialogs/packs/asset.dart b/app/lib/dialogs/packs/asset.dart index 882fe53ae901..b6c2ceaa34e6 100644 --- a/app/lib/dialogs/packs/asset.dart +++ b/app/lib/dialogs/packs/asset.dart @@ -4,6 +4,7 @@ import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import '../../bloc/document_bloc.dart'; @@ -79,7 +80,7 @@ class AssetDialog extends StatelessWidget { const SizedBox(height: 8), TextFormField( decoration: InputDecoration( - labelText: AppLocalizations.of(context).name, + labelText: LeapLocalizations.of(context).name, filled: true, ), initialValue: name, @@ -94,7 +95,8 @@ class AssetDialog extends StatelessWidget { onPressed: () { Navigator.of(context).pop(); }, - child: Text(AppLocalizations.of(context).cancel), + child: + Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () { @@ -104,7 +106,7 @@ class AssetDialog extends StatelessWidget { name, )); }, - child: Text(AppLocalizations.of(context).ok), + child: Text(MaterialLocalizations.of(context).okButtonLabel), ), ], ); diff --git a/app/lib/dialogs/packs/color_pick.dart b/app/lib/dialogs/packs/color_pick.dart index 8acd72315086..4ff8e8ce9346 100644 --- a/app/lib/dialogs/packs/color_pick.dart +++ b/app/lib/dialogs/packs/color_pick.dart @@ -12,14 +12,14 @@ import 'select.dart'; class ColorPalettePickerDialog extends StatefulWidget { final bool viewMode; - final Color value; + final SRGBColor value; final ColorPalette? palette; final ValueChanged? onChanged; final DocumentBloc? bloc; const ColorPalettePickerDialog({ super.key, - this.value = Colors.white, + this.value = SRGBColor.white, this.viewMode = false, this.bloc, this.palette, @@ -83,7 +83,7 @@ class _ColorPalettePickerDialogState extends State { if (_palette == null) return Container(); if ((_palette!.colors.length) <= index) return Container(); final color = _palette!.colors[index]; - final colorText = color.toHexColor(alpha: false); + final colorText = color.toHexString(alpha: false); return Column(mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(8.0), @@ -91,7 +91,7 @@ class _ColorPalettePickerDialogState extends State { children: [ Container( decoration: BoxDecoration( - color: Color(color), + color: color.toColor(), borderRadius: BorderRadius.circular(16), ), height: 75, @@ -116,11 +116,11 @@ class _ColorPalettePickerDialogState extends State { onTap: () async { final value = await showDialog( context: context, - builder: (context) => ColorPicker(value: Color(color))); + builder: (context) => ColorPicker(value: color)); if (value != null) { _changePalette(_palette!.copyWith( colors: List.from(_palette!.colors) - ..[index] = value.color)); + ..[index] = value.toSRGB())); } }), ListTile( @@ -204,7 +204,7 @@ class _ColorPalettePickerDialogState extends State { initialValue: _palette?.name, decoration: InputDecoration( labelText: - AppLocalizations.of(context) + LeapLocalizations.of(context) .name, filled: true, ), @@ -239,7 +239,7 @@ class _ColorPalettePickerDialogState extends State { height: 75, margin: const EdgeInsets.all(5), decoration: BoxDecoration( - color: Color(_palette!.colors[index]), + color: _palette!.colors[index].toColor(), borderRadius: const BorderRadius.all( Radius.circular(32))), ))), @@ -275,8 +275,9 @@ class _ColorPalettePickerDialogState extends State { ColorPicker(value: widget.value)); if (value == null) return; _changePalette(_palette!.copyWith( - colors: List.from(_palette!.colors) - ..add(value.color))); + colors: + List.from(_palette!.colors) + ..add(value.toSRGB()))); }, ), ), @@ -294,7 +295,7 @@ class _ColorPalettePickerDialogState extends State { context: context, builder: (context) => ColorPicker(value: widget.value)); - if (value != null) navigator.pop(value.color); + if (value != null) navigator.pop(value.value); }, child: Text(AppLocalizations.of(context).custom)), ], diff --git a/app/lib/dialogs/packs/dialog.dart b/app/lib/dialogs/packs/dialog.dart index 50596a3688b6..9aae95918cf2 100644 --- a/app/lib/dialogs/packs/dialog.dart +++ b/app/lib/dialogs/packs/dialog.dart @@ -368,8 +368,9 @@ class _PacksDialogState extends State onPressed: () => Navigator.of(context).pop(), child: Text( - AppLocalizations.of(context) - .cancel), + MaterialLocalizations.of( + context) + .cancelButtonLabel), ), ElevatedButton( onPressed: () => @@ -391,7 +392,7 @@ class _PacksDialogState extends State }, ), ListTile( - title: Text(AppLocalizations.of(ctx).create), + title: Text(LeapLocalizations.of(ctx).create), leading: const PhosphorIcon( PhosphorIconsLight.plusCircle), onTap: () async { diff --git a/app/lib/dialogs/packs/general.dart b/app/lib/dialogs/packs/general.dart index bd2dc653a1c5..eb6ee015d0e5 100644 --- a/app/lib/dialogs/packs/general.dart +++ b/app/lib/dialogs/packs/general.dart @@ -1,6 +1,7 @@ import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; class GeneralPackView extends StatelessWidget { @@ -28,7 +29,7 @@ class GeneralPackView extends StatelessWidget { const SizedBox(height: 8), TextFormField( decoration: InputDecoration( - labelText: AppLocalizations.of(context).name, + labelText: LeapLocalizations.of(context).name, icon: const PhosphorIcon(PhosphorIconsLight.textT), filled: true, ), diff --git a/app/lib/dialogs/packs/pack.dart b/app/lib/dialogs/packs/pack.dart index 4e8b6542e7f0..00590509c20a 100644 --- a/app/lib/dialogs/packs/pack.dart +++ b/app/lib/dialogs/packs/pack.dart @@ -93,12 +93,12 @@ class _PackDialogState extends State { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(pack), child: Text(widget.pack == null - ? AppLocalizations.of(context).create + ? LeapLocalizations.of(context).create : AppLocalizations.of(context).save), ), ], diff --git a/app/lib/dialogs/packs/palettes.dart b/app/lib/dialogs/packs/palettes.dart index afeb4af94569..9cdc3348bbbe 100644 --- a/app/lib/dialogs/packs/palettes.dart +++ b/app/lib/dialogs/packs/palettes.dart @@ -1,7 +1,7 @@ import 'package:butterfly/dialogs/packs/color_pick.dart'; -import 'package:butterfly/dialogs/name.dart'; import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; +import 'package:material_leap/material_leap.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -75,7 +75,7 @@ class PalettesPackView extends StatelessWidget { onChanged(value.setPalette(ColorPalette(name: name))); }, icon: const PhosphorIcon(PhosphorIconsLight.plus), - label: Text(AppLocalizations.of(context).create), + label: Text(LeapLocalizations.of(context).create), ), ), ], diff --git a/app/lib/dialogs/packs/select.dart b/app/lib/dialogs/packs/select.dart index e3dfd63676e7..e14cf10d28a1 100644 --- a/app/lib/dialogs/packs/select.dart +++ b/app/lib/dialogs/packs/select.dart @@ -90,7 +90,8 @@ class SelectPackAssetDialog extends StatelessWidget { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).cancel), + child: + Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ], )); diff --git a/app/lib/dialogs/packs/styles/general.dart b/app/lib/dialogs/packs/styles/general.dart index 5110393992bb..22d1cfec37c9 100644 --- a/app/lib/dialogs/packs/styles/general.dart +++ b/app/lib/dialogs/packs/styles/general.dart @@ -1,6 +1,6 @@ import 'package:butterfly_api/butterfly_text.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; class GeneralStyleView extends StatelessWidget { @@ -20,7 +20,7 @@ class GeneralStyleView extends StatelessWidget { const SizedBox(height: 8), TextFormField( decoration: InputDecoration( - labelText: AppLocalizations.of(context).name, + labelText: LeapLocalizations.of(context).name, icon: const PhosphorIcon(PhosphorIconsLight.textT), filled: true, ), diff --git a/app/lib/dialogs/packs/styles/paragraphs.dart b/app/lib/dialogs/packs/styles/paragraphs.dart index df7949b6817c..23cd0b35766b 100644 --- a/app/lib/dialogs/packs/styles/paragraphs.dart +++ b/app/lib/dialogs/packs/styles/paragraphs.dart @@ -1,4 +1,3 @@ -import 'package:butterfly/dialogs/name.dart'; import 'package:butterfly/models/defaults.dart'; import 'package:butterfly_api/butterfly_text.dart' as text; import 'package:collection/collection.dart'; @@ -192,7 +191,7 @@ class _ParagraphsStyleViewState extends State { if (currentParagraph == null) { return Center( child: ElevatedButton( - child: Text(AppLocalizations.of(context).create), + child: Text(LeapLocalizations.of(context).create), onPressed: () { widget.onChanged(widget.value.copyWith( paragraphProperties: { diff --git a/app/lib/dialogs/packs/styles/style.dart b/app/lib/dialogs/packs/styles/style.dart index ed267676b532..d5042cb00fbd 100644 --- a/app/lib/dialogs/packs/styles/style.dart +++ b/app/lib/dialogs/packs/styles/style.dart @@ -85,7 +85,7 @@ class _StyleDialogState extends State { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () { diff --git a/app/lib/dialogs/packs/styles/text.dart b/app/lib/dialogs/packs/styles/text.dart index 379ed172491b..5ea356a589fa 100644 --- a/app/lib/dialogs/packs/styles/text.dart +++ b/app/lib/dialogs/packs/styles/text.dart @@ -36,14 +36,12 @@ class _TextStyleViewState extends State { return Column( children: [ ColorField( - title: Text(AppLocalizations.of(context).color), + title: Text(LeapLocalizations.of(context).color), subtitle: widget.value.color == null ? Text(AppLocalizations.of(context).notSet) : null, custom: true, - value: widget.value.color == null - ? Colors.transparent - : Color(widget.value.color!), + value: widget.value.color ?? SRGBColor.transparent, leading: widget.value.color == null ? null : IconButton( @@ -53,17 +51,14 @@ class _TextStyleViewState extends State { widget.onChanged(widget.value.copyWith(color: null))), defaultColor: null, onChanged: (color) => - // ignore: deprecated_member_use - widget.onChanged(widget.value.copyWith(color: color.value))), + widget.onChanged(widget.value.copyWith(color: color))), ColorField( title: Text(AppLocalizations.of(context).background), subtitle: widget.value.backgroundColor == null ? Text(AppLocalizations.of(context).notSet) : null, custom: true, - value: widget.value.backgroundColor == null - ? Colors.transparent - : Color(widget.value.backgroundColor!), + value: widget.value.backgroundColor ?? SRGBColor.transparent, leading: widget.value.color == null ? null : IconButton( @@ -72,9 +67,8 @@ class _TextStyleViewState extends State { onPressed: () => widget.onChanged( widget.value.copyWith(backgroundColor: null))), defaultColor: null, - onChanged: (color) => widget.onChanged( - // ignore: deprecated_member_use - widget.value.copyWith(backgroundColor: color.value))), + onChanged: (color) => widget + .onChanged(widget.value.copyWith(backgroundColor: color))), ExactSlider( header: Text(AppLocalizations.of(context).size), bottom: widget.value.size == null @@ -198,14 +192,13 @@ class _TextStyleViewState extends State { widget.onChanged(widget.value.copyWith( decorationStyle: decorationStyle)))), ColorField( - title: Text(AppLocalizations.of(context).color), + title: Text(LeapLocalizations.of(context).color), custom: true, subtitle: widget.value.decorationColor == null ? Text(AppLocalizations.of(context).notSet) : null, - value: widget.value.decorationColor == null - ? Colors.transparent - : Color(widget.value.decorationColor!), + value: widget.value.decorationColor ?? + SRGBColor.transparent, leading: widget.value.decorationColor == null ? null : IconButton( @@ -217,9 +210,8 @@ class _TextStyleViewState extends State { .value .copyWith(decorationColor: null))), defaultColor: null, - onChanged: (color) => widget.onChanged(widget.value - // ignore: deprecated_member_use - .copyWith(decorationColor: color.value))), + onChanged: (color) => widget.onChanged( + widget.value.copyWith(decorationColor: color))), Padding( padding: const EdgeInsets.all(16.0), child: ExactSlider( diff --git a/app/lib/dialogs/packs/styles/texts.dart b/app/lib/dialogs/packs/styles/texts.dart index 470eb5c1cb7a..3cac393f9677 100644 --- a/app/lib/dialogs/packs/styles/texts.dart +++ b/app/lib/dialogs/packs/styles/texts.dart @@ -1,4 +1,3 @@ -import 'package:butterfly/dialogs/name.dart'; import 'package:butterfly_api/butterfly_text.dart' as text; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; @@ -189,7 +188,7 @@ class _TextsStyleViewState extends State { if (currentSpan == null) { return Center( child: ElevatedButton( - child: Text(AppLocalizations.of(context).create), + child: Text(LeapLocalizations.of(context).create), onPressed: () { widget.onChanged(widget.value.copyWith( spanProperties: { diff --git a/app/lib/dialogs/packs/styles/view.dart b/app/lib/dialogs/packs/styles/view.dart index c1ecf46bb33d..4a18a4b2b690 100644 --- a/app/lib/dialogs/packs/styles/view.dart +++ b/app/lib/dialogs/packs/styles/view.dart @@ -3,6 +3,7 @@ import 'package:butterfly_api/butterfly_text.dart' as text; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import '../../../bloc/document_bloc.dart'; @@ -89,7 +90,7 @@ class StylesPackView extends StatelessWidget { onChanged(value.setStyle(styleSheet)); }, icon: const PhosphorIcon(PhosphorIconsLight.plus), - label: Text(AppLocalizations.of(context).create), + label: Text(LeapLocalizations.of(context).create), ), ), ], diff --git a/app/lib/dialogs/presentation.dart b/app/lib/dialogs/presentation.dart index b9073ff36e0b..de9584125d48 100644 --- a/app/lib/dialogs/presentation.dart +++ b/app/lib/dialogs/presentation.dart @@ -47,7 +47,7 @@ class PresentationControlsDialog extends StatelessWidget { return StatefulBuilder( builder: (context, setState) => SwitchListTile( value: fullscreen, - title: Text(AppLocalizations.of(context).fullScreen), + title: Text(LeapLocalizations.of(context).fullScreen), onChanged: (value) { setFullScreen(value); setState(() => fullscreen = value); @@ -61,7 +61,7 @@ class PresentationControlsDialog extends StatelessWidget { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), diff --git a/app/lib/dialogs/sync.dart b/app/lib/dialogs/sync.dart index ae2a7608d0c4..d3c6f513f8f0 100644 --- a/app/lib/dialogs/sync.dart +++ b/app/lib/dialogs/sync.dart @@ -43,7 +43,8 @@ class _SyncDialogState extends State { leading: IconButton.outlined( icon: const PhosphorIcon(PhosphorIconsLight.x), onPressed: () => Navigator.pop(context), - tooltip: AppLocalizations.of(context).close, + tooltip: + MaterialLocalizations.of(context).closeButtonLabel, ), ), const Divider(), diff --git a/app/lib/dialogs/template.dart b/app/lib/dialogs/template.dart index 23c3bfec49d7..a579ae46cc1d 100644 --- a/app/lib/dialogs/template.dart +++ b/app/lib/dialogs/template.dart @@ -3,7 +3,6 @@ import 'package:butterfly/actions/new.dart'; import 'package:butterfly/api/file_system.dart'; import 'package:butterfly/api/save.dart'; import 'package:butterfly/cubits/settings.dart'; -import 'package:butterfly/dialogs/name.dart'; import 'package:butterfly/visualizer/tool.dart'; import 'package:butterfly/widgets/connection_button.dart'; import 'package:butterfly/widgets/option_button.dart'; @@ -85,7 +84,7 @@ class _TemplateDialogState extends State { leading: IconButton.outlined( icon: const PhosphorIcon(PhosphorIconsLight.x), onPressed: () => Navigator.of(context).pop(), - tooltip: AppLocalizations.of(context).close, + tooltip: MaterialLocalizations.of(context).closeButtonLabel, ), headerActions: [ ConnectionButton( @@ -122,11 +121,13 @@ class _TemplateDialogState extends State { content: Text(AppLocalizations.of(context).reallyReset), actions: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: Text( + MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ElevatedButton( - child: Text(AppLocalizations.of(context).ok), + child: + Text(MaterialLocalizations.of(context).okButtonLabel), onPressed: () async { for (final template in await _templateSystem.getKeys()) { _templateSystem.deleteFile(template); @@ -150,7 +151,7 @@ class _TemplateDialogState extends State { if (widget.bloc != null) ElevatedButton.icon( onPressed: () => _showCreateDialog(widget.bloc!), - label: Text(AppLocalizations.of(context).create), + label: Text(LeapLocalizations.of(context).create), icon: const PhosphorIcon(PhosphorIconsLight.floppyDisk), ) ], @@ -305,7 +306,7 @@ class _TemplateDialogState extends State { initialValue: name, onChanged: (e) => name = e, decoration: InputDecoration( - labelText: AppLocalizations.of(context).name, + labelText: LeapLocalizations.of(context).name, filled: true, ), ), @@ -323,11 +324,12 @@ class _TemplateDialogState extends State { ), actions: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: + Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(), ), ElevatedButton( - child: Text(AppLocalizations.of(context).create), + child: Text(LeapLocalizations.of(context).create), onPressed: () async { bloc.createTemplate( _templateSystem.storage?.identifier, diff --git a/app/lib/dialogs/texture.dart b/app/lib/dialogs/texture.dart index 695a9004a152..df5b0799e928 100644 --- a/app/lib/dialogs/texture.dart +++ b/app/lib/dialogs/texture.dart @@ -37,11 +37,10 @@ class _TextureViewState extends State { child: Column( children: [ ColorField( - title: Text(AppLocalizations.of(context).color), - value: Color(widget.value.boxColor), + title: Text(LeapLocalizations.of(context).color), + value: widget.value.boxColor, onChanged: (value) => - // ignore: deprecated_member_use - widget.onChanged(widget.value.copyWith(boxColor: value.value)), + widget.onChanged(widget.value.copyWith(boxColor: value)), ), const SizedBox(height: 16), TabBar.secondary(tabs: [ @@ -58,11 +57,10 @@ class _TextureViewState extends State { child: TabBarView(children: [ ListView(children: [ ColorField( - value: Color(widget.value.boxXColor), - title: Text(AppLocalizations.of(context).color), - onChanged: (value) => widget - // ignore: deprecated_member_use - .onChanged(widget.value.copyWith(boxXColor: value.value)), + value: widget.value.boxXColor, + title: Text(LeapLocalizations.of(context).color), + onChanged: (value) => + widget.onChanged(widget.value.copyWith(boxXColor: value)), ), const SizedBox(height: 16), ExactSlider( @@ -98,11 +96,10 @@ class _TextureViewState extends State { ]), ListView(children: [ ColorField( - title: Text(AppLocalizations.of(context).color), - value: Color(widget.value.boxYColor), - onChanged: (value) => widget - // ignore: deprecated_member_use - .onChanged(widget.value.copyWith(boxYColor: value.value)), + title: Text(LeapLocalizations.of(context).color), + value: widget.value.boxYColor, + onChanged: (value) => + widget.onChanged(widget.value.copyWith(boxYColor: value)), ), const SizedBox(height: 16), ExactSlider( diff --git a/app/lib/handlers/area.dart b/app/lib/handlers/area.dart index c360c83e6d43..f8a51feea04d 100644 --- a/app/lib/handlers/area.dart +++ b/app/lib/handlers/area.dart @@ -222,7 +222,7 @@ class AreaHandler extends Handler { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ], ), diff --git a/app/lib/handlers/eye_dropper.dart b/app/lib/handlers/eye_dropper.dart index 6d421b5b96cc..a204cab059c5 100644 --- a/app/lib/handlers/eye_dropper.dart +++ b/app/lib/handlers/eye_dropper.dart @@ -26,20 +26,19 @@ class EyeDropperHandler extends Handler { final pixel = image.getPixel(0, 0); final handler = context.getCurrentIndexCubit().getHandler(disableTemporary: true); + final color = SRGBColor.from( + r: pixel.r.toInt(), + g: pixel.g.toInt(), + b: pixel.b.toInt(), + ); if (handler is ColoredHandler) { - final color = pixel.a.toInt() << 24 | - pixel.r.toInt() << 16 | - pixel.g.toInt() << 8 | - pixel.b.toInt(); handler.changeToolColor(context.getDocumentBloc(), color); } else { - final color = - pixel.r.toInt() << 16 | pixel.g.toInt() << 8 | pixel.b.toInt(); saveToClipboard( context.buildContext, - color.toHexColor(alpha: false), + color.toHexString(alpha: false), leading: ColorButton( - color: Color(color).withAlpha(255), + color: color.toColor().withAlpha(255), size: 32, ), ); diff --git a/app/lib/handlers/handler.dart b/app/lib/handlers/handler.dart index 4a77b04d6ffc..45d857964c6e 100644 --- a/app/lib/handlers/handler.dart +++ b/app/lib/handlers/handler.dart @@ -42,7 +42,6 @@ import '../actions/select.dart'; import '../api/save.dart'; import '../cubits/current_index.dart'; import '../dialogs/import/camera.dart'; -import '../dialogs/name.dart'; import '../models/label.dart'; import '../models/viewport.dart'; import '../renderers/cursors/eraser.dart'; @@ -277,8 +276,8 @@ extension ToolHandler on Handler { } mixin ColoredHandler on Handler { - int getColor(); - T setColor(int color); + SRGBColor getColor(); + T setColor(SRGBColor color); @override PreferredSizeWidget? getToolbar(DocumentBloc bloc) => @@ -298,7 +297,7 @@ mixin ColoredHandler on Handler { ) : null; - void changeToolColor(DocumentBloc bloc, int value) => + void changeToolColor(DocumentBloc bloc, SRGBColor value) => changeTool(bloc, setColor(value)); } diff --git a/app/lib/handlers/laser.dart b/app/lib/handlers/laser.dart index 983862d328b1..3df076427f7e 100644 --- a/app/lib/handlers/laser.dart +++ b/app/lib/handlers/laser.dart @@ -35,7 +35,7 @@ class LaserHandler extends Handler with ColoredHandler { PenElement _updateElement(PenElement element, Duration difference) { final duration = _getDuration(); final hideDuration = _getHideDuration(); - final delta = + final double delta = ((difference - duration).inMilliseconds / hideDuration.inMilliseconds) .clamp(0, 1); if (data.animation == LaserAnimation.path) { @@ -44,13 +44,12 @@ class LaserHandler extends Handler with ColoredHandler { points.sublist((points.length * delta).round(), points.length); return element.copyWith(points: subPoints); } - var color = Color(data.color); + var color = data.color; final toolOpacity = color.a; final opacity = (1 - delta) * toolOpacity; - color = color.withValues(alpha: opacity.clamp(0, 1)); + color = color.withValues(a: opacity.clamp(0, 1).round()); return element.copyWith( - // ignore: deprecated_member_use - property: element.property.copyWith(color: color.value), + property: element.property.copyWith(color: color), ); } @@ -159,10 +158,10 @@ class LaserHandler extends Handler with ColoredHandler { } @override - int getColor() => data.color; + SRGBColor getColor() => data.color; @override - LaserTool setColor(int color) => data.copyWith(color: color); + LaserTool setColor(SRGBColor color) => data.copyWith(color: color); @override MouseCursor get cursor => (_hideCursorWhileDrawing && _elements.isNotEmpty) diff --git a/app/lib/handlers/pen.dart b/app/lib/handlers/pen.dart index 7e2d0367d6da..85b401c0915e 100644 --- a/app/lib/handlers/pen.dart +++ b/app/lib/handlers/pen.dart @@ -350,12 +350,12 @@ class PenHandler extends Handler with ColoredHandler { } @override - int getColor() => data.property.color; + SRGBColor getColor() => data.property.color; @override - PenTool setColor(int color) => data.copyWith( + PenTool setColor(SRGBColor color) => data.copyWith( property: data.property - .copyWith(color: convertOldColor(color, data.property.color))); + .copyWith(color: color.withValues(a: data.property.color.a))); @override MouseCursor get cursor => (_hideCursorWhileDrawing && elements.isNotEmpty) diff --git a/app/lib/handlers/shape.dart b/app/lib/handlers/shape.dart index 3daad860c791..4b161c84f20d 100644 --- a/app/lib/handlers/shape.dart +++ b/app/lib/handlers/shape.dart @@ -33,9 +33,9 @@ class ShapeHandler extends PastingHandler with ColoredHandler { double get constraintedWidth => data.constrainedWidth; @override - int getColor() => data.property.color; + SRGBColor getColor() => data.property.color; @override - ShapeTool setColor(int color) => + ShapeTool setColor(SRGBColor color) => data.copyWith(property: data.property.copyWith(color: color)); } diff --git a/app/lib/helpers/color.dart b/app/lib/helpers/color.dart index c5b77506886c..787599e97b8b 100644 --- a/app/lib/helpers/color.dart +++ b/app/lib/helpers/color.dart @@ -1,10 +1,9 @@ import 'package:butterfly_api/butterfly_api.dart'; -import 'package:flutter/material.dart'; import 'package:material_leap/material_leap.dart'; -Tool updateToolDefaultColor(Tool tool, int color) { +Tool updateToolDefaultColor(Tool tool, SRGBColor color) { final defaultColor = - isDarkColor(Color(color)) ? BasicColors.white : BasicColors.black; + color.toColor().isDark() ? SRGBColor.white : SRGBColor.black; return switch (tool) { PenTool e => e.copyWith(property: e.property.copyWith(color: defaultColor)), ShapeTool e => diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 4252f697bd04..7b7354fc39e6 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -6,10 +6,6 @@ "darkTheme": "Dark theme", "lightTheme": "Light theme", "systemTheme": "Use default system theme", - "enterName": "Please enter the name", - "create": "Create", - "ok": "Okay", - "cancel": "Cancel", "view": "View", "edit": "Edit", "export": "Export", @@ -18,7 +14,6 @@ "zoomIn": "Zoom in", "zoomOut": "Zoom out", "resetZoom": "Reset zoom", - "name": "Name", "strokeWidth": "Stroke width", "includeEraser": "Include eraser?", "thinning": "Thinning", @@ -36,7 +31,6 @@ "project": "Project", "general": "General", "copyTitle": "Copied to clipboard", - "copyMessage": "You can now paste it into a text editor", "loading": "Loading...", "enterText": "Enter the text", "size": "Size", @@ -56,7 +50,6 @@ "documentation": "Documentation", "changelog": "Changelog", "existOverride": "This element already exist. Overwrite?", - "color": "Color", "description": "Description", "fill": "Fill", "defaultPalette": "Default palette", @@ -65,7 +58,6 @@ "remove": "Remove", "removeConfirm": "Do you really want to remove this?", "resetPalette": "Reset palette", - "close": "Close", "custom": "Custom", "decoration": "Decoration", "underline": "Underline", @@ -108,7 +100,6 @@ } } }, - "shouldNotEmpty": "This value should not be empty", "waypoints": "Waypoints", "origin": "Origin", "import": "Import", @@ -202,9 +193,7 @@ "areas": "Areas", "enterArea": "Enter the area", "exitArea": "Exit the area", - "alreadyExists": "This element already exists", "currentArea": "Current area", - "fullScreen": "Full screen", "design": "Design", "text": "Text", "welcome": "Hey, this is Linwood Butterfly", @@ -269,13 +258,6 @@ "hideDetails": "Hide details", "error": "Error", "stackTrace": "Stack trace", - "alwaysOnTop": "Always on top", - "exitAlwaysOnTop": "Exit always on top", - "maximize": "Maximize", - "minimize": "Minimize", - "restore": "Restore", - "enterFullScreen": "Enter full screen", - "exitFullScreen": "Exit full screen", "laser": "Laser", "duration": "Duration", "quality": "Quality", @@ -490,7 +472,6 @@ "modified": "Modified", "quickstart": "Quickstart", "noTemplates": "There are currently no templates available", - "reset": "Reset", "importCorePack": "Import core pack", "importCorePackDescription": "Import the core pack that contains all basic assets to get started. This will override the current core pack.", "never": "Never", @@ -509,7 +490,6 @@ "sendToBack": "Send to back", "bringForward": "Bring forward", "sendBackward": "Send backward", - "invalidName": "Invalid name", "rotation": "Rotation", "onlyAvailableLargerScreen": "Only available on larger screens", "toolbarPosition": "Toolbar position", @@ -645,5 +625,15 @@ "high": "High", "highDescription": "Description: Maximizes quality at the cost of performance. Bakes an image covering 2 times the visible area, ensuring seamless rendering even during rapid scrolling or zooming.", "renderResolution": "Render resolution", - "translate": "Translate" + "translate": "Translate", + "unencrypted": "Unencrypted", + "encrypted": "Decrypted", + "encryptDocumentMessage": "Click to encrypt the document", + "unencryptDocumentMessage": "Click to unencrypt the document", + "unencrypt": "Unencrypt", + "encrypt": "Encrypt", + "encryptWarning": "This will encrypt the document. You will need to remember the password to decrypt it.", + "unencryptWarning": "This will unencrypt the document. The password will be removed and everyone with access will be able to open it.", + "confirmPassword": "Confirm password", + "passwordMismatch": "The passwords do not match" } diff --git a/app/lib/main.dart b/app/lib/main.dart index 224cfa4f0fa1..b86e66850a8a 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -18,7 +18,6 @@ import 'package:flutter_web_plugins/url_strategy.dart'; import 'package:go_router/go_router.dart'; import 'package:lw_file_system/lw_file_system.dart'; import 'package:lw_sysapi/lw_sysapi.dart'; -import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:material_leap/material_leap.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:shared_preferences/shared_preferences.dart'; diff --git a/app/lib/models/defaults.dart b/app/lib/models/defaults.dart index 956acc2eb33b..5784d96a8c65 100644 --- a/app/lib/models/defaults.dart +++ b/app/lib/models/defaults.dart @@ -7,18 +7,19 @@ import 'package:flutter/material.dart'; import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/services.dart' show rootBundle; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:material_leap/material_leap.dart'; class DocumentDefaults { static NoteData? _corePack; DocumentDefaults._(); - static Future _createPlainThumnail(Color color) async { + static Future _createPlainThumnail(SRGBColor color) async { final size = Size(kThumbnailWidth.toDouble(), kThumbnailHeight.toDouble()); final recorder = ui.PictureRecorder(); final canvas = Canvas(recorder); - canvas.drawRect( - Rect.fromLTWH(0, 0, size.width, size.height), Paint()..color = color); + canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), + Paint()..color = color.toColor()); final picture = recorder.endRecording(); final image = await picture.toImage(size.width.toInt(), size.height.toInt()); @@ -26,7 +27,7 @@ class DocumentDefaults { return bytes!.buffer.asUint8List(); } - static List createTools([int? background]) => [ + static List createTools([SRGBColor? background]) => [ SelectTool(mode: SelectMode.lasso), PenTool(), PathEraserTool(), @@ -53,7 +54,7 @@ class DocumentDefaults { final color = bg.defaultColor; return createTemplate( name: e.$1, - thumbnail: await _createPlainThumnail(Color(color)), + thumbnail: await _createPlainThumnail(color), backgrounds: [bg], ); }).toList()); @@ -119,7 +120,7 @@ class DocumentDefaults { ]); } - static DocumentInfo createInfo([int? background]) { + static DocumentInfo createInfo([SRGBColor? background]) { return DocumentInfo(tools: createTools(background)); } diff --git a/app/lib/renderers/cursors/eraser.dart b/app/lib/renderers/cursors/eraser.dart index b7218c7d99a5..ac583fada09d 100644 --- a/app/lib/renderers/cursors/eraser.dart +++ b/app/lib/renderers/cursors/eraser.dart @@ -1,6 +1,7 @@ import 'package:butterfly/cubits/transform.dart'; import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; +import 'package:material_leap/material_leap.dart'; import '../../models/cursor.dart'; import '../renderer.dart'; @@ -30,9 +31,10 @@ class EraserCursor extends Renderer> { Paint() ..style = PaintingStyle.stroke ..color = switch (background) { - TextureBackground e => Color(e.texture.boxColor), - _ => Colors.white, + TextureBackground e => e.texture.boxColor, + _ => SRGBColor.white, } + .toColor() ..strokeCap = StrokeCap.round ..invertColors = true ..strokeWidth = radius / transform.size diff --git a/app/lib/renderers/cursors/label.dart b/app/lib/renderers/cursors/label.dart index e6c63f388f99..443d2ba33ac4 100644 --- a/app/lib/renderers/cursors/label.dart +++ b/app/lib/renderers/cursors/label.dart @@ -1,9 +1,8 @@ -// ignore_for_file: deprecated_member_use - import 'package:butterfly/cubits/transform.dart'; import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; import 'package:butterfly_api/butterfly_text.dart' as text; +import 'package:material_leap/material_leap.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import '../../models/cursor.dart'; @@ -33,9 +32,8 @@ class LabelCursor extends Renderer { (element.context?.labelElement?.scale ?? (element.tool.scale * (element.tool.zoomDependent ? 1 / transform.size : 1))); - final iconColor = Color(property.span.color ?? - colorScheme?.primary.value ?? - Colors.black.value); + final iconColor = + property.span.color ?? colorScheme?.primary.toSRGB() ?? SRGBColor.black; final iconPainter = TextPainter( textDirection: TextDirection.rtl, text: TextSpan( @@ -44,7 +42,7 @@ class LabelCursor extends Renderer { fontFamily: icon.fontFamily, package: icon.fontPackage, fontSize: iconSize, - color: iconColor, + color: iconColor.toColor(), fontStyle: property.span.getItalic() ? FontStyle.italic : FontStyle.normal, ), @@ -80,7 +78,7 @@ class LabelSelectionCursor extends Renderer { ); canvas.drawRect( rect, - Paint()..color = color.withOpacity(0.5), + Paint()..color = color.withValues(alpha: 0.5), ); } // Paint cursor diff --git a/app/lib/renderers/elements/path.dart b/app/lib/renderers/elements/path.dart index ddefb85cf32d..ca0f55b32fcf 100644 --- a/app/lib/renderers/elements/path.dart +++ b/app/lib/renderers/elements/path.dart @@ -1,6 +1,6 @@ part of '../renderer.dart'; -typedef PathVisual = ({int color, bool fill}); +typedef PathVisual = ({SRGBColor color, bool fill}); abstract class PathRenderer extends Renderer { @override @@ -24,7 +24,7 @@ abstract class PathRenderer extends Renderer { Paint buildPaint([DocumentPage? page, bool foreground = false]) { final visual = buildPathVisual(page, foreground); return Paint() - ..color = Color(visual.color) + ..color = visual.color.toColor() ..style = visual.fill ? PaintingStyle.fill : PaintingStyle.stroke ..strokeCap = StrokeCap.round; } @@ -168,7 +168,7 @@ abstract class PathRenderer extends Renderer { xml.getElement('svg')?.createElement('path') ?..setAttribute('d', path) - ..setAttribute('fill', visual.color.toHexColor()) + ..setAttribute('fill', visual.color.toHexString()) ..setAttribute('stroke', 'none') ..setAttribute('stroke-linecap', 'round') ..setAttribute('stroke-linejoin', 'round'); diff --git a/app/lib/renderers/elements/shape.dart b/app/lib/renderers/elements/shape.dart index e5d49ee20369..aed94082297e 100644 --- a/app/lib/renderers/elements/shape.dart +++ b/app/lib/renderers/elements/shape.dart @@ -33,7 +33,8 @@ class ShapeRenderer extends Renderer { bottomLeft: bottomLeftCornerRadius, bottomRight: bottomRightCornerRadius, ), - _buildPaint(color: Color(shape.fillColor), style: PaintingStyle.fill), + _buildPaint( + color: shape.fillColor.toColor(), style: PaintingStyle.fill), ); if (strokeWidth > 0) { canvas.drawRRect( @@ -51,7 +52,7 @@ class ShapeRenderer extends Renderer { canvas.drawOval( drawRect, _buildPaint( - color: Color(shape.fillColor), style: PaintingStyle.fill)); + color: shape.fillColor.toColor(), style: PaintingStyle.fill)); if (strokeWidth > 0) { canvas.drawOval(rect, paint); } @@ -68,7 +69,7 @@ class ShapeRenderer extends Renderer { canvas.drawPath( path, _buildPaint( - color: Color(shape.fillColor), style: PaintingStyle.fill)); + color: shape.fillColor.toColor(), style: PaintingStyle.fill)); if (strokeWidth > 0) { canvas.drawPath(path, paint); } @@ -76,7 +77,7 @@ class ShapeRenderer extends Renderer { } Paint _buildPaint({Color? color, PaintingStyle? style}) => Paint() - ..color = color ?? Color(element.property.color) + ..color = color ?? element.property.color.toColor() ..strokeWidth = element.property.strokeWidth ..style = style ?? PaintingStyle.stroke ..strokeCap = StrokeCap.round @@ -121,8 +122,8 @@ class ShapeRenderer extends Renderer { 'path', attributes: { 'd': d, - 'fill': shape.fillColor.toHexColor(), - 'stroke': element.property.color.toHexColor(), + 'fill': shape.fillColor.toHexString(), + 'stroke': element.property.color.toHexString(), 'stroke-width': '${element.property.strokeWidth}px', }, ); @@ -134,8 +135,8 @@ class ShapeRenderer extends Renderer { 'cy': '${drawRect.center.dy}', 'rx': '${drawRect.width / 2}', 'ry': '${drawRect.height / 2}', - 'fill': shape.fillColor.toHexColor(), - 'stroke': element.property.color.toHexColor(), + 'fill': shape.fillColor.toHexString(), + 'stroke': element.property.color.toHexString(), 'stroke-width': '${element.property.strokeWidth}px', }, ); @@ -148,7 +149,7 @@ class ShapeRenderer extends Renderer { 'x2': '${element.secondPosition.x}px', 'y2': '${element.secondPosition.y}px', 'stroke-width': '${element.property.strokeWidth}px', - 'stroke': element.property.color.toHexColor(), + 'stroke': element.property.color.toHexString(), 'fill': 'none', }, ); diff --git a/app/lib/renderers/textures/pattern.dart b/app/lib/renderers/textures/pattern.dart index 0d9abad65e43..7a17911ae22c 100644 --- a/app/lib/renderers/textures/pattern.dart +++ b/app/lib/renderers/textures/pattern.dart @@ -6,7 +6,7 @@ void drawPatternTextureOnCanvas(PatternTexture texture, Canvas canvas, canvas.drawRect( Rect.fromLTWH(translation.dx, translation.dy, size.width, size.height), Paint() - ..color = Color(texture.boxColor) + ..color = texture.boxColor.toColor() ..style = PaintingStyle.fill); if (scale <= 0) return; if (texture.boxWidth > 0 && texture.boxXCount > 0) { @@ -25,7 +25,7 @@ void drawPatternTextureOnCanvas(PatternTexture texture, Canvas canvas, Offset(x + translation.dx, size.height + translation.dy), Paint() ..strokeWidth = texture.boxXStroke * scale - ..color = Color(texture.boxXColor)); + ..color = texture.boxXColor.toColor()); count++; if (count >= texture.boxXCount) { count = 0; @@ -49,7 +49,7 @@ void drawPatternTextureOnCanvas(PatternTexture texture, Canvas canvas, Offset(size.width + translation.dx, y + translation.dy), Paint() ..strokeWidth = texture.boxYStroke * scale - ..color = Color(texture.boxYColor)); + ..color = texture.boxYColor.toColor()); count++; if (count >= texture.boxYCount) { count = 0; @@ -71,7 +71,7 @@ void drawPatternTextureOnSvg( 'y': '${offset.dy + translation.dy}px', 'width': '${size.width}px', 'height': '${size.height}px', - 'fill': texture.boxColor.toHexColor(), + 'fill': texture.boxColor.toHexString(), }); if (texture.boxWidth > 0 && texture.boxXCount > 0) { final part = texture.boxWidth * texture.boxXCount + texture.boxXSpace; @@ -85,7 +85,7 @@ void drawPatternTextureOnSvg( 'y1': '${offset.dy + translation.dy}px', 'x2': '${x + offset.dx + translation.dx}px', 'y2': '${offset.dy + size.height + translation.dy}px', - 'stroke': texture.boxXColor.toHexColor(), + 'stroke': texture.boxXColor.toHexString(), 'stroke-width': '${texture.boxXStroke}' }); count++; @@ -108,7 +108,7 @@ void drawPatternTextureOnSvg( 'y1': '${y + offset.dy + translation.dy}px', 'x2': '${offset.dx + size.width + translation.dx}px', 'y2': '${y + offset.dy + translation.dy}px', - 'stroke': texture.boxYColor.toHexColor(), + 'stroke': texture.boxYColor.toHexString(), 'stroke-width': '${texture.boxYStroke}' }); count++; diff --git a/app/lib/renderers/utilities.dart b/app/lib/renderers/utilities.dart index b91d2381ef69..ceafaa3db622 100644 --- a/app/lib/renderers/utilities.dart +++ b/app/lib/renderers/utilities.dart @@ -44,7 +44,7 @@ class UtilitiesRenderer extends Renderer { size.height / transform.size + transform.position.dy), Paint() ..strokeWidth = 1 / transform.size - ..color = Color(option.gridColor), + ..color = option.gridColor.toColor(), ); x += option.gridXSize; } @@ -59,7 +59,7 @@ class UtilitiesRenderer extends Renderer { transform.position.dy + localY), Paint() ..strokeWidth = 1 / transform.size - ..color = Color(option.gridColor), + ..color = option.gridColor.toColor(), ); y += option.gridYSize; } diff --git a/app/lib/selections/elements/shape.dart b/app/lib/selections/elements/shape.dart index 2807013d30ad..39c36dac25b9 100644 --- a/app/lib/selections/elements/shape.dart +++ b/app/lib/selections/elements/shape.dart @@ -9,22 +9,18 @@ class ShapeElementSelection extends ElementSelection { return [ ...super.buildProperties(context), ColorField( - title: Text(AppLocalizations.of(context).color), - value: Color(element.property.color).withAlpha(255), + title: Text(LeapLocalizations.of(context).color), + value: element.property.color.withValues(a: 255), onChanged: (color) => updateElements( context, elements .map((e) => e.copyWith( property: e.property.copyWith( - color: convertOldColor( - // ignore: deprecated_member_use - color.value, - element.property.color)))) + color: color.withValues(a: element.property.color.a)))) .toList()), ), ExactSlider( - // ignore: deprecated_member_use - value: Color(element.property.color).alpha.toDouble(), + value: element.property.color.a.toDouble(), header: Text(AppLocalizations.of(context).alpha), fractionDigits: 0, max: 255, @@ -35,7 +31,7 @@ class ShapeElementSelection extends ElementSelection { elements .map((e) => e.copyWith( property: e.property.copyWith( - color: convertColor(e.property.color, value.toInt())))) + color: e.property.color.withValues(a: value.toInt())))) .toList()), ), ShapeView( diff --git a/app/lib/selections/properties/pen.dart b/app/lib/selections/properties/pen.dart index 1646703d4764..f6d46422092f 100644 --- a/app/lib/selections/properties/pen.dart +++ b/app/lib/selections/properties/pen.dart @@ -14,22 +14,20 @@ class PenPropertySelection extends PropertySelection ...super.build(context, property, onChanged), const SizedBox(height: 4), ColorField( - value: Color(property.color).withAlpha(255), - onChanged: (value) => onChanged(property.copyWith( - // ignore: deprecated_member_use - color: convertOldColor(value.value, property.color))), - title: Text(AppLocalizations.of(context).color), + value: property.color.withValues(a: 255), + onChanged: (value) => onChanged( + property.copyWith(color: value.withValues(a: property.color.a))), + title: Text(LeapLocalizations.of(context).color), ), ExactSlider( - // ignore: deprecated_member_use - value: Color(property.color).alpha.toDouble(), + value: property.color.a.toDouble(), header: Text(AppLocalizations.of(context).alpha), fractionDigits: 0, max: 255, min: 0, defaultValue: 255, onChangeEnd: (value) => onChanged(property.copyWith( - color: convertColor(property.color, value.toInt()))), + color: property.color.withValues(a: value.toInt()))), ), const SizedBox(height: 4), CheckboxListTile( diff --git a/app/lib/selections/tools/label.dart b/app/lib/selections/tools/label.dart index 4ea14391f6a7..6a58cf095c53 100644 --- a/app/lib/selections/tools/label.dart +++ b/app/lib/selections/tools/label.dart @@ -11,22 +11,19 @@ class LabelToolSelection extends ToolSelection { return [ ...super.buildProperties(context), ColorField( - value: Color(selected.first.foreground).withAlpha(255), + value: selected.first.foreground.withValues(a: 255), onChanged: (value) => update( context, selected .map((e) => e.copyWith( - foreground: convertOldColor( - // ignore: deprecated_member_use - value.value, - selected.first.foreground))) + foreground: + value.withValues(a: selected.first.foreground.a))) .toList()), title: Text(AppLocalizations.of(context).foreground), ), ExactSlider( header: Text(AppLocalizations.of(context).alpha), - // ignore: deprecated_member_use - value: Color(selected.first.foreground).alpha.toDouble(), + value: selected.first.foreground.a.toDouble(), defaultValue: 255, min: 0, max: 255, @@ -35,9 +32,7 @@ class LabelToolSelection extends ToolSelection { context, selected .map((e) => e.copyWith( - foreground: - // ignore: deprecated_member_use - Color(e.foreground).withAlpha(value.toInt()).value)) + foreground: e.foreground.withValues(a: value.toInt()))) .toList()), ), ]; diff --git a/app/lib/selections/tools/laser.dart b/app/lib/selections/tools/laser.dart index 86086ee088df..3d1390725bc6 100644 --- a/app/lib/selections/tools/laser.dart +++ b/app/lib/selections/tools/laser.dart @@ -31,13 +31,12 @@ class LaserToolSelection extends ToolSelection { ), const SizedBox(height: 4), ColorField( - value: Color(selected.first.color), + value: selected.first.color, onChanged: (value) => update( context, - // ignore: deprecated_member_use - selected.map((e) => e.copyWith(color: value.value)).toList(), + selected.map((e) => e.copyWith(color: value)).toList(), ), - title: Text(AppLocalizations.of(context).color), + title: Text(LeapLocalizations.of(context).color), ), ExactSlider( value: selected.first.duration, @@ -69,7 +68,7 @@ class LaserToolSelection extends ToolSelection { (e) => DropdownMenuEntry( value: e, label: switch (e) { - LaserAnimation.fade => AppLocalizations.of(context).color, + LaserAnimation.fade => LeapLocalizations.of(context).color, LaserAnimation.path => AppLocalizations.of(context).path, }, leadingIcon: Icon(switch (e) { diff --git a/app/lib/selections/tools/shape.dart b/app/lib/selections/tools/shape.dart index 866e456cb88d..e86fd69b8bfb 100644 --- a/app/lib/selections/tools/shape.dart +++ b/app/lib/selections/tools/shape.dart @@ -83,20 +83,18 @@ class ShapeToolSelection extends ToolSelection { .toList())), const SizedBox(height: 50), ColorField( - value: Color(property.color).withAlpha(255), + value: property.color.withValues(a: 255), onChanged: (color) => update( context, selected .map((e) => e.copyWith( property: e.property.copyWith( - // ignore: deprecated_member_use - color: convertOldColor(color.value, property.color)))) + color: color.withValues(a: property.color.a)))) .toList()), - title: Text(AppLocalizations.of(context).color), + title: Text(LeapLocalizations.of(context).color), ), ExactSlider( - // ignore: deprecated_member_use - value: Color(property.color).alpha.toDouble(), + value: property.color.a.toDouble(), header: Text(AppLocalizations.of(context).alpha), fractionDigits: 0, max: 255, @@ -107,7 +105,7 @@ class ShapeToolSelection extends ToolSelection { selected .map((e) => e.copyWith( property: e.property.copyWith( - color: convertColor(property.color, value.toInt())))) + color: property.color.withValues(a: value.toInt())))) .toList()), ), ShapeView( @@ -237,24 +235,22 @@ class _CircleShapeView extends StatelessWidget { Widget build(BuildContext context) { return Column(children: [ ColorField( - value: Color(shape.fillColor).withAlpha(255), + value: shape.fillColor.withValues(a: 255), title: Text(AppLocalizations.of(context).fill), leading: const PhosphorIcon(PhosphorIconsLight.paintBucket), - defaultColor: Colors.transparent, - onChanged: (color) => onChanged(shape.copyWith( - // ignore: deprecated_member_use - fillColor: convertOldColor(color.value, shape.fillColor))), + defaultColor: SRGBColor.transparent, + onChanged: (color) => onChanged( + shape.copyWith(fillColor: color.withValues(a: shape.fillColor.a))), ), ExactSlider( - // ignore: deprecated_member_use - value: Color(shape.fillColor).alpha.toDouble(), + value: shape.fillColor.a.toDouble(), header: Text(AppLocalizations.of(context).alpha), fractionDigits: 0, max: 255, min: 0, defaultValue: 255, onChangeEnd: (value) => onChanged(shape.copyWith( - fillColor: convertColor(shape.fillColor, value.toInt()))), + fillColor: shape.fillColor.withValues(a: value.toInt()))), ) ]); } @@ -269,24 +265,22 @@ class _TriangleShapeView extends StatelessWidget { Widget build(BuildContext context) { return Column(children: [ ColorField( - value: Color(shape.fillColor).withAlpha(255), + value: shape.fillColor.withValues(a: 255), title: Text(AppLocalizations.of(context).fill), leading: const PhosphorIcon(PhosphorIconsLight.paintBucket), - defaultColor: Colors.transparent, - onChanged: (color) => onChanged(shape.copyWith( - // ignore: deprecated_member_use - fillColor: convertOldColor(color.value, shape.fillColor))), + defaultColor: SRGBColor.transparent, + onChanged: (color) => onChanged( + shape.copyWith(fillColor: color.withValues(a: shape.fillColor.a))), ), ExactSlider( - // ignore: deprecated_member_use - value: Color(shape.fillColor).alpha.toDouble(), + value: shape.fillColor.a.toDouble(), header: Text(AppLocalizations.of(context).alpha), fractionDigits: 0, max: 255, min: 0, defaultValue: 255, onChangeEnd: (value) => onChanged(shape.copyWith( - fillColor: convertColor(shape.fillColor, value.toInt()))), + fillColor: shape.fillColor.withValues(a: value.toInt()))), ) ]); } @@ -310,23 +304,20 @@ class _RectangleShapeViewState extends State<_RectangleShapeView> { ColorField( title: Text(AppLocalizations.of(context).fill), leading: const PhosphorIcon(PhosphorIconsLight.paintBucket), - value: Color(widget.shape.fillColor).withAlpha(255), - defaultColor: Colors.transparent, + value: widget.shape.fillColor.withValues(a: 255), + defaultColor: SRGBColor.transparent, onChanged: (color) => widget.onChanged(widget.shape.copyWith( - fillColor: - // ignore: deprecated_member_use - convertOldColor(color.value, widget.shape.fillColor))), + fillColor: color.withValues(a: widget.shape.fillColor.a))), ), ExactSlider( - // ignore: deprecated_member_use - value: Color(widget.shape.fillColor).alpha.toDouble(), + value: widget.shape.fillColor.a.toDouble(), header: Text(AppLocalizations.of(context).alpha), fractionDigits: 0, max: 255, min: 0, defaultValue: 255, onChangeEnd: (value) => widget.onChanged(widget.shape.copyWith( - fillColor: convertColor(widget.shape.fillColor, value.toInt()))), + fillColor: widget.shape.fillColor.withValues(a: value.toInt()))), ), ExpansionPanelList( expansionCallback: (index, isExpanded) { diff --git a/app/lib/selections/tools/tool.dart b/app/lib/selections/tools/tool.dart index 7e9f3ebe5357..14aa9662b25e 100644 --- a/app/lib/selections/tools/tool.dart +++ b/app/lib/selections/tools/tool.dart @@ -26,7 +26,7 @@ class ToolSelection extends Selection { return [ TextFormField( decoration: InputDecoration( - filled: true, labelText: AppLocalizations.of(context).name), + filled: true, labelText: LeapLocalizations.of(context).name), initialValue: initialName, onChanged: (value) => update(context, selected.map((e) => e.copyWith(name: value) as T).toList())), diff --git a/app/lib/selections/utilities.dart b/app/lib/selections/utilities.dart index 68d3bc4b86d6..d1174dd4cebd 100644 --- a/app/lib/selections/utilities.dart +++ b/app/lib/selections/utilities.dart @@ -114,7 +114,7 @@ class _UtilitiesViewState extends State<_UtilitiesView> TextFormField( controller: _nameController, decoration: InputDecoration( - labelText: AppLocalizations.of(context).name, + labelText: LeapLocalizations.of(context).name, filled: true, ), onChanged: (value) { @@ -122,7 +122,7 @@ class _UtilitiesViewState extends State<_UtilitiesView> state.save(); }, ), - const SizedBox(height: 20), + const SizedBox(height: 8), TextFormField( minLines: 3, maxLines: 5, @@ -182,6 +182,158 @@ class _UtilitiesViewState extends State<_UtilitiesView> child: Text(AppLocalizations.of(context).captureThumbnail), ), + MenuItemButton( + leadingIcon: Tooltip( + message: state.data.isEncrypted + ? AppLocalizations.of(context).encrypted + : AppLocalizations.of(context).unencrypted, + child: Icon( + state.data.isEncrypted + ? PhosphorIconsLight.lock + : PhosphorIconsLight.lockOpen, + ), + ), + child: Text( + state.data.isEncrypted + ? AppLocalizations.of(context).unencrypt + : AppLocalizations.of(context).encrypt, + ), + onPressed: () async { + if (state.data.isEncrypted) { + final result = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: + Text(AppLocalizations.of(context).unencrypt), + content: Text(AppLocalizations.of(context) + .unencryptWarning), + actions: [ + TextButton( + onPressed: () => + Navigator.pop(context, false), + child: Text(MaterialLocalizations.of(context) + .cancelButtonLabel), + ), + TextButton( + onPressed: () => Navigator.pop(context, true), + child: Text(MaterialLocalizations.of(context) + .okButtonLabel), + ), + ], + ), + ); + if (result != true) return; + context + .read() + .add(EncryptionChanged(null)); + } else { + String password = ''; + bool showPassword = false, + showConfirmPassword = false; + final formKey = GlobalKey(); + final result = await showDialog( + context: context, + builder: (context) => StatefulBuilder( + builder: (context, setState) => Form( + key: formKey, + child: AlertDialog( + scrollable: true, + title: Text( + AppLocalizations.of(context).encrypt), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row(children: [ + Icon(PhosphorIconsLight.warning), + const SizedBox(width: 8), + Flexible( + child: Text( + AppLocalizations.of(context) + .encryptWarning), + ), + ]), + const SizedBox(height: 16), + TextFormField( + decoration: InputDecoration( + labelText: + AppLocalizations.of(context) + .password, + filled: true, + suffixIcon: IconButton( + icon: Icon(showPassword + ? PhosphorIconsLight.eye + : PhosphorIconsLight.eyeSlash), + onPressed: () => setState( + () => + showPassword = !showPassword, + ), + ), + ), + obscureText: !showPassword, + autofocus: true, + onChanged: (value) => password = value, + validator: (value) => + value?.isEmpty ?? true + ? LeapLocalizations.of(context) + .shouldNotEmpty + : null, + ), + const SizedBox(height: 8), + TextFormField( + decoration: InputDecoration( + labelText: + AppLocalizations.of(context) + .confirmPassword, + filled: true, + suffixIcon: IconButton( + icon: Icon(showConfirmPassword + ? PhosphorIconsLight.eye + : PhosphorIconsLight.eyeSlash), + onPressed: () => setState( + () => showConfirmPassword = + !showConfirmPassword, + ), + ), + ), + obscureText: !showConfirmPassword, + validator: (value) => value != password + ? AppLocalizations.of(context) + .passwordMismatch + : null, + ), + ], + ), + actions: [ + TextButton( + onPressed: () => + Navigator.pop(context, false), + child: Text( + MaterialLocalizations.of(context) + .cancelButtonLabel), + ), + TextButton( + onPressed: () { + if (formKey.currentState?.validate() ?? + false) { + Navigator.pop(context, true); + } + }, + child: Text( + MaterialLocalizations.of(context) + .okButtonLabel), + ), + ], + ), + ), + ), + ); + if (result != true) return; + context + .read() + .add(EncryptionChanged(password)); + } + }, + ) ], ), Column(children: [ @@ -229,34 +381,26 @@ class _UtilitiesViewState extends State<_UtilitiesView> ), const SizedBox(height: 8), ColorField( - title: Text(AppLocalizations.of(context).color), - value: - Color(widget.option.gridColor).withAlpha(255), + title: Text(LeapLocalizations.of(context).color), + value: widget.option.gridColor.withValues(a: 255), onChanged: (value) => widget.onToolChanged( widget.option.copyWith( - gridColor: convertOldColor( - // ignore: deprecated_member_use - value.value, - widget.option.gridColor)), + gridColor: value.withValues( + a: widget.option.gridColor.a)), ), ), const SizedBox(height: 8), ExactSlider( header: Text(AppLocalizations.of(context).alpha), - value: Color(widget.option.gridColor) - // ignore: deprecated_member_use - .alpha - .toDouble(), + value: widget.option.gridColor.a.toDouble(), defaultValue: 255, min: 0, max: 255, fractionDigits: 0, onChangeEnd: (value) => widget.onToolChanged( widget.option.copyWith( - gridColor: Color(widget.option.gridColor) - .withAlpha(value.toInt()) - // ignore: deprecated_member_use - .value, + gridColor: widget.option.gridColor + .withValues(a: value.toInt()), ), ), ), diff --git a/app/lib/services/import.dart b/app/lib/services/import.dart index e800a3d79762..2eb954b26c8e 100644 --- a/app/lib/services/import.dart +++ b/app/lib/services/import.dart @@ -88,6 +88,8 @@ class ImportService { bytes = Uint8List.fromList(List.from(data)); } else if (data is NoteData) { return data; + } else if (data is NoteFile) { + bytes = data.data; } if (type.isEmpty) type = 'note'; final fileType = AssetFileType.values.firstWhereOrNull((element) => @@ -221,7 +223,27 @@ class ImportService { try { final documentOpened = document != null; final realDocument = document ?? DocumentDefaults.createDocument(); - final data = NoteData.fromData(bytes); + final file = NoteFile(bytes); + String? password; + if (file.isEncrypted()) { + password = await showDialog( + context: context, + builder: (context) => NameDialog( + title: AppLocalizations.of(context).password, + button: AppLocalizations.of(context).open, + obscureText: true, + ), + ); + if (password == null) return null; + } + final data = file.load(password: password); + if (data == null) { + return showDialog( + context: context, + builder: (context) => UnknownImportConfirmationDialog( + message: AppLocalizations.of(context).unknownImportType), + ).then((value) => null); + } if (!data.isValid) { await importArchive(bytes); return null; @@ -481,11 +503,10 @@ class ImportService { final contentString = String.fromCharCodes(bytes); final styleSheet = document.findStyle(); final state = _getState(); - final background = state?.page.backgrounds.firstOrNull?.defaultColor ?? - BasicColors.white; - final foreground = isDarkColor(Color(background)) - ? BasicColors.white - : BasicColors.black; + final background = + state?.page.backgrounds.firstOrNull?.defaultColor ?? SRGBColor.white; + final foreground = + background.toColor().isDark() ? SRGBColor.white : SRGBColor.black; return _submit(context, document, elements: [ MarkdownElement( @@ -758,7 +779,7 @@ class ImportService { if (data.isValid) { final document = await importBfly(bytes); if (document != null) { - fileSystem.createFile(document.name ?? '', document); + fileSystem.createFile(document.name ?? '', document.toFile()); } return document != null; } @@ -767,7 +788,7 @@ class ImportService { if (!file.name.endsWith(fileExtension)) continue; final document = await importBfly(file.content, advanced: false); if (document != null) { - fileSystem.createFile(file.name, document); + fileSystem.createFile(file.name, document.toFile()); } } return true; diff --git a/app/lib/settings/connection.dart b/app/lib/settings/connection.dart index 1042013063c8..013bf9b6014d 100644 --- a/app/lib/settings/connection.dart +++ b/app/lib/settings/connection.dart @@ -97,11 +97,12 @@ class _ConnectionSettingsPageState extends State ), actions: [ TextButton( - child: Text(AppLocalizations.of(context).cancel), + child: + Text(MaterialLocalizations.of(context).cancelButtonLabel), onPressed: () => Navigator.of(context).pop(false), ), ElevatedButton( - child: Text(AppLocalizations.of(context).create), + child: Text(LeapLocalizations.of(context).create), onPressed: () => Navigator.of(context).pop(true), ), ], diff --git a/app/lib/settings/connections.dart b/app/lib/settings/connections.dart index 6caac21e6e87..986a60b47705 100644 --- a/app/lib/settings/connections.dart +++ b/app/lib/settings/connections.dart @@ -219,7 +219,7 @@ class __AddRemoteDialogState extends State<_AddRemoteDialog> { ), ElevatedButton( onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ], ), @@ -354,7 +354,7 @@ class __AddRemoteDialogState extends State<_AddRemoteDialog> { actions: [ TextButton( onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context).ok), + child: Text(MaterialLocalizations.of(context).okButtonLabel), ), ], )); @@ -443,7 +443,7 @@ class __AddRemoteDialogState extends State<_AddRemoteDialog> { TextField( controller: _nameController, decoration: InputDecoration( - labelText: AppLocalizations.of(context).name, + labelText: LeapLocalizations.of(context).name, filled: true, icon: const PhosphorIcon(PhosphorIconsLight.textAa), ), @@ -597,7 +597,8 @@ class __AddRemoteDialogState extends State<_AddRemoteDialog> { } Navigator.of(context).pop(); }, - child: Text(AppLocalizations.of(context).cancel), + child: + Text(MaterialLocalizations.of(context).cancelButtonLabel), ), if (_isConnected) ...[ ListenableBuilder( @@ -618,7 +619,7 @@ class __AddRemoteDialogState extends State<_AddRemoteDialog> { _packsDirectoryController.text.isEmpty ? null : _create, - child: Text(AppLocalizations.of(context).create), + child: Text(LeapLocalizations.of(context).create), )), ] else ...[ ElevatedButton( diff --git a/app/lib/settings/personalization.dart b/app/lib/settings/personalization.dart index 34549adead2a..5f0a532b6dc8 100644 --- a/app/lib/settings/personalization.dart +++ b/app/lib/settings/personalization.dart @@ -34,7 +34,7 @@ class PersonalizationSettingsPage extends StatelessWidget { String _getDensityName(BuildContext context, ThemeDensity density) => switch (density) { ThemeDensity.system => AppLocalizations.of(context).systemTheme, - ThemeDensity.maximize => AppLocalizations.of(context).maximize, + ThemeDensity.maximize => LeapLocalizations.of(context).maximize, ThemeDensity.desktop => AppLocalizations.of(context).desktop, ThemeDensity.compact => AppLocalizations.of(context).compact, ThemeDensity.standard => AppLocalizations.of(context).standard, diff --git a/app/lib/views/app_bar.dart b/app/lib/views/app_bar.dart index c6bb92084721..61fc403421bf 100644 --- a/app/lib/views/app_bar.dart +++ b/app/lib/views/app_bar.dart @@ -540,7 +540,7 @@ class _MainPopupMenu extends StatelessWidget { onPressed: () async { windowCubit.toggleFullScreen(); }, - child: Text(AppLocalizations.of(context).fullScreen), + child: Text(LeapLocalizations.of(context).fullScreen), )), ], if (state.embedding != null) ...[ diff --git a/app/lib/views/edit.dart b/app/lib/views/edit.dart index 97b8a55c4f23..1e1b4974adae 100644 --- a/app/lib/views/edit.dart +++ b/app/lib/views/edit.dart @@ -391,7 +391,7 @@ class _EditToolbarState extends State { tools.every((e) => e is! FullScreenTool)) IconButton( icon: const PhosphorIcon(PhosphorIconsLight.arrowsIn), - tooltip: AppLocalizations.of(context).exitFullScreen, + tooltip: LeapLocalizations.of(context).exitFullScreen, onPressed: () { context.read().changeFullScreen(false); }, diff --git a/app/lib/views/files/entity.dart b/app/lib/views/files/entity.dart index de4845ad6a3a..f38866d1e8cf 100644 --- a/app/lib/views/files/entity.dart +++ b/app/lib/views/files/entity.dart @@ -21,7 +21,7 @@ import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:popover/popover.dart'; class FileEntityItem extends StatefulWidget { - final FileSystemEntity entity; + final FileSystemEntity entity; final bool active, collapsed, gridView; final bool? selected; final VoidCallback onTap, onReload; @@ -125,11 +125,15 @@ class _FileEntityItemState extends State { PhosphorIconData icon = PhosphorIconsLight.folder; final entity = widget.entity; try { - if (entity is FileSystemFile) { + if (entity is FileSystemFile) { + final data = entity.data?.load(); icon = entity.location.fileType.icon(PhosphorIconsStyle.light); - thumbnail = entity.data?.getThumbnail(); + if (entity.data?.isEncrypted() ?? false) { + icon = PhosphorIconsLight.lock; + } + thumbnail = data?.getThumbnail(); if (thumbnail?.isEmpty ?? false) thumbnail = null; - metadata = entity.data?.getMetadata(); + metadata = data?.getMetadata(); final locale = Localizations.localeOf(context).languageCode; final dateFormatter = DateFormat.yMd(locale); final timeFormatter = DateFormat.Hm(locale); @@ -238,7 +242,7 @@ class _FileEntityItemState extends State { class ContextFileRegion extends StatelessWidget { final ExternalStorage? remote; final DocumentFileSystem documentSystem; - final FileSystemEntity entity; + final FileSystemEntity entity; final SettingsCubit settingsCubit; final bool editable; final ValueChanged onEdit; diff --git a/app/lib/views/files/grid.dart b/app/lib/views/files/grid.dart index 05540618dbfe..ff76ef0a457e 100644 --- a/app/lib/views/files/grid.dart +++ b/app/lib/views/files/grid.dart @@ -17,7 +17,7 @@ class FileEntityGridItem extends StatelessWidget { final VoidCallback onTap, onDelete, onReload; final ValueChanged onEdit, onSelectedChanged; final Uint8List? thumbnail; - final FileSystemEntity entity; + final FileSystemEntity entity; final TextEditingController nameController; const FileEntityGridItem({ diff --git a/app/lib/views/files/list.dart b/app/lib/views/files/list.dart index b3fe58ab54ed..5cf252229a7e 100644 --- a/app/lib/views/files/list.dart +++ b/app/lib/views/files/list.dart @@ -23,7 +23,7 @@ class FileEntityListTile extends StatelessWidget { final VoidCallback onTap, onDelete, onReload; final ValueChanged onEdit, onSelectedChanged; final Uint8List? thumbnail; - final FileSystemEntity entity; + final FileSystemEntity entity; final TextEditingController nameController; final Widget actionButton; diff --git a/app/lib/views/files/view.dart b/app/lib/views/files/view.dart index 8011a505e6b0..006d0e00e536 100644 --- a/app/lib/views/files/view.dart +++ b/app/lib/views/files/view.dart @@ -18,7 +18,6 @@ import 'package:phosphor_flutter/phosphor_flutter.dart'; import '../../api/open.dart'; import '../../cubits/settings.dart'; import '../../dialogs/file_system/sync.dart'; -import '../../dialogs/name.dart'; import '../../services/import.dart'; class FilesView extends StatefulWidget { @@ -52,7 +51,7 @@ class FilesViewState extends State { ExternalStorage? _remote; String _search = ''; late final SettingsCubit _settingsCubit; - Stream?>? _filesStream; + Stream?>? _filesStream; final Set _selectedFiles = {}; @override @@ -82,7 +81,7 @@ class FilesViewState extends State { } String getLocalizedNameOfSortBy(SortBy sortBy) => switch (sortBy) { - SortBy.name => AppLocalizations.of(context).name, + SortBy.name => LeapLocalizations.of(context).name, SortBy.created => AppLocalizations.of(context).created, SortBy.modified => AppLocalizations.of(context).modified, }; @@ -119,9 +118,11 @@ class FilesViewState extends State { directory: path, name: name, suffix: '.bfly', - template.createDocument( - name: name, - )); + template + .createDocument( + name: name, + ) + .toFile()); reloadFileSystem(); } @@ -450,7 +451,7 @@ class FilesViewState extends State { FloatingActionButton.small( heroTag: null, onPressed: controller.toggle, - tooltip: AppLocalizations.of(context).create, + tooltip: LeapLocalizations.of(context).create, child: const PhosphorIcon(PhosphorIconsLight.plus), ), ), @@ -523,7 +524,7 @@ class FilesViewState extends State { .getAsset(_locationController.text, readData: false); if (directory - is! FileSystemDirectory) { + is! FileSystemDirectory) { return; } setState(() { @@ -608,7 +609,7 @@ class FilesViewState extends State { BlocBuilder( buildWhen: (previous, current) => previous.starred != current.starred, builder: (context, settings) => - StreamBuilder?>( + StreamBuilder?>( stream: _filesStream, builder: (context, snapshot) { if (snapshot.hasError) { @@ -622,7 +623,7 @@ class FilesViewState extends State { child: Text(AppLocalizations.of(context).noElements)); } final entity = snapshot.data; - if (entity is! FileSystemDirectory) { + if (entity is! FileSystemDirectory) { return Container(); } final assets = entity.assets.where((e) { @@ -695,8 +696,8 @@ class FilesViewState extends State { ); } - Future _onFileTap(FileSystemEntity entity) async { - if (entity is! FileSystemFile) { + Future _onFileTap(FileSystemEntity entity) async { + if (entity is! FileSystemFile) { setState(() { _locationController.text = entity.pathWithoutLeadingSlash; _setFilesStream(); @@ -704,14 +705,14 @@ class FilesViewState extends State { return; } final location = entity.location; - final data = entity.data; + final data = entity.data?.data; await openFile(context, widget.collapsed, location, data); if (!widget.collapsed) { reloadFileSystem(); } } - int _sortAssets(FileSystemEntity a, FileSystemEntity b) { + int _sortAssets(FileSystemEntity a, FileSystemEntity b) { try { final settings = _settingsCubit.state; // Test if starred @@ -723,20 +724,20 @@ class FilesViewState extends State { if (bStarred && !aStarred) { return 1; } - if (a is FileSystemDirectory) { + if (a is FileSystemDirectory) { return -1; } - if (b is FileSystemDirectory) { + if (b is FileSystemDirectory) { return 1; } - final aFile = a as FileSystemFile; - final bFile = b as FileSystemFile; + final aFile = a as FileSystemFile; + final bFile = b as FileSystemFile; FileMetadata? aInfo, bInfo; try { - aInfo = aFile.data?.getMetadata(); + aInfo = aFile.data?.load()?.getMetadata(); } catch (_) {} try { - bInfo = bFile.data?.getMetadata(); + bInfo = bFile.data?.load()?.getMetadata(); } catch (_) {} if (aInfo == null) { if (bInfo == null) { @@ -791,7 +792,7 @@ class _RecentFilesView extends StatefulWidget { } class _RecentFilesViewState extends State<_RecentFilesView> { - late Stream>> _stream; + late Stream>> _stream; late final ButterflyFileSystem _fileSystem; final ScrollController _recentScrollController = ScrollController(); diff --git a/app/lib/views/home.dart b/app/lib/views/home.dart index f2877f07dbd9..c774e43aa14d 100644 --- a/app/lib/views/home.dart +++ b/app/lib/views/home.dart @@ -539,7 +539,7 @@ class _QuickstartHomeViewState extends State<_QuickstartHomeView> { widget.onReload(); }, child: Text( - AppLocalizations.of(context).reset, + LeapLocalizations.of(context).reset, style: Theme.of(context).textTheme.bodyLarge, ), ), diff --git a/app/lib/views/main.dart b/app/lib/views/main.dart index b13fb9b7ca43..ba7fdd802e17 100644 --- a/app/lib/views/main.dart +++ b/app/lib/views/main.dart @@ -25,6 +25,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.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'; @@ -188,6 +189,10 @@ class _ProjectPageState extends State { document ??= await globalImportService.load( type: widget.type.isEmpty ? (fileType ?? widget.type) : widget.type, data: data); + if (document == null) { + GoRouter.of(context).pop(); + return; + } } final name = absolute ? location!.fileName : ''; NoteData? defaultDocument; @@ -209,8 +214,17 @@ class _ProjectPageState extends State { if (!absolute) { final asset = await documentSystem.getAsset(location.path); if (!mounted) return; - if (location.fileType == AssetFileType.note) { - document = await checkFileChanges(context, asset); + if (asset is FileSystemFile && + location.fileType == AssetFileType.note) { + final noteData = await globalImportService.load( + document: defaultDocument, + type: widget.type.isEmpty + ? (fileType ?? widget.type) + : widget.type, + data: asset.data); + if (noteData != null) { + document = await checkFileChanges(context, noteData); + } } } else { final data = await documentSystem.loadAbsolute(location.path); diff --git a/app/lib/views/navigator/areas.dart b/app/lib/views/navigator/areas.dart index 806270bd5ce4..15a6c908e7ee 100644 --- a/app/lib/views/navigator/areas.dart +++ b/app/lib/views/navigator/areas.dart @@ -250,7 +250,7 @@ class _AreasViewState extends State { !currentIndex.areaNavigatorCreate), icon: const PhosphorIcon( PhosphorIconsLight.plusCircle), - tooltip: AppLocalizations.of(context).create, + tooltip: LeapLocalizations.of(context).create, ), IconButton( isSelected: currentIndex.areaNavigatorExact, diff --git a/app/lib/views/navigator/layers.dart b/app/lib/views/navigator/layers.dart index 5270e29f4888..e9d5979eba5e 100644 --- a/app/lib/views/navigator/layers.dart +++ b/app/lib/views/navigator/layers.dart @@ -3,6 +3,7 @@ import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import '../../dialogs/delete.dart'; @@ -152,7 +153,7 @@ class LayersView extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(8.0), child: FloatingActionButton.extended( - label: Text(AppLocalizations.of(context).create), + label: Text(LeapLocalizations.of(context).create), icon: const PhosphorIcon(PhosphorIconsLight.plus), backgroundColor: Theme.of(context).colorScheme.secondary, foregroundColor: Theme.of(context).colorScheme.onSecondary, @@ -236,7 +237,7 @@ class _LayerMergeDialogState extends State<_LayerMergeDialog> { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).cancel), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel), ), ElevatedButton( onPressed: () { diff --git a/app/lib/views/navigator/pages.dart b/app/lib/views/navigator/pages.dart index d65c353599ab..351dda4d38af 100644 --- a/app/lib/views/navigator/pages.dart +++ b/app/lib/views/navigator/pages.dart @@ -3,6 +3,7 @@ import 'package:butterfly_api/butterfly_api.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_leap/l10n/leap_localizations.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import '../../dialogs/delete.dart'; @@ -139,7 +140,7 @@ class _PagesViewState extends State { children: [ const PhosphorIcon(PhosphorIconsLight.plus), const SizedBox(width: 8), - Text(AppLocalizations.of(context).create), + Text(LeapLocalizations.of(context).create), ], ), Row( diff --git a/app/lib/views/navigator/view.dart b/app/lib/views/navigator/view.dart index 20925bb43d8e..d3c3666d4295 100644 --- a/app/lib/views/navigator/view.dart +++ b/app/lib/views/navigator/view.dart @@ -217,7 +217,8 @@ class _DocumentNavigatorState extends State ? IconButton.outlined( icon: const PhosphorIcon(PhosphorIconsLight.x), onPressed: () => Navigator.of(context).pop(), - tooltip: AppLocalizations.of(context).close, + tooltip: MaterialLocalizations.of(context) + .closeButtonLabel, ) : null, title: Text(page.getLocalizedName(context)), diff --git a/app/lib/views/navigator/waypoints.dart b/app/lib/views/navigator/waypoints.dart index 5dc1ae4f87be..bec23a30be94 100644 --- a/app/lib/views/navigator/waypoints.dart +++ b/app/lib/views/navigator/waypoints.dart @@ -129,13 +129,13 @@ class _WaypointCreateDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(AppLocalizations.of(context).create), + title: Text(LeapLocalizations.of(context).create), content: Column(mainAxisSize: MainAxisSize.min, children: [ TextField( controller: _nameController, autofocus: true, decoration: InputDecoration( - filled: true, labelText: AppLocalizations.of(context).name), + filled: true, labelText: LeapLocalizations.of(context).name), ), const SizedBox(height: 10), CheckboxListTile( @@ -148,7 +148,7 @@ class _WaypointCreateDialogState extends State { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context).cancel)), + child: Text(MaterialLocalizations.of(context).cancelButtonLabel)), ElevatedButton( onPressed: () { final bloc = context.read(); @@ -163,7 +163,7 @@ class _WaypointCreateDialogState extends State { _saveScale ? transform.size : null))); Navigator.of(context).pop(); }, - child: Text(AppLocalizations.of(context).create)), + child: Text(LeapLocalizations.of(context).create)), ], ); } diff --git a/app/lib/views/property.dart b/app/lib/views/property.dart index 3a14e384a43f..c42f2e16d8a9 100644 --- a/app/lib/views/property.dart +++ b/app/lib/views/property.dart @@ -217,7 +217,8 @@ class _PropertyViewState extends State ), const SizedBox(width: 8), IconButton.outlined( - tooltip: AppLocalizations.of(context).close, + tooltip: MaterialLocalizations.of(context) + .closeButtonLabel, icon: const PhosphorIcon( PhosphorIconsLight.x), onPressed: _closeView, diff --git a/app/lib/views/toolbar/color.dart b/app/lib/views/toolbar/color.dart index 0999f31d71b4..f4daa00afd9e 100644 --- a/app/lib/views/toolbar/color.dart +++ b/app/lib/views/toolbar/color.dart @@ -14,8 +14,8 @@ import '../../bloc/document_bloc.dart'; enum ColorPickerToolbarAction { delete, pin, eyeDropper } class ColorToolbarView extends StatefulWidget implements PreferredSizeWidget { - final int color; - final ValueChanged onChanged; + final SRGBColor color; + final ValueChanged onChanged; final void Function(BuildContext)? onEyeDropper; const ColorToolbarView({ @@ -69,8 +69,7 @@ class _ColorToolbarViewState extends State { final document = state.data; ColorPalette? palette; NoteData? pack; - // ignore: deprecated_member_use - int color = Color(widget.color).withAlpha(255).value; + SRGBColor color = widget.color.withValues(a: 255); void addColor() async { final settingsCubit = context.read(); @@ -78,9 +77,8 @@ class _ColorToolbarViewState extends State { await showDialog>( context: context, builder: (context) => ColorPicker( - value: Color(widget.color), - suggested: - settingsCubit.state.recentColors.map((e) => Color(e)).toList(), + value: widget.color, + suggested: settingsCubit.state.recentColors, secondaryActions: widget.onEyeDropper == null ? null : (close) => [ @@ -101,18 +99,19 @@ class _ColorToolbarViewState extends State { ), ); if (response == null) return; - widget.onChanged(response.color); + final srgb = response.toSRGB(); + widget.onChanged(srgb); if (response.action == ColorPickerToolbarAction.eyeDropper) { widget.onEyeDropper?.call(context); return; } if (response.action != ColorPickerToolbarAction.pin) { - settingsCubit.addRecentColors(response.color); + settingsCubit.addRecentColors(srgb); return; } var currentPalette = pack?.getPalette(colorPalette!.name); currentPalette = currentPalette?.copyWith( - colors: [...currentPalette.colors, response.color], + colors: [...currentPalette.colors, srgb], ); bloc.add( PackUpdated(colorPalette!.pack, pack!.setPalette(currentPalette!))); @@ -131,8 +130,8 @@ class _ColorToolbarViewState extends State { controller: _scrollController, children: [ if (!(palette?.colors.contains(color) ?? false)) ...[ - ColorButton( - color: Color(widget.color), + ColorButton.srgb( + color: widget.color, selected: true, onTap: addColor, ), @@ -148,10 +147,8 @@ class _ColorToolbarViewState extends State { ColorPickerResponse>( context: context, builder: (context) => ColorPicker( - value: Color(value), - suggested: settingsCubit.state.recentColors - .map((e) => Color(e)) - .toList(), + value: value, + suggested: settingsCubit.state.recentColors, secondaryActions: (close) => [ OutlinedButton( onPressed: () => @@ -164,22 +161,23 @@ class _ColorToolbarViewState extends State { if (response == null) return; if (response.action == ColorPickerToolbarAction.delete) { palette = palette?.copyWith( - colors: List.from(palette.colors)..removeAt(index), + colors: List.from(palette.colors) + ..removeAt(index), ); } else { palette = palette?.copyWith( - colors: List.from(palette.colors) - ..[index] = response.color, + colors: List.from(palette.colors) + ..[index] = response.toSRGB(), ); } bloc.add(PackUpdated( colorPalette!.pack, pack!.setPalette(palette!))); - widget.onChanged(response.color); + widget.onChanged(response.toSRGB()); setState(() {}); } - return ColorButton( - color: Color(value), + return ColorButton.srgb( + color: value, selected: value == color, onTap: () => widget.onChanged(value), onSecondaryTap: changeColor, diff --git a/app/lib/views/toolbar/label.dart b/app/lib/views/toolbar/label.dart index 10b79487d78e..3f8512fe04cd 100644 --- a/app/lib/views/toolbar/label.dart +++ b/app/lib/views/toolbar/label.dart @@ -559,7 +559,7 @@ class _LabelToolbarViewState extends State { width: 42, height: 42, decoration: BoxDecoration( - color: Color(span!.getColor(paragraph)), + color: span!.getColor(paragraph).toColor(), border: Border.all( color: Theme.of(context).primaryColor, width: 2, @@ -570,22 +570,17 @@ class _LabelToolbarViewState extends State { ), ), onTap: () async { - final result = await showDialog( + final result = await showDialog( context: context, builder: (_) => ColorPalettePickerDialog( - value: Color(span.getColor(paragraph)), + value: span.getColor(paragraph), bloc: context.read(), ), ); if (result == null) return; updateSpan((value) => value.copyWith( - color: Color(result) - .withValues( - alpha: Color(widget - .value.tool.foreground) - .a) - // ignore: deprecated_member_use - .value)); + color: result.withValues( + a: widget.value.tool.foreground.a))); }, ), const SizedBox(width: 16), diff --git a/app/lib/views/toolbar/presentation/toolbar.dart b/app/lib/views/toolbar/presentation/toolbar.dart index ce687b8153b1..dddb4a0ba0db 100644 --- a/app/lib/views/toolbar/presentation/toolbar.dart +++ b/app/lib/views/toolbar/presentation/toolbar.dart @@ -1,7 +1,6 @@ import 'dart:math'; import 'package:butterfly/cubits/transform.dart'; -import 'package:butterfly/dialogs/name.dart'; import 'package:butterfly/dialogs/presentation.dart'; import 'package:butterfly/views/toolbar/view.dart'; import 'package:butterfly_api/butterfly_api.dart'; @@ -209,7 +208,7 @@ class _PresentationToolbarViewState extends State { _updateControllers(); }); }, - child: Text(AppLocalizations.of(context).create), + child: Text(LeapLocalizations.of(context).create), ), MenuItemButton( leadingIcon: diff --git a/app/lib/visualizer/text.dart b/app/lib/visualizer/text.dart index 84896dce91ec..637f1cbc1b92 100644 --- a/app/lib/visualizer/text.dart +++ b/app/lib/visualizer/text.dart @@ -26,15 +26,15 @@ extension TextDecorationStyleFlutterConverter on text.TextDecorationStyle { extension DefinedSpanPropertyFlutterConverter on text.DefinedSpanProperty { TextStyle toFlutter( - [text.DefinedParagraphProperty? parent, int? foreground]) { + [text.DefinedParagraphProperty? parent, SRGBColor? foreground]) { return TextStyle( fontSize: getSize(parent), - color: Color(getColor(parent, foreground)), + color: getColor(parent, foreground).toColor(), fontFamily: 'Roboto', fontStyle: getItalic(parent) ? FontStyle.italic : FontStyle.normal, fontWeight: FontWeight.values[getFontWeight(parent)], letterSpacing: getLetterSpacing(parent), - decorationColor: Color(getDecorationColor(parent)), + decorationColor: getDecorationColor(parent).toColor(), decorationStyle: getDecorationStyle(parent).toFlutter(), decorationThickness: getDecorationThickness(parent), decoration: TextDecoration.combine([ @@ -42,7 +42,7 @@ extension DefinedSpanPropertyFlutterConverter on text.DefinedSpanProperty { if (getLineThrough(parent)) TextDecoration.lineThrough, if (getOverline(parent)) TextDecoration.overline, ]), - backgroundColor: Color(getBackgroundColor(parent)), + backgroundColor: getBackgroundColor(parent).toColor(), ); } @@ -50,13 +50,13 @@ extension DefinedSpanPropertyFlutterConverter on text.DefinedSpanProperty { font-weight: ${getFontWeight(parent)}; font-style: ${getItalic(parent) ? 'italic' : 'normal'}; font-size: ${getSize(parent)}px; - color: #${getColor(parent).toRadixString(16).padLeft(8, '0')}; + color: ${getColor(parent).toHexString()}; letter-spacing: ${getLetterSpacing(parent)}px; - text-decoration-color: #${getDecorationColor(parent).toRadixString(16).padLeft(8, '0')}; + text-decoration-color: ${getDecorationColor(parent).toHexString()}; text-decoration-style: ${getDecorationStyle(parent).toCss()}; text-decoration-thickness: ${getDecorationThickness(parent)}px; text-decoration-line: ${getUnderline(parent) ? 'underline' : 'none'} ${getLineThrough(parent) ? 'line-through' : 'none'} ${getOverline(parent) ? 'overline' : 'none'}; - background-color: #${getBackgroundColor(parent).toHexColor()}; + background-color: ${getBackgroundColor(parent).toHexString()}; """; } diff --git a/app/lib/visualizer/tool.dart b/app/lib/visualizer/tool.dart index a8d884d61361..2b95d0604e72 100644 --- a/app/lib/visualizer/tool.dart +++ b/app/lib/visualizer/tool.dart @@ -40,7 +40,7 @@ extension ToolVisualizer on Tool { StampTool() => loc.stamp, TextureTool() => loc.texture, PresentationTool() => loc.presentation, - FullScreenTool() => loc.fullScreen, + FullScreenTool() => LeapLocalizations.of(context).fullScreen, AssetTool e => e.importType.getLocalizedName(context), EyeDropperTool() => loc.eyeDropper, ExportTool() => loc.export, diff --git a/app/lib/widgets/color_field.dart b/app/lib/widgets/color_field.dart index a93ac5aa91b7..db581f931f75 100644 --- a/app/lib/widgets/color_field.dart +++ b/app/lib/widgets/color_field.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; 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'; @@ -9,17 +8,17 @@ import '../dialogs/packs/color_pick.dart'; class ColorField extends StatelessWidget { final bool enabled, custom; - final Color value; - final Color? defaultColor; + final SRGBColor value; + final SRGBColor? defaultColor; final Widget? title; final Widget? subtitle; final Widget? leading; - final ValueChanged? onChanged; + final ValueChanged? onChanged; final VoidCallback? onOpen; const ColorField( {super.key, - this.value = Colors.white, + this.value = SRGBColor.white, this.defaultColor, this.custom = false, this.enabled = true, @@ -34,7 +33,7 @@ class ColorField extends StatelessWidget { return ListTile( onTap: () async { onOpen?.call(); - int? nextColor; + SRGBColor? nextColor; if (custom) { final response = await showDialog( context: context, @@ -42,9 +41,9 @@ class ColorField extends StatelessWidget { value: value, ), ); - nextColor = response?.color; + nextColor = response?.toSRGB(); } else { - nextColor = await showDialog( + nextColor = await showDialog( context: context, builder: (ctx) => ColorPalettePickerDialog( value: value, @@ -53,7 +52,7 @@ class ColorField extends StatelessWidget { ); } if (nextColor != null) { - onChanged?.call(Color(nextColor)); + onChanged?.call(nextColor); } }, leading: leading, @@ -66,7 +65,7 @@ class ColorField extends StatelessWidget { width: 30, height: 30, decoration: BoxDecoration( - color: value, + color: value.toColor(), border: Border.all(color: Theme.of(context).primaryColor, width: 2), borderRadius: const BorderRadius.all(Radius.circular(32))), @@ -76,7 +75,7 @@ class ColorField extends StatelessWidget { IconButton( icon: const PhosphorIcon(PhosphorIconsLight.clockCounterClockwise), - tooltip: AppLocalizations.of(context).reset, + tooltip: LeapLocalizations.of(context).reset, onPressed: () async { onChanged?.call(defaultColor!); }, diff --git a/app/pubspec.lock b/app/pubspec.lock index 1f6060cc675c..c366716fddfb 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -297,8 +297,8 @@ packages: dependency: transitive description: path: "packages/dart_leap" - ref: dfda6c2e3cef2e29511f97e9470fd4deb8e0c573 - resolved-ref: dfda6c2e3cef2e29511f97e9470fd4deb8e0c573 + ref: db69a03082e6811c58dc2d0e5c23d04305e1623f + resolved-ref: db69a03082e6811c58dc2d0e5c23d04305e1623f url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "1.0.0" @@ -782,8 +782,8 @@ packages: dependency: "direct main" description: path: "packages/lw_file_system" - ref: f29b1ae0e338ec155e1c5b0a204c399232904540 - resolved-ref: f29b1ae0e338ec155e1c5b0a204c399232904540 + ref: "2325ec71be6691f64725bc78a911cabed68d901b" + resolved-ref: "2325ec71be6691f64725bc78a911cabed68d901b" url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "1.0.0" @@ -791,8 +791,8 @@ packages: dependency: transitive description: path: "packages/lw_file_system_api" - ref: b9d6c6173bf75247ce5a4d47fab0e48b730a9696 - resolved-ref: b9d6c6173bf75247ce5a4d47fab0e48b730a9696 + ref: a0752f136913f64a975cb8b20ccb16fb6ce37737 + resolved-ref: a0752f136913f64a975cb8b20ccb16fb6ce37737 url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "1.0.0" @@ -841,8 +841,8 @@ packages: dependency: "direct main" description: path: "packages/material_leap" - ref: "9a142aa2aefc61c8c5ff2c70b31ea81b8485e428" - resolved-ref: "9a142aa2aefc61c8c5ff2c70b31ea81b8485e428" + ref: "307657c0e0b93de9af1e1aa9bd96900e0bb7d27c" + resolved-ref: "307657c0e0b93de9af1e1aa9bd96900e0bb7d27c" url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "0.0.1" diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 18a56cdd3844..11f93d3afad9 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -79,7 +79,7 @@ dependencies: material_leap: git: url: https://github.com/LinwoodDev/dart_pkgs - ref: 9a142aa2aefc61c8c5ff2c70b31ea81b8485e428 + ref: 307657c0e0b93de9af1e1aa9bd96900e0bb7d27c path: packages/material_leap lw_sysapi: git: @@ -99,7 +99,7 @@ dependencies: lw_file_system: git: url: https://github.com/LinwoodDev/dart_pkgs - ref: f29b1ae0e338ec155e1c5b0a204c399232904540 + ref: 2325ec71be6691f64725bc78a911cabed68d901b path: packages/lw_file_system flutter_localized_locales: ^2.0.5 dynamic_color: ^1.7.0 diff --git a/docs/package.json b/docs/package.json index bf9d8582306a..3b615a6fd1dc 100644 --- a/docs/package.json +++ b/docs/package.json @@ -24,7 +24,7 @@ "sharp": "^0.33.5", "typescript": "^5.7.2" }, - "packageManager": "pnpm@9.15.1", + "packageManager": "pnpm@9.15.2", "devDependencies": { "sass": "^1.83.0" } diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index 6bd9750c648e..56523e720296 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -236,8 +236,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.24.0': - resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -248,8 +248,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.24.0': - resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -260,8 +260,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.24.0': - resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -272,8 +272,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.24.0': - resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -284,8 +284,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.24.0': - resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -296,8 +296,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.24.0': - resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -308,8 +308,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.24.0': - resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -320,8 +320,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.24.0': - resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -332,8 +332,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.24.0': - resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -344,8 +344,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.24.0': - resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -356,8 +356,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.24.0': - resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -368,8 +368,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.24.0': - resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -380,8 +380,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.24.0': - resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -392,8 +392,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.24.0': - resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -404,8 +404,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.24.0': - resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -416,8 +416,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.24.0': - resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -428,26 +428,32 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.24.0': - resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.24.0': - resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.24.0': - resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -458,8 +464,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.24.0': - resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -470,8 +476,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.24.0': - resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -482,8 +488,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.24.0': - resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -494,8 +500,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.24.0': - resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -506,8 +512,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.24.0': - resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -756,12 +762,6 @@ packages: cpu: [x64] os: [linux] - '@parcel/watcher-wasm@2.5.0': - resolution: {integrity: sha512-Z4ouuR8Pfggk1EYYbTaIoxc+Yv4o7cGQnH0Xy8+pQ+HbiW+ZnwhcD2LPf/prfq1nIWpAxjOkQ8uSMFWMtBLiVQ==} - engines: {node: '>= 10.0.0'} - bundledDependencies: - - napi-wasm - '@parcel/watcher-win32-arm64@2.5.0': resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==} engines: {node: '>= 10.0.0'} @@ -1153,17 +1153,10 @@ packages: resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} engines: {node: '>=8'} - citty@0.1.6: - resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - cli-boxes@3.0.0: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} - clipboardy@4.0.0: - resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} - engines: {node: '>=18'} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1198,11 +1191,8 @@ packages: common-ancestor-path@1.0.1: resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} - confbox@0.1.8: - resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - - consola@3.3.1: - resolution: {integrity: sha512-GyKnPG3/I+a4RtJxgHquJXWr70g9I3c4NT3dvqh0LPHQP2nZFQBOBszb7a5u/pGzqr40AKplQA6UxM1BSynSXg==} + consola@3.3.3: + resolution: {integrity: sha512-Qil5KwghMzlqd51UXM0b6fyaGHtOC22scxrwrz4A2882LyUMwQjnvaedN1HAeXzphspQ6CpHkzMAWxBTUruDLg==} engines: {node: ^14.18.0 || >=16.10.0} convert-source-map@2.0.0: @@ -1215,10 +1205,6 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - crossws@0.3.1: resolution: {integrity: sha512-HsZgeVYaG+b5zA+9PbIPGq4+J/CJynJuearykPsXx4V/eMhyQ5EDVg3Ak2FBZtVXCiOLu/U7IiwDHTr9MA+IKw==} @@ -1308,8 +1294,8 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - es-module-lexer@1.5.4: - resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} esast-util-from-estree@2.0.0: resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} @@ -1322,8 +1308,8 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.24.0: - resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} hasBin: true @@ -1367,10 +1353,6 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - expressive-code@0.38.3: resolution: {integrity: sha512-COM04AiUotHCKJgWdn7NtW2lqu8OW8owAidMpkXt1qxrZ9Q2iC7+tok/1qIn2ocGnczvr9paIySgGnEwFeEQ8Q==} @@ -1429,13 +1411,6 @@ packages: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} - get-port-please@3.1.2: - resolution: {integrity: sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} @@ -1525,14 +1500,6 @@ packages: http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - http-shutdown@1.2.2: - resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - i18next@23.16.8: resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==} @@ -1600,21 +1567,10 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-wsl@3.1.0: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} - is64bit@2.0.0: - resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} - engines: {node: '>=18'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - jiti@2.4.2: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true @@ -1657,10 +1613,6 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} - listhen@1.9.0: - resolution: {integrity: sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg==} - hasBin: true - load-yaml-file@0.2.0: resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} engines: {node: '>=6'} @@ -1748,9 +1700,6 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1872,13 +1821,6 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - mlly@1.7.3: - resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} - mrmime@2.0.0: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} engines: {node: '>=10'} @@ -1907,10 +1849,6 @@ packages: node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} - node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} - engines: {node: '>= 6.13.0'} - node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} @@ -1918,10 +1856,6 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -1931,10 +1865,6 @@ packages: ohash@1.1.4: resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - oniguruma-to-es@0.8.1: resolution: {integrity: sha512-dekySTEvCxCj0IgKcA2uUCO/e4ArsqpucDPcX26w9ajx+DvMWLc5eZeJaRQkd7oC/+rwif5gnT900tA34uN9Zw==} @@ -1982,14 +1912,6 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -2012,9 +1934,6 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} - pkg-types@1.2.1: - resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} - postcss-nested@6.2.0: resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} @@ -2091,14 +2010,14 @@ packages: regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regex-recursion@5.0.0: - resolution: {integrity: sha512-UwyOqeobrCCqTXPcsSqH4gDhOjD5cI/b8kjngWgSZbxYh5yVjAwTjO5+hAuPRNiuR70+5RlWSs+U9PVcVcW9Lw==} + regex-recursion@5.1.1: + resolution: {integrity: sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==} regex-utilities@2.3.0: resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} - regex@5.0.2: - resolution: {integrity: sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==} + regex@5.1.1: + resolution: {integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==} rehype-expressive-code@0.38.3: resolution: {integrity: sha512-RYSSDkMBikoTbycZPkcWp6ELneANT4eTpND1DSRJ6nI2eVFUwTBDCvE2vO6jOOTaavwnPiydi4i/87NRyjpdOA==} @@ -2212,21 +2131,9 @@ packages: resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - shiki@1.24.4: resolution: {integrity: sha512-aVGSFAOAr1v26Hh/+GBIsRVDWJ583XYV7CuNURKRWh9gpGv4OdbisZGq96B9arMYTZhTQkmRF5BrShOSTvNqhw==} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -2259,9 +2166,6 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - std-env@3.8.0: - resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} - stream-replace-string@2.0.0: resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} @@ -2288,20 +2192,12 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - style-to-object@0.4.4: resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} style-to-object@1.0.8: resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} - system-architecture@0.1.0: - resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} - engines: {node: '>=18'} - terser@5.37.0: resolution: {integrity: sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==} engines: {node: '>=10'} @@ -2333,8 +2229,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - type-fest@4.30.2: - resolution: {integrity: sha512-UJShLPYi1aWqCdq9HycOL/gwsuqda1OISdBO3t8RlXQC4QvtuIz4b5FCfe2dQIWEpmlRExKmcTBfP1r9bhY7ig==} + type-fest@4.31.0: + resolution: {integrity: sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==} engines: {node: '>=16'} typesafe-path@0.2.2: @@ -2402,8 +2298,8 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - unstorage@1.14.1: - resolution: {integrity: sha512-0MBKpoVhNLL/Ixvue9lIsrHkwwWW9/f3TRftsYu1R7nZJJyHSdgPMBDjny2op07nirnS3OX6H3u+YDFGld+1Bg==} + unstorage@1.14.4: + resolution: {integrity: sha512-1SYeamwuYeQJtJ/USE1x4l17LkmQBzg7deBJ+U9qOBoHo15d1cDxG4jM31zKRgF7pG0kirZy4wVMX6WL6Zoscg==} peerDependencies: '@azure/app-configuration': ^1.8.0 '@azure/cosmos': ^4.2.0 @@ -2421,7 +2317,7 @@ packages: aws4fetch: ^1.0.20 db0: '>=0.2.1' idb-keyval: ^6.2.1 - ioredis: ^5.4.1 + ioredis: ^5.4.2 uploadthing: ^7.4.1 peerDependenciesMeta: '@azure/app-configuration': @@ -2461,19 +2357,12 @@ packages: uploadthing: optional: true - untun@0.1.3: - resolution: {integrity: sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==} - hasBin: true - update-browserslist-db@1.1.1: resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' - uqr@0.1.2: - resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -2486,8 +2375,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@6.0.5: - resolution: {integrity: sha512-akD5IAH/ID5imgue2DYhzsEwCi0/4VKY31uhMLEYJwPP4TiUp8pL5PIK+Wo7H8qT8JY9i+pVfPydcFPYD1EL7g==} + vite@6.0.6: + resolution: {integrity: sha512-NSjmUuckPmDU18bHz7QZ+bTYhRR0iA72cs2QAxCqDpafJ0S6qetco0LB3WW2OxlMHS0JmAv+yZ/R3uPmMyGTjQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -2651,11 +2540,6 @@ packages: resolution: {integrity: sha512-ysVYmw6+ZBhx3+ZkcPwRuJi38ZOTLJJ33PSHaitLxSKUMsh0LkKd0nC69zZCwt5D+AYUcMK2hhw4yWny20vSGg==} engines: {node: '>=18.12'} - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - widest-line@5.0.0: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} @@ -2803,7 +2687,7 @@ snapshots: '@mdx-js/mdx': 3.1.0(acorn@8.14.0) acorn: 8.14.0 astro: 5.1.1(jiti@2.4.2)(rollup@4.29.1)(sass@1.83.0)(terser@5.37.0)(typescript@5.7.2)(yaml@2.6.1) - es-module-lexer: 1.5.4 + es-module-lexer: 1.6.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.4 kleur: 4.1.5 @@ -2824,11 +2708,11 @@ snapshots: dependencies: '@types/react': 19.0.2 '@types/react-dom': 19.0.2(@types/react@19.0.2) - '@vitejs/plugin-react': 4.3.4(vite@6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1)) + '@vitejs/plugin-react': 4.3.4(vite@6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1)) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) ultrahtml: 1.5.3 - vite: 6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - '@types/node' - jiti @@ -3042,142 +2926,145 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true - '@esbuild/aix-ppc64@0.24.0': + '@esbuild/aix-ppc64@0.24.2': optional: true '@esbuild/android-arm64@0.21.5': optional: true - '@esbuild/android-arm64@0.24.0': + '@esbuild/android-arm64@0.24.2': optional: true '@esbuild/android-arm@0.21.5': optional: true - '@esbuild/android-arm@0.24.0': + '@esbuild/android-arm@0.24.2': optional: true '@esbuild/android-x64@0.21.5': optional: true - '@esbuild/android-x64@0.24.0': + '@esbuild/android-x64@0.24.2': optional: true '@esbuild/darwin-arm64@0.21.5': optional: true - '@esbuild/darwin-arm64@0.24.0': + '@esbuild/darwin-arm64@0.24.2': optional: true '@esbuild/darwin-x64@0.21.5': optional: true - '@esbuild/darwin-x64@0.24.0': + '@esbuild/darwin-x64@0.24.2': optional: true '@esbuild/freebsd-arm64@0.21.5': optional: true - '@esbuild/freebsd-arm64@0.24.0': + '@esbuild/freebsd-arm64@0.24.2': optional: true '@esbuild/freebsd-x64@0.21.5': optional: true - '@esbuild/freebsd-x64@0.24.0': + '@esbuild/freebsd-x64@0.24.2': optional: true '@esbuild/linux-arm64@0.21.5': optional: true - '@esbuild/linux-arm64@0.24.0': + '@esbuild/linux-arm64@0.24.2': optional: true '@esbuild/linux-arm@0.21.5': optional: true - '@esbuild/linux-arm@0.24.0': + '@esbuild/linux-arm@0.24.2': optional: true '@esbuild/linux-ia32@0.21.5': optional: true - '@esbuild/linux-ia32@0.24.0': + '@esbuild/linux-ia32@0.24.2': optional: true '@esbuild/linux-loong64@0.21.5': optional: true - '@esbuild/linux-loong64@0.24.0': + '@esbuild/linux-loong64@0.24.2': optional: true '@esbuild/linux-mips64el@0.21.5': optional: true - '@esbuild/linux-mips64el@0.24.0': + '@esbuild/linux-mips64el@0.24.2': optional: true '@esbuild/linux-ppc64@0.21.5': optional: true - '@esbuild/linux-ppc64@0.24.0': + '@esbuild/linux-ppc64@0.24.2': optional: true '@esbuild/linux-riscv64@0.21.5': optional: true - '@esbuild/linux-riscv64@0.24.0': + '@esbuild/linux-riscv64@0.24.2': optional: true '@esbuild/linux-s390x@0.21.5': optional: true - '@esbuild/linux-s390x@0.24.0': + '@esbuild/linux-s390x@0.24.2': optional: true '@esbuild/linux-x64@0.21.5': optional: true - '@esbuild/linux-x64@0.24.0': + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': optional: true '@esbuild/netbsd-x64@0.21.5': optional: true - '@esbuild/netbsd-x64@0.24.0': + '@esbuild/netbsd-x64@0.24.2': optional: true - '@esbuild/openbsd-arm64@0.24.0': + '@esbuild/openbsd-arm64@0.24.2': optional: true '@esbuild/openbsd-x64@0.21.5': optional: true - '@esbuild/openbsd-x64@0.24.0': + '@esbuild/openbsd-x64@0.24.2': optional: true '@esbuild/sunos-x64@0.21.5': optional: true - '@esbuild/sunos-x64@0.24.0': + '@esbuild/sunos-x64@0.24.2': optional: true '@esbuild/win32-arm64@0.21.5': optional: true - '@esbuild/win32-arm64@0.24.0': + '@esbuild/win32-arm64@0.24.2': optional: true '@esbuild/win32-ia32@0.21.5': optional: true - '@esbuild/win32-ia32@0.24.0': + '@esbuild/win32-ia32@0.24.2': optional: true '@esbuild/win32-x64@0.21.5': optional: true - '@esbuild/win32-x64@0.24.0': + '@esbuild/win32-x64@0.24.2': optional: true '@expressive-code/core@0.38.3': @@ -3394,11 +3281,6 @@ snapshots: '@parcel/watcher-linux-x64-musl@2.5.0': optional: true - '@parcel/watcher-wasm@2.5.0': - dependencies: - is-glob: 4.0.3 - micromatch: 4.0.8 - '@parcel/watcher-win32-arm64@2.5.0': optional: true @@ -3428,6 +3310,7 @@ snapshots: '@parcel/watcher-win32-arm64': 2.5.0 '@parcel/watcher-win32-ia32': 2.5.0 '@parcel/watcher-win32-x64': 2.5.0 + optional: true '@phosphor-icons/react@2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: @@ -3601,14 +3484,14 @@ snapshots: '@ungap/structured-clone@1.2.1': {} - '@vitejs/plugin-react@4.3.4(vite@6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1))': + '@vitejs/plugin-react@4.3.4(vite@6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - supports-color @@ -3737,7 +3620,7 @@ snapshots: diff: 5.2.0 dlv: 1.1.3 dset: 3.1.4 - es-module-lexer: 1.5.4 + es-module-lexer: 1.6.0 esbuild: 0.21.5 estree-walker: 3.0.3 fast-glob: 3.3.2 @@ -3763,10 +3646,10 @@ snapshots: tsconfck: 3.1.4(typescript@5.7.2) ultrahtml: 1.5.3 unist-util-visit: 5.0.0 - unstorage: 1.14.1 + unstorage: 1.14.4 vfile: 6.0.3 - vite: 6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) - vitefu: 1.0.4(vite@6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1)) + vite: 6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) + vitefu: 1.0.4(vite@6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1)) which-pm: 3.0.0 xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 @@ -3835,7 +3718,7 @@ snapshots: chalk: 5.4.1 cli-boxes: 3.0.0 string-width: 7.2.0 - type-fest: 4.30.2 + type-fest: 4.31.0 widest-line: 5.0.0 wrap-ansi: 9.0.0 @@ -3887,18 +3770,8 @@ snapshots: ci-info@4.1.0: {} - citty@0.1.6: - dependencies: - consola: 3.3.1 - cli-boxes@3.0.0: {} - clipboardy@4.0.0: - dependencies: - execa: 8.0.1 - is-wsl: 3.1.0 - is64bit: 2.0.0 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -3932,9 +3805,7 @@ snapshots: common-ancestor-path@1.0.1: {} - confbox@0.1.8: {} - - consola@3.3.1: {} + consola@3.3.3: {} convert-source-map@2.0.0: {} @@ -3942,12 +3813,6 @@ snapshots: cookie@0.7.2: {} - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - crossws@0.3.1: dependencies: uncrypto: 0.1.3 @@ -3972,7 +3837,8 @@ snapshots: destr@2.0.3: {} - detect-libc@1.0.3: {} + detect-libc@1.0.3: + optional: true detect-libc@2.0.3: {} @@ -4009,7 +3875,7 @@ snapshots: entities@4.5.0: {} - es-module-lexer@1.5.4: {} + es-module-lexer@1.6.0: {} esast-util-from-estree@2.0.0: dependencies: @@ -4051,32 +3917,33 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - esbuild@0.24.0: + esbuild@0.24.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.24.0 - '@esbuild/android-arm': 0.24.0 - '@esbuild/android-arm64': 0.24.0 - '@esbuild/android-x64': 0.24.0 - '@esbuild/darwin-arm64': 0.24.0 - '@esbuild/darwin-x64': 0.24.0 - '@esbuild/freebsd-arm64': 0.24.0 - '@esbuild/freebsd-x64': 0.24.0 - '@esbuild/linux-arm': 0.24.0 - '@esbuild/linux-arm64': 0.24.0 - '@esbuild/linux-ia32': 0.24.0 - '@esbuild/linux-loong64': 0.24.0 - '@esbuild/linux-mips64el': 0.24.0 - '@esbuild/linux-ppc64': 0.24.0 - '@esbuild/linux-riscv64': 0.24.0 - '@esbuild/linux-s390x': 0.24.0 - '@esbuild/linux-x64': 0.24.0 - '@esbuild/netbsd-x64': 0.24.0 - '@esbuild/openbsd-arm64': 0.24.0 - '@esbuild/openbsd-x64': 0.24.0 - '@esbuild/sunos-x64': 0.24.0 - '@esbuild/win32-arm64': 0.24.0 - '@esbuild/win32-ia32': 0.24.0 - '@esbuild/win32-x64': 0.24.0 + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 escalade@3.2.0: {} @@ -4121,18 +3988,6 @@ snapshots: eventemitter3@5.0.1: {} - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - expressive-code@0.38.3: dependencies: '@expressive-code/core': 0.38.3 @@ -4187,10 +4042,6 @@ snapshots: get-east-asian-width@1.3.0: {} - get-port-please@3.1.2: {} - - get-stream@8.0.1: {} - github-slugger@2.0.0: {} glob-parent@5.1.2: @@ -4411,10 +4262,6 @@ snapshots: http-cache-semantics@4.1.1: {} - http-shutdown@1.2.2: {} - - human-signals@5.0.0: {} - i18next@23.16.8: dependencies: '@babel/runtime': 7.26.0 @@ -4464,19 +4311,12 @@ snapshots: is-plain-obj@4.1.0: {} - is-stream@3.0.0: {} - is-wsl@3.1.0: dependencies: is-inside-container: 1.0.0 - is64bit@2.0.0: - dependencies: - system-architecture: 0.1.0 - - isexe@2.0.0: {} - - jiti@2.4.2: {} + jiti@2.4.2: + optional: true js-tokens@4.0.0: {} @@ -4503,27 +4343,6 @@ snapshots: kleur@4.1.5: {} - listhen@1.9.0: - dependencies: - '@parcel/watcher': 2.5.0 - '@parcel/watcher-wasm': 2.5.0 - citty: 0.1.6 - clipboardy: 4.0.0 - consola: 3.3.1 - crossws: 0.3.1 - defu: 6.1.4 - get-port-please: 3.1.2 - h3: 1.13.0 - http-shutdown: 1.2.2 - jiti: 2.4.2 - mlly: 1.7.3 - node-forge: 1.3.1 - pathe: 1.1.2 - std-env: 3.8.0 - ufo: 1.5.4 - untun: 0.1.3 - uqr: 0.1.2 - load-yaml-file@0.2.0: dependencies: graceful-fs: 4.2.11 @@ -4741,8 +4560,6 @@ snapshots: dependencies: '@types/mdast': 4.0.4 - merge-stream@2.0.0: {} - merge2@1.4.1: {} micromark-core-commonmark@2.0.2: @@ -5028,15 +4845,6 @@ snapshots: mime@3.0.0: {} - mimic-fn@4.0.0: {} - - mlly@1.7.3: - dependencies: - acorn: 8.14.0 - pathe: 1.1.2 - pkg-types: 1.2.1 - ufo: 1.5.4 - mrmime@2.0.0: {} ms@2.1.3: {} @@ -5051,20 +4859,15 @@ snapshots: dependencies: '@types/nlcst': 2.0.3 - node-addon-api@7.1.1: {} + node-addon-api@7.1.1: + optional: true node-fetch-native@1.6.4: {} - node-forge@1.3.1: {} - node-releases@2.0.19: {} normalize-path@3.0.0: {} - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -5077,15 +4880,11 @@ snapshots: ohash@1.1.4: {} - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - oniguruma-to-es@0.8.1: dependencies: emoji-regex-xs: 1.0.0 - regex: 5.0.2 - regex-recursion: 5.0.0 + regex: 5.1.1 + regex-recursion: 5.1.1 p-limit@2.3.0: dependencies: @@ -5143,10 +4942,6 @@ snapshots: path-exists@4.0.0: {} - path-key@3.1.1: {} - - path-key@4.0.0: {} - pathe@1.1.2: {} picocolors@1.1.1: {} @@ -5161,12 +4956,6 @@ snapshots: dependencies: find-up: 4.1.0 - pkg-types@1.2.1: - dependencies: - confbox: 0.1.8 - mlly: 1.7.3 - pathe: 1.1.2 - postcss-nested@6.2.0(postcss@8.4.49): dependencies: postcss: 8.4.49 @@ -5252,13 +5041,14 @@ snapshots: regenerator-runtime@0.14.1: {} - regex-recursion@5.0.0: + regex-recursion@5.1.1: dependencies: + regex: 5.1.1 regex-utilities: 2.3.0 regex-utilities@2.3.0: {} - regex@5.0.2: + regex@5.1.1: dependencies: regex-utilities: 2.3.0 @@ -5478,12 +5268,6 @@ snapshots: '@img/sharp-win32-ia32': 0.33.5 '@img/sharp-win32-x64': 0.33.5 - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - shiki@1.24.4: dependencies: '@shikijs/core': 1.24.4 @@ -5493,8 +5277,6 @@ snapshots: '@shikijs/vscode-textmate': 9.3.1 '@types/hast': 3.0.4 - signal-exit@4.1.0: {} - simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 @@ -5525,8 +5307,6 @@ snapshots: sprintf-js@1.0.3: {} - std-env@3.8.0: {} - stream-replace-string@2.0.0: {} string-width@4.2.3: @@ -5556,8 +5336,6 @@ snapshots: strip-bom@3.0.0: {} - strip-final-newline@3.0.0: {} - style-to-object@0.4.4: dependencies: inline-style-parser: 0.1.1 @@ -5566,8 +5344,6 @@ snapshots: dependencies: inline-style-parser: 0.2.4 - system-architecture@0.1.0: {} - terser@5.37.0: dependencies: '@jridgewell/source-map': 0.3.6 @@ -5593,7 +5369,7 @@ snapshots: tslib@2.8.1: optional: true - type-fest@4.30.2: {} + type-fest@4.31.0: {} typesafe-path@0.2.2: {} @@ -5611,7 +5387,7 @@ snapshots: unenv@1.10.0: dependencies: - consola: 3.3.1 + consola: 3.3.3 defu: 6.1.4 mime: 3.0.0 node-fetch-native: 1.6.4 @@ -5683,33 +5459,23 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - unstorage@1.14.1: + unstorage@1.14.4: dependencies: anymatch: 3.1.3 chokidar: 3.6.0 - citty: 0.1.6 destr: 2.0.3 h3: 1.13.0 - listhen: 1.9.0 lru-cache: 10.4.3 node-fetch-native: 1.6.4 ofetch: 1.4.1 ufo: 1.5.4 - untun@0.1.3: - dependencies: - citty: 0.1.6 - consola: 3.3.1 - pathe: 1.1.2 - update-browserslist-db@1.1.1(browserslist@4.24.3): dependencies: browserslist: 4.24.3 escalade: 3.2.0 picocolors: 1.1.1 - uqr@0.1.2: {} - util-deprecate@1.0.2: {} vfile-location@5.0.3: @@ -5727,9 +5493,9 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1): + vite@6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1): dependencies: - esbuild: 0.24.0 + esbuild: 0.24.2 postcss: 8.4.49 rollup: 4.29.1 optionalDependencies: @@ -5739,9 +5505,9 @@ snapshots: terser: 5.37.0 yaml: 2.6.1 - vitefu@1.0.4(vite@6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1)): + vitefu@1.0.4(vite@6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1)): optionalDependencies: - vite: 6.0.5(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.6(jiti@2.4.2)(sass@1.83.0)(terser@5.37.0)(yaml@2.6.1) volar-service-css@0.0.62(@volar/language-service@2.4.11): dependencies: @@ -5860,10 +5626,6 @@ snapshots: dependencies: load-yaml-file: 0.2.0 - which@2.0.2: - dependencies: - isexe: 2.0.0 - widest-line@5.0.0: dependencies: string-width: 7.2.0