caduandrade / davi_flutter

A full customized data view that builds the cells on demand. Focused on Web/Desktop Applications. Bidirectional scroll bars.
MIT License
58 stars 18 forks source link

[Flutter 3.3.0+] Scrolling does not work with a trackpad on macOS #50

Open Sesa1988 opened 2 years ago

Sesa1988 commented 2 years ago

Hi,

after the update to Flutter 3.3.0 the table keeps freezing when multiple entries are in and Im scrolling. I think they changed internally how scrolling works and maybe thats part of the issue.

I tested it on macOS via trackpad and not sure if this happens as well on Android, iOS, Windows or web.

Current behaviour Table is not scrollable

Expected behaviour Table will scroll

caduandrade commented 2 years ago

Hi @Sesa1988 ! Thanks for the issue.

I just tested it on the web and apparently everything is OK.

Now I have a problem. I don't have macOS to test :cry:. Can I borrow yours? :smile: . I'll see what I can do.

Sesa1988 commented 2 years ago

Hi @Sesa1988 ! Thanks for the issue.

I just tested it on the web and apparently everything is OK.

Now I have a problem. I don't have macOS to test 😢. Can I borrow yours? 😄 . I'll see what I can do.

I think it has something to do with the scroll bouncing effect that is now default on macOS after upgrading flutter to 3.3.4. Instead of bouncing it freezes and is not scrollable anymore.

Sesa1988 commented 1 year ago

Hi @caduandrade

I try to scroll all the time via trackpad and at some point it scrolls but blocks the scrolling for the most part. Sometimes the bounce effect is visible when you reach the end it freezes before that.

https://user-images.githubusercontent.com/26410357/194782543-b67a993e-ef14-4287-a107-f9ceb8fc60ce.mov

Sesa1988 commented 1 year ago

The example above was actually on the 1.5.1 version. I tested it with the latest version and I can't scroll at all there. I see the scrollbar, can move it manually with dragging but I can't scroll via trackpad.

I have a footer and the table is above but even just with the table its not scrollable via trackpad.

return Column(
      mainAxisSize: MainAxisSize.max,
      children: [
        Expanded(child: _getTable(context)),
        if (maxCount > pageSize)
          SizedBox(child: _getFooter(context), height: 50),
      ],
    );
