EchoEllet / flutter_keyboard_visibility_temp_fork

Get notified on keyboard visibility changes in your Flutter app
MIT License
2 stars 7 forks source link

added iOS notification observer for the floating keyboard #2

Closed mtallenca closed 3 weeks ago

mtallenca commented 1 month ago

I was using a forked version of flutter_keyboard_visibility that had detection for iOS floating keyboards on iPads. I had also submitted a PR a few months ago to the main repo - but as you already know - no updates from them.

EchoEllet commented 3 weeks ago

For some reason, I didn't got a notification of this PR. I will review it soon.

mtallenca commented 3 weeks ago

This is unrelated to the floating keyboard. On Samsung phones, when a text field gets focus, the soft keyboard comes up. If the user is using voice typing by tapping a microphone, (depending on samsung keyboard / google keyboard / samsung voice / google voice configuration and One UI version) the soft keyboard drops and the voice input takes its place. Without the debounce, keyboard visibility will send a keyboard drop, keyboard up within a few milliseconds. In our app, if you drop the keyboard manually, focus is removed. We added the debounce so if the keyboard is quickly changing to another mode, no change notification is sent.

On Tue, Nov 5, 2024 at 6:36 AM Ellet @.***> wrote:

@.**** commented on this pull request.

Unfortunately, I'm unable to review this PR properly, I'm unfamiliar with the Apple ecosystem and haven't used Objective-C before. Also, I need some time to understand the plugin itself.

I plan on rewriting the keyboard visibility functionality as part of quill_native_bridge https://pub.dev/packages/quill_native_bridge once I have more time.

Thank you for your contribution.

