From ede9c0d7664246f5832f1658a186bf7b616417b7 Mon Sep 17 00:00:00 2001 From: Robert Santucci Date: Thu, 1 Oct 2026 13:37:02 -0500 Subject: [PATCH 1/6] StandardApp: optional selectable flag for the app-wide SelectionArea --- lib/src/app_scaffold.dart | 12 +++++++++++- test/widget/app_scaffold_test.dart | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/src/app_scaffold.dart b/lib/src/app_scaffold.dart index d936576..b2a77a7 100644 --- a/lib/src/app_scaffold.dart +++ b/lib/src/app_scaffold.dart @@ -407,6 +407,13 @@ final class StandardApp extends StatelessWidget { /// is set up and the drawer will show "No login required". final AuthInfo? authInfo; + /// Whether the app's text can be selected with the mouse (the default). + /// + /// When `true` the whole app sits in a [SelectionArea], so every [Text] + /// registers as selectable. Apps whose text changes many times a second + /// (live readings) can pass `false` to skip that work. + final bool selectable; + StandardApp({ required this.title, this.model, @@ -419,6 +426,7 @@ final class StandardApp extends StatelessWidget { List? neededRoles, this.themeMode = ThemeMode.system, this.useBison = false, + this.selectable = true, super.key, }) : _neededRoles = neededRoles?.toSet() ?? {}; @@ -469,7 +477,9 @@ final class StandardApp extends StatelessWidget { theme: theme.light, darkTheme: theme.dark, themeMode: themeMode, - home: ToastificationWrapper(child: SelectionArea(child: scaffold)), + home: ToastificationWrapper( + child: selectable ? SelectionArea(child: scaffold) : scaffold, + ), ); } } diff --git a/test/widget/app_scaffold_test.dart b/test/widget/app_scaffold_test.dart index 73d16d3..e1a63de 100644 --- a/test/widget/app_scaffold_test.dart +++ b/test/widget/app_scaffold_test.dart @@ -119,4 +119,21 @@ void main() { expect(find.text('no-model'), findsOneWidget); }); }); + + group('StandardApp text selection', () { + testWidgets('text is selectable by default', (tester) async { + await tester.pumpWidget(StandardApp(title: 'T', body: const Text('x'))); + expect(find.byType(SelectionArea), findsOneWidget); + }); + + testWidgets('selectable: false leaves out the SelectionArea', ( + tester, + ) async { + await tester.pumpWidget( + StandardApp(title: 'T', selectable: false, body: const Text('x')), + ); + expect(find.byType(SelectionArea), findsNothing); + expect(find.text('x'), findsOneWidget); + }); + }); } From 00a95f0996e92ca4ce9022ccc05dd5080c13630d Mon Sep 17 00:00:00 2001 From: Robert Santucci Date: Thu, 1 Oct 2026 13:39:35 -0500 Subject: [PATCH 2/6] Drop the selectable doc comment --- lib/src/app_scaffold.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/src/app_scaffold.dart b/lib/src/app_scaffold.dart index b2a77a7..906704c 100644 --- a/lib/src/app_scaffold.dart +++ b/lib/src/app_scaffold.dart @@ -407,11 +407,6 @@ final class StandardApp extends StatelessWidget { /// is set up and the drawer will show "No login required". final AuthInfo? authInfo; - /// Whether the app's text can be selected with the mouse (the default). - /// - /// When `true` the whole app sits in a [SelectionArea], so every [Text] - /// registers as selectable. Apps whose text changes many times a second - /// (live readings) can pass `false` to skip that work. final bool selectable; StandardApp({ From f6bdc4c8d4a968796c601203c9ee34f145b4d215 Mon Sep 17 00:00:00 2001 From: Rich Neswold Date: Fri, 9 Oct 2026 12:39:42 -0500 Subject: [PATCH 3/6] Change selectable property to false Selecting the entire app has an impact on performance. We shut it off, by default. A developer can choose to enable it for their app. --- lib/src/app_scaffold.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/app_scaffold.dart b/lib/src/app_scaffold.dart index 906704c..e4d6dc7 100644 --- a/lib/src/app_scaffold.dart +++ b/lib/src/app_scaffold.dart @@ -421,7 +421,7 @@ final class StandardApp extends StatelessWidget { List? neededRoles, this.themeMode = ThemeMode.system, this.useBison = false, - this.selectable = true, + this.selectable = false, super.key, }) : _neededRoles = neededRoles?.toSet() ?? {}; From 9fbe9fd919bc09da403cc48fddaa1cbfd4551246 Mon Sep 17 00:00:00 2001 From: Rich Neswold Date: Fri, 9 Oct 2026 13:01:08 -0500 Subject: [PATCH 4/6] Modify SelectionArea tests for StandardApp Updated tests to reflect changes in SelectionArea behavior based on selectable property. --- test/widget/app_scaffold_test.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/widget/app_scaffold_test.dart b/test/widget/app_scaffold_test.dart index e1a63de..ef07723 100644 --- a/test/widget/app_scaffold_test.dart +++ b/test/widget/app_scaffold_test.dart @@ -123,7 +123,7 @@ void main() { group('StandardApp text selection', () { testWidgets('text is selectable by default', (tester) async { await tester.pumpWidget(StandardApp(title: 'T', body: const Text('x'))); - expect(find.byType(SelectionArea), findsOneWidget); + expect(find.byType(SelectionArea), findsNothing); }); testWidgets('selectable: false leaves out the SelectionArea', ( @@ -135,5 +135,15 @@ void main() { expect(find.byType(SelectionArea), findsNothing); expect(find.text('x'), findsOneWidget); }); + + testWidgets('selectable: true adds the SelectionArea', ( + tester, + ) async { + await tester.pumpWidget( + StandardApp(title: 'T', selectable: true, body: const Text('x')), + ); + expect(find.byType(SelectionArea), findsOneWidget); + expect(find.text('x'), findsOneWidget); + }); }); } From 5812db768c56b8d6b536d9ec6f03b7af2904f49f Mon Sep 17 00:00:00 2001 From: Rich Neswold Date: Fri, 9 Oct 2026 13:14:37 -0500 Subject: [PATCH 5/6] Bump version from 1.4.0 to 1.4.1 Bump version number so dependents can use SemVer to update. --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 74cdc35..f398bd6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_controls_core description: A Flutter package to write Fermilab applications. -version: 1.4.0 +version: 1.4.1 publish_to: none environment: From e0daf97cde70fb6a4c9806b0d9db80d497861aa3 Mon Sep 17 00:00:00 2001 From: Rich Neswold Date: Fri, 9 Oct 2026 13:20:21 -0500 Subject: [PATCH 6/6] Update flutter_controls_core version to 1.4.0 Update the docs to use the SemVer-compatible syntax in `pubspec.yaml`. --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8ece59c..2ff6e00 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ flutter_controls_core: git: url: https://github.com/fermi-ad/flutter-controls-core.git tag_pattern: v{{version}} - version: ^1.3.0 + version: ^1.4.0 ``` _NOTE:_ This project is under very active development so calling this the @@ -54,12 +54,14 @@ dependencies: flutter_gql_acsys: git: url: https://github.com/fermi-ad/flutter-gql-acsys.git - ref: main + tag_pattern: v{{version}} + version: ^1.1.0 flutter_controls_core: git: url: https://github.com/fermi-ad/flutter-controls-core.git - ref: main + tag_pattern: v{{version}} + version: ^1.4.0 ``` and where your application constructs the `StandardApp`, you specify the