diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6ac46fb0d..cee57edc7 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -28,7 +28,7 @@ jobs: # using flutter - uses: subosito/flutter-action@v2 with: - channel: 'stable' + flutter-version: '3.38.10' - run: dart --version - run: flutter --version - run: flutter pub get diff --git a/.gitignore b/.gitignore index b0407d4e1..4906da0e1 100644 --- a/.gitignore +++ b/.gitignore @@ -77,4 +77,11 @@ coverage/ !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages # FVM Support - https://fvm.app/ -.fvm/flutter_sdk \ No newline at end of file + +# FVM Version Cache +.fvm/ +.fvmrc + + +.claude/ +.vscode \ No newline at end of file diff --git a/demo/ios/Flutter/ephemeral/flutter_lldb_helper.py b/demo/ios/Flutter/ephemeral/flutter_lldb_helper.py new file mode 100644 index 000000000..a88caf99d --- /dev/null +++ b/demo/ios/Flutter/ephemeral/flutter_lldb_helper.py @@ -0,0 +1,32 @@ +# +# Generated file, do not edit. +# + +import lldb + +def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict): + """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages.""" + base = frame.register["x0"].GetValueAsAddress() + page_len = frame.register["x1"].GetValueAsUnsigned() + + # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the + # first page to see if handled it correctly. This makes diagnosing + # misconfiguration (e.g. missing breakpoint) easier. + data = bytearray(page_len) + data[0:8] = b'IHELPED!' + + error = lldb.SBError() + frame.GetThread().GetProcess().WriteMemory(base, data, error) + if not error.Success(): + print(f'Failed to write into {base}[+{page_len}]', error) + return + +def __lldb_init_module(debugger: lldb.SBDebugger, _): + target = debugger.GetDummyTarget() + # Caveat: must use BreakpointCreateByRegEx here and not + # BreakpointCreateByName. For some reasons callback function does not + # get carried over from dummy target for the later. + bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$") + bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__)) + bp.SetAutoContinue(True) + print("-- LLDB integration loaded --") diff --git a/demo/ios/Flutter/ephemeral/flutter_lldbinit b/demo/ios/Flutter/ephemeral/flutter_lldbinit new file mode 100644 index 000000000..e3ba6fbed --- /dev/null +++ b/demo/ios/Flutter/ephemeral/flutter_lldbinit @@ -0,0 +1,5 @@ +# +# Generated file, do not edit. +# + +command script import --relative-to-command-file flutter_lldb_helper.py diff --git a/demo/lib/screen/development_screen.dart b/demo/lib/screen/development_screen.dart index 2f4ef47df..f590b05b2 100644 --- a/demo/lib/screen/development_screen.dart +++ b/demo/lib/screen/development_screen.dart @@ -1,4 +1,4 @@ -import 'package:faker/faker.dart'; +import 'package:faker/faker.dart' hide Color, Image; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:pluto_grid/pluto_grid.dart'; @@ -95,9 +95,9 @@ class _DevelopmentScreenState extends State { ), // localeText: const PlutoGridLocaleText.korean(), columnFilter: PlutoGridColumnFilterConfig( - filters: const [ + filters: [ ...FilterHelper.defaultFilters, - ClassYouImplemented(), + const ClassYouImplemented(), ], resolveDefaultColumnFilter: (column, resolver) { if (column.field == 'column3') { diff --git a/demo/lib/screen/feature/add_and_remove_column_row_screen.dart b/demo/lib/screen/feature/add_and_remove_column_row_screen.dart index 152fbbc52..603a07bbc 100644 --- a/demo/lib/screen/feature/add_and_remove_column_row_screen.dart +++ b/demo/lib/screen/feature/add_and_remove_column_row_screen.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:faker/faker.dart'; +import 'package:faker/faker.dart' hide Color; import 'package:flutter/material.dart'; import 'package:pluto_grid/pluto_grid.dart'; diff --git a/demo/pubspec.yaml b/demo/pubspec.yaml index 1353d10e3..77fe01d95 100644 --- a/demo/pubspec.yaml +++ b/demo/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.17.0 <3.0.0" + sdk: ">=3.9.0 <4.0.0" dependencies: flutter: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 87755ebe2..fd63a2e9c 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.17.0 <3.0.0" + sdk: ">=3.9.0 <4.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions diff --git a/lib/src/helper/pluto_size_helper.dart b/lib/src/helper/pluto_size_helper.dart index 915a830ee..4b88542e1 100644 --- a/lib/src/helper/pluto_size_helper.dart +++ b/lib/src/helper/pluto_size_helper.dart @@ -161,8 +161,6 @@ class PlutoAutoSizeScale extends PlutoAutoSize { @override void update() { - final length = items.length; - double effectiveMaxSize = maxSize; double totalWidth = items.fold(0, (p, e) => p += getItemSize(e)); @@ -189,17 +187,39 @@ class PlutoAutoSizeScale extends PlutoAutoSize { scale = effectiveMaxSize / totalWidth; } - for (int i = 0; i < length; i += 1) { - final item = items.elementAt(i); + double currentTotal = 0; + T? lastResizableItem; - if (isSuppressedItem(item)) continue; + for (final item in items) { + if (isSuppressedItem(item)) { + currentTotal += getItemSize(item); + continue; + } final minSize = getItemMinSize(item); - - final size = max(minSize, getItemSize(item) * scale + 1); + final size = max(minSize, getItemSize(item) * scale); setItemSize(item, size); + currentTotal += size; + lastResizableItem = item; } + + if (lastResizableItem == null) { + return; + } + + final remaining = maxSize - currentTotal; + + if (remaining == 0) { + return; + } + + final currentLastSize = getItemSize(lastResizableItem); + final minLastSize = getItemMinSize(lastResizableItem); + setItemSize( + lastResizableItem, + max(minLastSize, currentLastSize + remaining), + ); } } diff --git a/lib/src/manager/pluto_grid_event_manager.dart b/lib/src/manager/pluto_grid_event_manager.dart index f448fd7a5..d3c1c67e4 100644 --- a/lib/src/manager/pluto_grid_event_manager.dart +++ b/lib/src/manager/pluto_grid_event_manager.dart @@ -32,7 +32,8 @@ class PlutoGridEventManager { .where((event) => event.type.isThrottleLeading) .transform( ThrottleStreamTransformer( - (_) => TimerStream(_, _.duration as Duration), + (PlutoGridEvent event) => + TimerStream(event, event.duration as Duration), trailing: false, leading: true, ), @@ -42,7 +43,8 @@ class PlutoGridEventManager { .where((event) => event.type.isThrottleTrailing) .transform( ThrottleStreamTransformer( - (_) => TimerStream(_, _.duration as Duration), + (PlutoGridEvent event) => + TimerStream(event, event.duration as Duration), trailing: true, leading: false, ), @@ -51,7 +53,8 @@ class PlutoGridEventManager { final debounceStream = _subject.stream.where((event) => event.type.isDebounce).transform( DebounceStreamTransformer( - (_) => TimerStream(_, _.duration as Duration), + (PlutoGridEvent event) => + TimerStream(event, event.duration as Duration), ), ); diff --git a/lib/src/manager/pluto_grid_key_manager.dart b/lib/src/manager/pluto_grid_key_manager.dart index 52a6a2e79..c782c831b 100644 --- a/lib/src/manager/pluto_grid_key_manager.dart +++ b/lib/src/manager/pluto_grid_key_manager.dart @@ -66,7 +66,8 @@ class PlutoGridKeyManager { final movingStream = _subject.stream.where((event) => event.needsThrottle).transform( ThrottleStreamTransformer( - (_) => TimerStream(_, const Duration(milliseconds: 1)), + (PlutoKeyManagerEvent keyEvent) => + TimerStream(keyEvent, const Duration(milliseconds: 1)), ), ); diff --git a/lib/src/pluto_grid_configuration.dart b/lib/src/pluto_grid_configuration.dart index ab3689a75..cfbd4536f 100644 --- a/lib/src/pluto_grid_configuration.dart +++ b/lib/src/pluto_grid_configuration.dart @@ -859,7 +859,7 @@ class PlutoGridColumnFilterConfig { final int _debounceMilliseconds; - bool get hasUserFilter => _userFilters != null && _userFilters!.isNotEmpty; + bool get hasUserFilter => _userFilters != null && _userFilters.isNotEmpty; List get filters => hasUserFilter ? _userFilters! : FilterHelper.defaultFilters; @@ -878,7 +878,7 @@ class PlutoGridColumnFilterConfig { return filters.first; } - var resolvedFilter = _userResolveDefaultColumnFilter!(column, resolver); + var resolvedFilter = _userResolveDefaultColumnFilter(column, resolver); assert(filters.contains(resolvedFilter)); diff --git a/packages/pluto_grid_export/example/macos/Flutter/GeneratedPluginRegistrant.swift b/packages/pluto_grid_export/example/macos/Flutter/GeneratedPluginRegistrant.swift index 9c4efdd9c..13e7edec9 100644 --- a/packages/pluto_grid_export/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/packages/pluto_grid_export/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,11 +6,9 @@ import FlutterMacOS import Foundation import file_saver -import path_provider_foundation import printing func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin")) } diff --git a/pubspec.yaml b/pubspec.yaml index 1f385d133..3bd64841d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,8 +5,8 @@ homepage: https://pluto.weblaze.dev repository: https://github.com/bosskmk/pluto_grid environment: - sdk: '>=2.17.0 <4.0.0' - flutter: ">=2.5.0" + sdk: '>=3.9.0 <4.0.0' + flutter: ">=3.38.10" dependencies: flutter: diff --git a/test/src/helper/pluto_size_helper_test.dart b/test/src/helper/pluto_size_helper_test.dart index 4a3d1b055..8991852fd 100644 --- a/test/src/helper/pluto_size_helper_test.dart +++ b/test/src/helper/pluto_size_helper_test.dart @@ -146,11 +146,11 @@ void main() { mode: mode, ).update(); - expect(items[0].size, 100 * scale + 1); - expect(items[1].size, 200 * scale + 1); - expect(items[2].size, 200 * scale + 1); - expect(items[3].size, 100 * scale + 1); - expect(items[4].size, 100 * scale + 1); + expect(items[0].size, 100 * scale); + expect(items[1].size, 200 * scale); + expect(items[2].size, 200 * scale); + expect(items[3].size, 100 * scale); + expect(items[4].size, 100 * scale); }); test( @@ -203,12 +203,33 @@ void main() { mode: mode, ).update(); - expect(items[0].size, 100 * scale + 1); + expect(items[0].size, 100 * scale); expect(items[1].size, 120); - expect(items[2].size, 130 * scale + 1); + expect(items[2].size, 130 * scale); expect(items[3].size, 140); expect(items[4].size, 150); }); + + test('리사이즈 이후 전체 합은 maxSize 와 같아야 한다.', () { + final items = [ + _ResizeItem(index: 0, size: 130, minSize: 50), + _ResizeItem(index: 1, size: 220, minSize: 50), + _ResizeItem(index: 2, size: 90, minSize: 50), + ]; + + PlutoAutoSizeHelper.items<_ResizeItem>( + maxSize: 500, + items: items, + isSuppressed: (i) => i.suppressed, + getItemSize: (i) => i.size, + getItemMinSize: (i) => i.minSize, + setItemSize: (i, size) => i.size = size, + mode: mode, + ).update(); + + final total = items.fold(0, (p, e) => p + e.size); + expect(total, 500); + }); }); });