In flutter_keyboard_visibility_temp_fork/lib/src/keyboard_visibility_handler.dart https://github.com/EchoEllet/flutter_keyboard_visibility_temp_fork/pull/2#discussion_r1829451596 :

  • if (_debounce?.isActive ?? false) _debounce?.cancel();
  • // report keyboard visible quickly, report keyboard not visible after longer delay
  • // in case the keyboard is just switching modes
  • _debounce = Timer(Duration(milliseconds: newValue ? 25 : 250), () {
  • _testIsVisible = newValue;
  • // Don't report the same value multiple times

  • if (newValue == _isVisible) {

  • return;

  • }

  • // Don't report the same value multiple times

  • if (newValue == _isVisible) {

  • return;

  • }

  • _isVisible = newValue;

  • _onChangeController.add(newValue);

  • _isVisible = newValue;

  • _onChangeController.add(newValue);

Is this for all platforms and unrelated to the floating keyboard on iOS?

— Reply to this email directly, view it on GitHub https://github.com/EchoEllet/flutter_keyboard_visibility_temp_fork/pull/2#pullrequestreview-2415793532, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAXMGLMG3GVAFLXPB5EKXKLZ7DJV5AVCNFSM6AAAAABPGCJKX2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDIMJVG44TGNJTGI . You are receiving this because you authored the thread.Message ID: <EchoEllet/flutter_keyboard_visibility_temp_fork/pull/2/review/2415793532@ github.com>

EchoEllet commented 3 weeks ago

Published as pre-release:

dependency_overrides:
  flutter_keyboard_visibility_temp_fork: 0.1.3-alpha
EchoEllet commented 3 weeks ago

It looks like tests are failing:

Details

```console 00:01 +6: KeyboardDismissOnTap It removes focus when tapped Warning: A call to tap() with finder "Found 1 widget with key [<'box'>]: [ SizedBox-[<'box'>](width: 100.0, height: 100.0, renderObject: RenderConstrainedBox#a1e1d relayoutBoundary=up1), ]" derived an Offset (Offset(400.0, 50.0)) that would not hit test on the specified widget. Maybe the widget is actually off-screen, or another widget is obscuring it, or the widget cannot receive pointer events. The finder corresponds to this RenderBox: RenderConstrainedBox#a1e1d relayoutBoundary=up1 The hit test result at that offset is: HitTestResult(_RenderInkFeatures#74297@Offset(400.0, 50.0), RenderPhysicalModel#7e9a8@Offset(400.0, 50.0), RenderPointerListener#7d574@Offset(400.0, 50.0), RenderSemanticsGestureHandler#07645@Offset(400.0, 50.0), RenderSemanticsAnnotations#6610e@Offset(400.0, 50.0), RenderRepaintBoundary#31724@Offset(400.0, 50.0), RenderIgnorePointer#2c244@Offset(400.0, 50.0), _RenderSnapshotWidget#888a0@Offset(400.0, 50.0), _RenderSnapshotWidget#6ab93@Offset(400.0, 50.0), _RenderSnapshotWidget#7af8f@Offset(400.0, 50.0), _RenderSnapshotWidget#0f5fb@Offset(400.0, 50.0), RenderRepaintBoundary#184be@Offset(400.0, 50.0), RenderSemanticsAnnotations#fea93@Offset(400.0, 50.0), RenderOffstage#77c1f@Offset(400.0, 50.0), RenderSemanticsAnnotations#94844@Offset(400.0, 50.0), _RenderTheater#1b108@Offset(400.0, 50.0), RenderAbsorbPointer#60ceb@Offset(400.0, 50.0), RenderPointerListener#1b0d0@Offset(400.0, 50.0), RenderSemanticsAnnotations#b0b17@Offset(400.0, 50.0), RenderCustomPaint#f5274@Offset(400.0, 50.0), RenderSemanticsAnnotations#b5649@Offset(400.0, 50.0), RenderSemanticsAnnotations#7dad5@Offset(400.0, 50.0), RenderTapRegionSurface#98963@Offset(400.0, 50.0), RenderSemanticsAnnotations#0238a@Offset(400.0, 50.0), RenderSemanticsAnnotations#08185@Offset(400.0, 50.0), RenderSemanticsAnnotations#828c5@Offset(400.0, 50.0), HitTestEntry#76180(_ReusableRenderView#24aab), HitTestEntry#35307()) #0 WidgetController._getElementPoint (package:flutter_test/src/controller.dart:1941:25) #1 WidgetController.getCenter (package:flutter_test/src/controller.dart:1792:12) #2 WidgetController.tap (package:flutter_test/src/controller.dart:1040:18) #3 main.. (file:///Users/ellet/Developer/contributions/flutter_keyboard_visibility_temp_fork/flutter_keyboard_visibility_temp_fork/test/flutter_keyboard_visibility_test.dart:243:20) #4 testWidgets.. (package:flutter_test/src/widget_tester.dart:189:15) #5 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1032:5) #6 StackZoneSpecification._registerCallback. (package:stack_trace/src/stack_zone_specification.dart:114:42) To silence this warning, pass "warnIfMissed: false" to "tap()". To make this warning fatal, set WidgetController.hitTestWarningShouldBeFatal to true. 00:01 +7: KeyboardVisibilityTesting setVisibilityForTesting allows overriding of value to true for testing ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ The following TestFailure was thrown running a test: Expected: Actual: When the exception was thrown, this was the stack: #4 main.. (file:///Users/ellet/Developer/contributions/flutter_keyboard_visibility_temp_fork/flutter_keyboard_visibility_temp_fork/test/flutter_keyboard_visibility_test.dart:273:7) #5 testWidgets.. (package:flutter_test/src/widget_tester.dart:189:15) #6 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1032:5) (elided one frame from package:stack_trace) This was caught by the test expectation on the following line: file:///Users/ellet/Developer/contributions/flutter_keyboard_visibility_temp_fork/flutter_keyboard_visibility_temp_fork/test/flutter_keyboard_visibility_test.dart line 273 The test description was: setVisibilityForTesting allows overriding of value to true for testing ════════════════════════════════════════════════════════════════════════════════════════════════════ 00:01 +7 -1: KeyboardVisibilityTesting setVisibilityForTesting allows overriding of value to true for testing [E] Test failed. See exception logs above. The test description was: setVisibilityForTesting allows overriding of value to true for testing To run this test again: /Users/ellet/Developer/sdks/flutter/bin/cache/dart-sdk/bin/dart test /Users/ellet/Developer/contributions/flutter_keyboard_visibility_temp_fork/flutter_keyboard_visibility_temp_fork/test/flutter_keyboard_visibility_test.dart -p vm --plain-name 'KeyboardVisibilityTesting setVisibilityForTesting allows overriding of value to true for testing' 00:01 +7 -1: KeyboardVisibilityTesting setVisibilityForTesting allows overriding of value to false for testing Pending timers: Timer (duration: 0:00:00.250000, periodic: false), created: #0 new FakeTimer._ (package:fake_async/fake_async.dart:308:62) #1 FakeAsync._createTimer (package:fake_async/fake_async.dart:252:27) #2 FakeAsync.run. (package:fake_async/fake_async.dart:185:19) #5 KeyboardVisibilityHandler._updateValue (package:flutter_keyboard_visibility_temp_fork/src/keyboard_visibility_handler.dart:54:17) #6 KeyboardVisibilityHandler.setVisibilityForTesting (package:flutter_keyboard_visibility_temp_fork/src/keyboard_visibility_handler.dart:47:5) #7 KeyboardVisibilityTesting.setVisibilityForTesting (package:flutter_keyboard_visibility_temp_fork/src/keyboard_visibility_test_util.dart:13:31) #8 main.. (file:///Users/ellet/Developer/contributions/flutter_keyboard_visibility_temp_fork/flutter_keyboard_visibility_temp_fork/test/flutter_keyboard_visibility_test.dart:279:33) #9 testWidgets.. (package:flutter_test/src/widget_tester.dart:189:29) #10 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1032:5) (elided 3 frames from dart:async and package:stack_trace) ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ The following assertion was thrown running a test: A Timer is still pending even after the widget tree was disposed. 'package:flutter_test/src/binding.dart': Failed assertion: line 1542 pos 12: '!timersPending' When the exception was thrown, this was the stack: #2 AutomatedTestWidgetsFlutterBinding._verifyInvariants (package:flutter_test/src/binding.dart:1542:12) #3 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1049:7) (elided 3 frames from class _AssertionError and package:stack_trace) The test description was: setVisibilityForTesting allows overriding of value to false for testing ════════════════════════════════════════════════════════════════════════════════════════════════════ 00:01 +7 -2: KeyboardVisibilityTesting setVisibilityForTesting allows overriding of value to false for testing [E] Test failed. See exception logs above. The test description was: setVisibilityForTesting allows overriding of value to false for testing ```

Fixed by applying the change directly in tests without the timer.