nank1ro / flutter-shadcn-ui

shadcn-ui ported in Flutter. Awesome UI components for Flutter, fully customizable.
https://flutter-shadcn-ui.mariuti.com
MIT License
1.14k stars 64 forks source link

[ShadContextMenuRegion - `BUG` ] #148

Closed moshOntong-IT closed 1 month ago

moshOntong-IT commented 1 month ago

Throw exception: Failed assertion: line 1174 pos 15: '!identical(kind, PointerDeviceKind.trackpad)':

In below this could be the simple Widget that we can easily reproduce the throw exception:


class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return ShadContextMenuRegion(
      children: [
        ShadContextMenuItem(
          leading: const ShadImage.square(LucideIcons.plus, size: 16),
          child: const Text('Create Report'),
          onPressed: () {},
        ),
        ShadContextMenuItem.inset(
          child: const Text(
            'Refresh',
          ),
          onPressed: () {},
        ),
        ShadContextMenuItem.inset(
          child: const Text(
            'Advanced Filter',
          ),
          onPressed: () {},
        ),
      ],
      child: Scaffold(
        body: CustomScrollView(
          slivers: [],
        ),
      ),
    );
  }
}

When you are trying to scroll down using your Trackpad (Not mouse - currenlty I am using windows). It will occur the bug. If you try to remove that ShadContextMenuRegion the error will not occur anymore

nank1ro commented 1 month ago

Why are you putting your context menu region above all the scaffold? It should be placed only on the specific widget where you want the behavior

moshOntong-IT commented 1 month ago

Why are you putting your context menu region above all the scaffold? It should be placed only on the specific widget where you want the behavior

I put the Scaffold as a parent of Context Menu region:

  return Scaffold(
      body: ShadContextMenuRegion(
        children: [
          ShadContextMenuItem(
            leading: const ShadImage.square(LucideIcons.plus, size: 16),
            child: const Text('Create Report'),
            onPressed: () {},
          ),
          ShadContextMenuItem.inset(
            child: const Text(
              'Refresh',
            ),
            onPressed: () {},
          ),
          ShadContextMenuItem.inset(
            child: const Text(
              'Advanced Filter',
            ),
            onPressed: () {},
          ),
        ],
        child: CustomScrollView(
          slivers: [],
        ),
      ),
    );

But the it still throws an error

nank1ro commented 1 month ago

I don't understand why you are placing the whole page inside a context menu. What's your use case? Ideally you should place only a specific widget, and only the specific widget will have a context menu. See this code for example https://flutter-shadcn-ui.mariuti.com/components/context-menu/

moshOntong-IT commented 1 month ago

I don't understand why you are placing the whole page inside a context menu. What's your use case? Ideally you should place only a specific widget, and only the specific widget will have a context menu. See this code for example https://flutter-shadcn-ui.mariuti.com/components/context-menu/

In my use case: image

I do have list of reports which when right click there a context menu what user can do:

nank1ro commented 1 month ago

But you want a specific context menu for each report right? In case place one above each one in the list.

moshOntong-IT commented 1 month ago

But you want a specific context menu for each report right? In case place one above each one in the list. Nope.

nank1ro commented 1 month ago

Can you share the stack trace and the error?

moshOntong-IT commented 1 month ago