_getTable ``` EasyTableTheme _getTable(BuildContext context) { var configuration = _getConfiguration(context); var theme = Theme.of(context); var dividerColor = theme.dividerColor; var backgroundColor = theme.scaffoldBackgroundColor; return EasyTableTheme( child: EasyTable( configuration, columnsFit: true, onRowTap: (row) => _openMenu(context, row, _cryptoBalance), onRowSecondaryTap: (row) => _openMenu(context, row, _cryptoBalance), ), data: EasyTableThemeData( columnDividerThickness: 0.5, columnDividerColor: dividerColor, bottomCornerColor: backgroundColor, bottomCornerBorderColor: backgroundColor, topCornerColor: backgroundColor, topCornerBorderColor: backgroundColor, scrollbar: TableScrollbarThemeData( verticalBorderColor: backgroundColor, verticalColor: backgroundColor, unpinnedHorizontalColor: backgroundColor, pinnedHorizontalColor: backgroundColor, unpinnedHorizontalBorderColor: backgroundColor, pinnedHorizontalBorderColor: backgroundColor, thickness: 10, ), row: RowThemeData( dividerColor: dividerColor, hoverBackground: (_) => Theme.of(context).cardColor, dividerThickness: 0.5, ), cell: const CellThemeData(padding: EdgeInsets.all(8)), header: HeaderThemeData( columnDividerColor: dividerColor, bottomBorderColor: dividerColor, bottomBorderHeight: 0.5, ), headerCell: const HeaderCellThemeData(alignment: Alignment.center, height: 60), decoration: BoxDecoration( border: Border( bottom: BorderSide(color: dividerColor, width: 0.5), top: BorderSide(color: dividerColor, width: 0.5), left: BorderSide(color: dividerColor, width: 0.5), right: BorderSide(color: dividerColor, width: 0.5), ), boxShadow: const [], ), ), ); } ```
_getConfiguration ``` EasyTableModel? _getConfiguration(BuildContext context) { return EasyTableModel( rows: [...this._openPositions], columns: [ EasyTableColumn( weight: 1, name: '', resizable: false, cellBuilder: (context, position) => Center( child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Tooltip( message: AppLocalizations.of(context) .translate(position.row.type == PositionTypeEnum.bought ? 'bought' : position.row.type == PositionTypeEnum.sold ? 'sold' : 'error'), child: Icon( position.row.type == PositionTypeEnum.bought ? Icons.keyboard_arrow_right : position.row.type == PositionTypeEnum.sold ? Icons.keyboard_arrow_left : Icons.error, color: position.row.type == PositionTypeEnum.bought ? const Color(0xff66c97f) : position.row.type == PositionTypeEnum.sold ? Colors.red : Colors.black, size: 24.0, ), ), ], ), ), ), EasyTableColumn( name: AppLocalizations.of(context).translate('date'), weight: 2, resizable: false, cellBuilder: (context, position) => Center( child: Text( DateFormat.yMd(Platform.localeName).format( DateTime.fromMillisecondsSinceEpoch(position.row.createdAt) .toLocal()), style: Theme.of(context).textTheme.bodyText2, ), ), ), EasyTableColumn( name: AppLocalizations.of(context).translate('current_value'), weight: 2, resizable: false, cellBuilder: (context, position) => Center( child: position.row.type == PositionTypeEnum.sold ? const Text('-') : PositionTrendWrapperDesktop( position.row, _cryptoBalance.assetId), ), ), EasyTableColumn( name: AppLocalizations.of(context).translate('%_change'), weight: 2, resizable: false, cellBuilder: (context, position) => Center( child: position.row.type == PositionTypeEnum.sold ? const Text('-') : PositionPercentageGainsDesktop( position.row, _cryptoBalance.assetId), ), ), EasyTableColumn( name: AppLocalizations.of(context).translate('change'), weight: 2, resizable: false, cellBuilder: (context, position) => Center( child: position.row.type == PositionTypeEnum.sold ? const Text('-') : PositionFiatGainsDesktop( position.row, _cryptoBalance.assetId), ), ), EasyTableColumn( name: AppLocalizations.of(context).translate('in_out'), weight: 2, resizable: false, cellBuilder: (context, position) => Center( child: DepositCardAreaDeposit(position.row), ), ), EasyTableColumn( name: AppLocalizations.of(context).translate('amount'), weight: 2, resizable: false, cellBuilder: (context, position) => Center( child: DepositCoinAmountDesktop(position.row), ), ), EasyTableColumn( name: AppLocalizations.of(context).translate('unit_price'), weight: 2, resizable: false, cellBuilder: (context, position) => Center( child: DepositCoinPriceDesktop(position.row), ), ), ], ); } ```

https://user-images.githubusercontent.com/26410357/198150900-48dcdf3c-8e2c-4df5-a5e1-c33a082ae016.mov

I noticed also that if I wrap the table with a ScrollConfiguration also dragging with pressing down on the trackpad does not work as well. Hope this helps for reproduction :)

return Column(
      mainAxisSize: MainAxisSize.max,
      children: [
        Expanded(
          child: ScrollConfiguration(
            child: _getTable(context),
            behavior: ScrollConfiguration.of(context).copyWith(
              dragDevices: {
                PointerDeviceKind.mouse,
                PointerDeviceKind.touch,
                PointerDeviceKind.trackpad,
              },
            ),
          ),
        ),
        if (maxCount > pageSize)
          SizedBox(child: _getFooter(context), height: 50),
      ],
    );
