diff --git a/app/lib/dialogs/add.dart b/app/lib/dialogs/add.dart index 44faeee245e5..a1309adbacd4 100644 --- a/app/lib/dialogs/add.dart +++ b/app/lib/dialogs/add.dart @@ -130,6 +130,7 @@ class AddDialog extends StatelessWidget { Tool.presentation, () => Tool.spacer(axis: Axis2D.vertical), () => Tool.spacer(axis: Axis2D.horizontal), + Tool.eyeDropper, ] .map((e) => e()) .where((e) => e diff --git a/app/lib/handlers/eye_dropper.dart b/app/lib/handlers/eye_dropper.dart index ef43f7a614ef..455e23d14a38 100644 --- a/app/lib/handlers/eye_dropper.dart +++ b/app/lib/handlers/eye_dropper.dart @@ -4,9 +4,9 @@ class EyeDropperHandler extends Handler { EyeDropperHandler(super.data); @override - void onTapUp(TapUpDetails details, EventContext context) async { + void onPointerUp(PointerUpEvent event, EventContext context) async { final globalPos = - context.getCameraTransform().localToGlobal(details.localPosition); + context.getCameraTransform().localToGlobal(event.localPosition); final state = context.getState(); if (state == null) return; final data = await context.getCurrentIndexCubit().render( @@ -19,14 +19,29 @@ class EyeDropperHandler extends Handler { y: globalPos.dy, ); if (data == null) return; - final image = img.Image.fromBytes(width: 1, height: 1, bytes: data.buffer); + final image = img.decodePng(data.buffer.asUint8List()); + if (image == null) return; final pixel = image.getPixel(0, 0); - final color = pixel.r.toInt() << 24 | - pixel.g.toInt() << 16 | - pixel.b.toInt() << 8 | - pixel.a.toInt(); - Clipboard.setData(ClipboardData( - text: '#${color.toRadixString(16).padLeft(8, '0').toUpperCase()}', - )); + final handler = + context.getCurrentIndexCubit().getHandler(disableTemporary: true); + if (handler is ColoredHandler) { + final color = pixel.a.toInt() << 24 | + pixel.r.toInt() << 16 | + pixel.g.toInt() << 8 | + pixel.b.toInt(); + final newTool = handler.setColor(color); + final index = state.info.tools.indexOf(handler.data); + context.getDocumentBloc().add(ToolsChanged({index: newTool})); + } else { + final color = + pixel.r.toInt() << 16 | pixel.g.toInt() << 8 | pixel.b.toInt(); + Clipboard.setData(ClipboardData( + text: '#${color.toRadixString(16).padLeft(6, '0')}', + )); + final loc = AppLocalizations.of(context.buildContext); + ScaffoldMessenger.of(context.buildContext).showSnackBar(SnackBar( + content: Text(loc.copyTitle), + )); + } } } diff --git a/app/lib/handlers/handler.dart b/app/lib/handlers/handler.dart index 72417ddc5211..92c51e1ffc44 100644 --- a/app/lib/handlers/handler.dart +++ b/app/lib/handlers/handler.dart @@ -263,6 +263,27 @@ abstract class Handler { MouseCursor? get cursor => null; } +mixin ColoredHandler on Handler { + int getColor(); + T setColor(int color); + + @override + PreferredSizeWidget getToolbar(DocumentBloc bloc) => ColorToolbarView( + color: getColor(), + onChanged: (value) { + final state = bloc.state; + if (state is! DocumentLoadSuccess) return; + final index = state.info.tools.indexOf(data); + bloc.add(ToolsChanged({index: setColor(value)})); + }, + onEyeDropper: () { + final state = bloc.state; + state.currentIndexCubit + ?.changeTemporaryHandler(bloc, EyeDropperTool()); + }, + ); +} + mixin HandlerWithCursor on Handler { Offset? _currentPos; diff --git a/app/lib/handlers/pen.dart b/app/lib/handlers/pen.dart index 60fcf34e7495..686a2dea7ca3 100644 --- a/app/lib/handlers/pen.dart +++ b/app/lib/handlers/pen.dart @@ -1,6 +1,6 @@ part of 'handler.dart'; -class PenHandler extends Handler { +class PenHandler extends Handler with ColoredHandler { final Map elements = {}; final Map lastPosition = {}; @@ -122,19 +122,12 @@ class PenHandler extends Handler { } @override - PreferredSizeWidget getToolbar(DocumentBloc bloc) => ColorToolbarView( - color: data.property.color, - onChanged: (value) { - final state = bloc.state; - if (state is! DocumentLoadSuccess) return; - final index = state.info.tools.indexOf(data); - bloc.add(ToolsChanged({ - index: data.copyWith( - property: data.property.copyWith( - color: convertOldColor(value, data.property.color))) - })); - }, - ); + int getColor() => data.property.color; + + @override + PenTool setColor(int color) => data.copyWith( + property: data.property + .copyWith(color: convertOldColor(color, data.property.color))); @override MouseCursor get cursor => SystemMouseCursors.precise; diff --git a/app/lib/views/toolbars/color.dart b/app/lib/views/toolbars/color.dart index 3c35bd241348..a0649c3ad521 100644 --- a/app/lib/views/toolbars/color.dart +++ b/app/lib/views/toolbars/color.dart @@ -11,16 +11,18 @@ import 'package:phosphor_flutter/phosphor_flutter.dart'; import '../../bloc/document_bloc.dart'; -enum ColorPickerToolbarAction { delete, pin } +enum ColorPickerToolbarAction { delete, pin, eyeDropper } class ColorToolbarView extends StatefulWidget implements PreferredSizeWidget { final int color; final ValueChanged onChanged; + final VoidCallback? onEyeDropper; const ColorToolbarView({ super.key, required this.color, required this.onChanged, + this.onEyeDropper, }); @override @@ -71,6 +73,15 @@ class _ColorToolbarViewState extends State { value: Color(widget.color), suggested: settingsCubit.state.recentColors.map((e) => Color(e)).toList(), + secondaryActions: widget.onEyeDropper == null + ? null + : (close) => [ + OutlinedButton( + onPressed: () => + close(ColorPickerToolbarAction.eyeDropper), + child: Text(AppLocalizations.of(context).eyeDropper), + ), + ], primaryActions: palette == null ? null : (close) => [ @@ -83,6 +94,10 @@ class _ColorToolbarViewState extends State { ); if (response == null) return; widget.onChanged(response.color); + if (response.action == ColorPickerToolbarAction.eyeDropper) { + widget.onEyeDropper?.call(); + return; + } if (response.action != ColorPickerToolbarAction.pin) { settingsCubit.addRecentColors(response.color); return; diff --git a/docs/package.json b/docs/package.json index 09a8e2fdb6fa..79b7cae8bf89 100644 --- a/docs/package.json +++ b/docs/package.json @@ -47,7 +47,7 @@ "last 1 safari version" ] }, - "packageManager": "pnpm@8.10.0", + "packageManager": "pnpm@8.10.2", "devDependencies": { "@docusaurus/module-type-aliases": "2.4.3", "@tsconfig/docusaurus": "^2.0.2", diff --git a/fastlane/metadata/android/en-US/changelogs/78.txt b/fastlane/metadata/android/en-US/changelogs/78.txt index f3fd1b7ce6b6..2a30859fcf24 100644 --- a/fastlane/metadata/android/en-US/changelogs/78.txt +++ b/fastlane/metadata/android/en-US/changelogs/78.txt @@ -2,6 +2,7 @@ * Add scrollbar to recent files * Add recent colors to color picker * Add version to web +* Add eye dropper * Show remote on hover in recent files * Improve action buttons in add dialog * Improve color picker dialog