I just try to find a way :

  return SafeArea(
      child: Scaffold(
        body: RefreshIndicator(
          onRefresh: () async {
            ref.invalidate(reportListControllerProvider);
          },
          child: Padding(
            padding: breakpoints.between(MOBILE, TABLET)
                ? const EdgeInsets.all(8)
                : const EdgeInsets.all(16),
            child: LazyLoadScrollView(
              onEndOfPage: () {
                ref.read(reportListControllerProvider.notifier).loadMore();
              },
              child: Stack(
                children: [
                  Positioned.fill(
                    child: CustomScrollView(
                      slivers: [
                        const SliverToBoxAdapter(
                          child: _SearchAndPostSection(),
                        ),
                        const SliverToBoxAdapter(
                          child: _ExtraTagsSection(),
                        ),
                        const SliverGap(16),
                        ...reportState.when(
                            data: (value) {
                              return [
                                switch (value.isEmpty) {
                                  true => SliverFillRemaining(
                                      hasScrollBody: false,
                                      child: Center(
                                        child: Text(switch (userMetadata.role) {
                                          RoleType.watcher =>
                                            'No reports found. To add a report, please go to your dedicated room.',
                                          _ =>
                                            'No reports found. Tap + to add a report.'
                                        }),
                                      ),
                                    ),
                                  false => SliverList.separated(
                                      separatorBuilder: (context, index) =>
                                          const Gap(10),
                                      itemCount: value.length,
                                      itemBuilder: (context, index) {
                                        return ProviderScope(
                                          key: ValueKey(value[index].id),
                                          overrides: [
                                            reportProvider.overrideWithValue(
                                                value[index]),
                                          ],
                                          child: const ReportItem(),
                                        );
                                      },
                                    ),
                                }
                              ];
                            },
                            error: (error, stackTrace) => [],
                            loading: () => [])
                      ],
                    ),
                  ),
                  Positioned.fill(
                    child: ShadContextMenuRegion(
                      children: [
                        ShadContextMenuItem(
                          leading: const ShadImage.square(LucideIcons.plus,
                              size: 16),
                          child: const Text('Create Report'),
                          onPressed: () {
                            context.router.push(
                              CreateReportRoute(
                                onDone: (BuildContext innerRontext) async {
                                  await innerRontext.router.maybePop();
                                  if (context.mounted) {
                                    toastification.show(
                                      context: context,
                                      title: const Text(
                                          'Report created successfully'),
                                      autoCloseDuration:
                                          const Duration(seconds: 3),
                                      type: ToastificationType.success,
                                    );

                                    ref
                                        .read(reportListControllerProvider
                                            .notifier)
                                        .search(
                                          queries: ref
                                              .read(_queriesProvider)
                                              .values
                                              .toList(),
                                        );
                                  }
                                },
                              ),
                            );
                          },
                        ),
                        ShadContextMenuItem.inset(
                          child: const Text(
                            'Refresh',
                          ),
                          onPressed: () {
                            ref.invalidate(reportListControllerProvider);
                          },
                        ),
                        ShadContextMenuItem.inset(
                          child: const Text(
                            'Advanced Filter',
                          ),
                          onPressed: () {
                            _FiltersSection.showFilterModal(context,
                                ref: ref, breakpoints: breakpoints);
                          },
                        ),
                      ],
                      child: SizedBox.shrink(),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
        floatingActionButton: userMetadata.role != RoleType.watcher &&
                breakpoints.between(MOBILE, TABLET)
            ? FloatingActionButton(
                tooltip: 'New Report',
                onPressed: () {
                  context.router.push(
                    CreateReportRoute(
                      onDone: (BuildContext innerRontext) async {
                        await innerRontext.router.maybePop();
                        if (context.mounted) {
                          toastification.show(
                            context: context,
                            title: const Text('Report created successfully'),
                            autoCloseDuration: const Duration(seconds: 3),
                            type: ToastificationType.success,
                          );

                          ref
                              .read(reportListControllerProvider.notifier)
                              .search(
                                queries:
                                    ref.read(_queriesProvider).values.toList(),
                              );
                        }
                      },
                    ),
                  );
                },
                child: const Icon(Icons.add),
              )
            : null,
      ),
    );
As you can see in that code I used Stack so that I can so I that the context menu be only place on specific widget. But it still occurs
moshOntong-IT commented 1 month ago

Can you share the stack trace and the error?

════════ Exception caught by gesture library ═══════════════════════════════════
The following assertion was thrown while dispatching a pointer event:
'package:flutter/src/gestures/events.dart': Failed assertion: line 1174 pos 15: '!identical(kind, PointerDeviceKind.trackpad)': is not true.

When the exception was thrown, this was the stack:
#2      new PointerEnterEvent (package:flutter/src/gestures/events.dart:1174:15)
events.dart:1174
#3      MouseAreaSurfaceRenderBox.handleEvent (package:shadcn_ui/src/utils/mouse_area.dart:124:9)
mouse_area.dart:124
#4      GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:481:22)
binding.dart:481
#5      RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:450:11)
binding.dart:450
#6      GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:426:7)
binding.dart:426
#7      GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:389:5)
binding.dart:389
#8      GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:336:7)
binding.dart:336
#9      GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:305:9)
binding.dart:305
#10     _invoke1 (dart:ui/hooks.dart:328:13)
hooks.dart:328
#11     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:442:7)
platform_dispatcher.dart:442
#12     _dispatchPointerDataPacket (dart:ui/hooks.dart:262:31)
hooks.dart:262
(elided 2 frames from class _AssertionError)

Event: PointerPanZoomStartEvent#7075d(position: Offset(686.4, 427.2))
    position: Offset(686.4, 427.2)
Target: MouseAreaSurfaceRenderBox#d2569
    needs compositing
    parentData: <none>
    constraints: BoxConstraints(w=1265.6, h=682.4)
    size: Size(1265.6, 682.4)
    behavior: deferToChild
════════════════════════════════════════════════════════════════════════════════
nank1ro commented 1 month ago

Fixed in the v0.9.7

moshOntong-IT commented 1 month ago

Fixed in the v0.9.7

I loved to know what is the cause of this bug?

nank1ro commented 1 month ago

This assert present in the Flutter framework. https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/gestures/events.dart#L1174-L1177

This means that affected only debug mode.