caduandrade commented 1 year ago

Hi @Sesa1988!

As I don't have a mac, would it be possible for you to test a code for me to see if it solves the problem? You will need to clone the repo from here and change the lib/src/internal/table_scrollbar.dart file.

Find for ScrollConfiguration and add the dragDevices:

ScrollConfiguration(
                    behavior: ScrollConfiguration.of(context)
                        .copyWith(scrollbars: false,
                        dragDevices: {
                          PointerDeviceKind.touch,
                          PointerDeviceKind.mouse,
                          PointerDeviceKind.invertedStylus,
                          PointerDeviceKind.trackpad
                        }),

After this, go to your project and change the pubspec.yaml to use an path to your the easy_table, example:

  easy_table: 
    path: /cadu/easy_table_flutter
Sesa1988 commented 1 year ago

Hi @caduandrade

That's no problem, I'll test it in the next few days or next week.

Sesa1988 commented 1 year ago

Hi @Sesa1988!

As I don't have a mac, would it be possible for you to test a code for me to see if it solves the problem? You will need to clone the repo from here and change the lib/src/internal/table_scrollbar.dart file.

Find for ScrollConfiguration and add the dragDevices:

ScrollConfiguration(
                    behavior: ScrollConfiguration.of(context)
                        .copyWith(scrollbars: false,
                        dragDevices: {
                          PointerDeviceKind.touch,
                          PointerDeviceKind.mouse,
                          PointerDeviceKind.invertedStylus,
                          PointerDeviceKind.trackpad
                        }),

After this, go to your project and change the pubspec.yaml to use an path to your the easy_table, example:

  easy_table: 
    path: /cadu/easy_table_flutter

Hi @caduandrade

I tested it and it does not fix the issue but I also tested your example application and the same issue is present there.

launch.json

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "example debug",
            "cwd": "example",
            "request": "launch",
            "type": "dart",
            "flutterMode": "debug",
            "args": [
                "-d",
                "macos",
            ]
        },
    ]
}

I added also the platform an android but this don't helped as well.

table_scrollbar ``` import 'package:easy_table/src/theme/scrollbar_theme_data.dart'; import 'package:easy_table/src/theme/theme.dart'; import 'package:easy_table/src/theme/theme_data.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; @internal class TableScrollbar extends StatelessWidget { const TableScrollbar( {Key? key, required this.contentSize, required this.scrollController, required this.axis, required this.color, required this.borderColor, required this.onDragScroll}) : super(key: key); final double contentSize; final ScrollController scrollController; final Axis axis; final Color color; final Color borderColor; final OnDragScroll onDragScroll; @override Widget build(BuildContext context) { EasyTableThemeData theme = EasyTableTheme.of(context); TableScrollbarThemeData scrollTheme = theme.scrollbar; BoxBorder? border; if (theme.scrollbar.borderThickness > 0) { if (axis == Axis.horizontal) { border = Border( top: BorderSide( color: borderColor, width: theme.scrollbar.borderThickness)); } else if (axis == Axis.vertical) { border = Border( left: BorderSide( color: borderColor, width: theme.scrollbar.borderThickness)); } } Widget scrollbar = Container( decoration: BoxDecoration(color: color, border: border), child: Theme( data: ThemeData( scrollbarTheme: ScrollbarThemeData( crossAxisMargin: scrollTheme.margin, thumbColor: MaterialStateProperty.all(scrollTheme.thumbColor))), child: Scrollbar( controller: scrollController, thickness: scrollTheme.thickness, radius: scrollTheme.radius, thumbVisibility: true, child: ScrollConfiguration( behavior: ScrollConfiguration.of(context).copyWith( scrollbars: false, dragDevices: { PointerDeviceKind.touch, PointerDeviceKind.mouse, PointerDeviceKind.invertedStylus, PointerDeviceKind.trackpad, PointerDeviceKind.unknown, }, platform: TargetPlatform.android, ), child: SingleChildScrollView( controller: scrollController, scrollDirection: axis, child: _sizedBox(), ), ), ), ), ); return Listener( onPointerDown: (event) => onDragScroll(true), onPointerUp: (event) => onDragScroll(false), child: scrollbar); } Widget _sizedBox() { if (axis == Axis.vertical) { return SizedBox(height: contentSize); } return SizedBox(width: contentSize); } } typedef OnDragScroll = void Function(bool start); ```

https://user-images.githubusercontent.com/26410357/199325873-93524625-91d4-4e76-a436-4e2e99f5bc2e.mov

Could you open a bug on the flutter repository with your repository? Your example application is great with that.

caduandrade commented 1 year ago

Hi @Sesa1988 !

Could you make one more attempt? Just checkout the bugfix/50-scrolling-trackpad branch and test.

Sesa1988 commented 1 year ago

Hi @Sesa1988 !

Could you make one more attempt? Just checkout the bugfix/50-scrolling-trackpad branch and test.

I tested the example application on your bugfix branch and its the same issue.

Sesa1988 commented 1 year ago

Hi @Sesa1988 !

Could you make one more attempt? Just checkout the bugfix/50-scrolling-trackpad branch and test.

Im not sure this could be related. https://github.com/flutter/flutter/issues/114889

caduandrade commented 1 year ago

I think so. :-(

Sesa1988 commented 1 year ago

I think so. :-(

I opened a bug and someone mentioned this solution. I tested it and this works but Im not sure if this is enough for your feature set but maybe it's enough for a right direction. (https://github.com/flutter/flutter/issues/115428#issuecomment-1317338914)

onPointerPanZoomUpdate: (e) {
          if (e.panDelta.dy != 0) {
            _scrollControllers.vertical.position.pointerScroll(-e.panDelta.dy);
          }
        },

your previously called _onScroll(pointerSignal.scrollDelta.dy, themeMetrics.row.height); but Im not sure what's the difference there but you know better then me :)

caduandrade commented 1 year ago

Hi @Sesa1988 ! If it's working for you, that's ok. Is it possible for you to make a merge request? But attention because I did a merge today. Please update your code first. Use the main branch.

Sesa1988 commented 1 year ago

Hi @Sesa1988 ! If it's working for you, that's ok. Is it possible for you to make a merge request? But attention because I did a merge today. Please update your code first.

I think it would be easier for you to update. Im not sure if this solution is valid, I pasted it in and it worked.

In your fix branch you added this event already just with another implementation.

caduandrade commented 1 year ago

@Sesa1988 , you made this change in _EasyTableState of table.dart right?

Sesa1988 commented 1 year ago

@Sesa1988 , you made this change in _EasyTableState of table.dart right?

Yes, around line 200 in table.dart

caduandrade commented 1 year ago

@Sesa1988 ,

I made a commit to the main branch. Can you test it? On web and linux desktop this event is not fired. I have no way to test. I just thought it was weird to use a negative value as if on macOS it was inverted...

If it's ok for you, I'll publish it as a patch.

Sesa1988 commented 1 year ago

@Sesa1988 ,

I made a commit to the main branch. Can you test it? On web and linux desktop this event is not fired. I have no way to test. I just thought it was weird to use a negative value as if on macOS it was inverted...

If it's ok for you, I'll publish it as a patch.

Yea thats weird but even the scroll-settings on macOS are weird so who knows :D

I will test it now.

Sesa1988 commented 1 year ago

@caduandrade It works, thats great! :)

caduandrade commented 1 year ago

@Sesa1988 , version 2.1.0 released! Thank you for your help!

Sesa1988 commented 1 year ago

@Sesa1988 , version 2.1.0 released! Thank you for your help!

I just noticed that there is no velocity, its scrolling but stops instantly.

Maybe this is now a smaller fix? @caduandrade