Skip to content

v1: patches + enhancements #5254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 29, 2025
22 changes: 11 additions & 11 deletions client/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,18 @@ void main([List<String>? args]) async {
appStartupScreenMessage: "Working...",
extensions: const [
// // --FAT_CLIENT_START--
// flet_audio.createControl,
// flet_video.createControl,
// flet_audio.Extension(),
// flet_video.Extension(),
// // --FAT_CLIENT_END--
// flet_audio_recorder.createControl,
// flet_geolocator.createControl,
// flet_permission_handler.createControl,
// flet_lottie.createControl,
// flet_map.createControl,
// flet_ads.createControl,
// flet_rive.createControl,
// flet_webview.createControl,
// flet_flashlight.createControl,
// flet_audio_recorder.Extension(),
// flet_geolocator.Extension(),
// flet_permission_handler.Extension(),
// flet_lottie.Extension(),
// flet_map.Extension(),
// flet_ads.Extension(),
// flet_rive.Extension(),
// flet_webview.Extension(),
// flet_flashlight.Extension(),
],
));
}
40 changes: 17 additions & 23 deletions packages/flet/lib/src/controls/button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
widget.control.getClipBehavior("clip_behavior", Clip.none)!;
var autofocus = widget.control.getBool("autofocus", false)!;

Widget? iconWidget =
widget.control.buildIconOrWidget("icon", color: iconColor);

var icon = widget.control.buildIconOrWidget("icon", color: iconColor);
var content = widget.control.buildTextOrWidget("content");

Function()? onPressed = !widget.control.disabled
? () {
Expand Down Expand Up @@ -109,7 +108,7 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
Widget error = const ErrorControl("Error displaying Button",
description: "\"icon\" must be specified together with \"content\"");

if (iconWidget != null) {
if (icon != null) {
if (isFilledButton) {
button = FilledButton.icon(
style: style,
Expand All @@ -119,9 +118,8 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onLongPress: onLongPressHandler,
onHover: onHoverHandler,
clipBehavior: clipBehavior,
icon: iconWidget,
label: widget.control.buildTextOrWidget("content",
required: true, errorWidget: error)!);
icon: icon,
label: content ?? error);
} else if (isFilledTonalButton) {
button = FilledButton.tonalIcon(
style: style,
Expand All @@ -131,9 +129,8 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onLongPress: onLongPressHandler,
onHover: onHoverHandler,
clipBehavior: clipBehavior,
icon: iconWidget,
label: widget.control.buildTextOrWidget("content",
required: true, errorWidget: error)!);
icon: icon,
label: content ?? error);
} else if (isTextButton) {
button = TextButton.icon(
autofocus: autofocus,
Expand All @@ -143,9 +140,8 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onHover: onHoverHandler,
style: style,
clipBehavior: clipBehavior,
icon: iconWidget,
label: widget.control.buildTextOrWidget("content",
required: true, errorWidget: error)!,
icon: icon,
label: content ?? error,
);
} else if (isOutlinedButton) {
button = OutlinedButton.icon(
Expand All @@ -155,9 +151,8 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onLongPress: onLongPressHandler,
clipBehavior: clipBehavior,
style: style,
icon: iconWidget,
label: widget.control.buildTextOrWidget("content",
required: true, errorWidget: error)!);
icon: icon,
label: content ?? error);
} else {
button = ElevatedButton.icon(
style: style,
Expand All @@ -167,9 +162,8 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onLongPress: onLongPressHandler,
onHover: onHoverHandler,
clipBehavior: clipBehavior,
icon: iconWidget,
label: widget.control.buildTextOrWidget("content",
required: true, errorWidget: error)!);
icon: icon,
label: content ?? error);
}
} else {
if (isFilledButton) {
Expand All @@ -181,7 +175,7 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onLongPress: onLongPressHandler,
onHover: onHoverHandler,
clipBehavior: clipBehavior,
child: widget.control.buildTextOrWidget("content"));
child: content);
} else if (isFilledTonalButton) {
button = FilledButton.tonal(
style: style,
Expand All @@ -191,7 +185,7 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onLongPress: onLongPressHandler,
onHover: onHoverHandler,
clipBehavior: clipBehavior,
child: widget.control.buildTextOrWidget("content"));
child: content);
} else if (isTextButton) {
button = TextButton(
autofocus: autofocus,
Expand All @@ -212,7 +206,7 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
clipBehavior: clipBehavior,
onHover: onHoverHandler,
style: style,
child: widget.control.buildTextOrWidget("content"));
child: content);
} else {
button = ElevatedButton(
style: style,
Expand All @@ -222,7 +216,7 @@ class _ButtonControlState extends State<ButtonControl> with FletStoreMixin {
onLongPress: onLongPressHandler,
onHover: onHoverHandler,
clipBehavior: clipBehavior,
child: widget.control.buildTextOrWidget("content"));
child: content);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ class CupertinoActionSheetActionControl extends StatelessWidget {
var content = control.buildTextOrWidget("content");
if (content == null) {
return const ErrorControl(
"CupertinoActionSheetAction.content (string or visible Control) must be provided");
"CupertinoActionSheetAction.content must be a string or visible Control");
}

final actionSheet = CupertinoActionSheetAction(
isDefaultAction: control.getBool("is_default_action", false)!,
isDestructiveAction: control.getBool("is_destructive_action", false)!,
isDefaultAction: control.getBool("default", false)!,
isDestructiveAction: control.getBool("destructive", false)!,
onPressed: () {
if (!control.disabled) {
control.triggerEvent("click");
Expand Down
33 changes: 10 additions & 23 deletions packages/flet/lib/src/controls/cupertino_alert_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../flet_backend.dart';
import '../extensions/control.dart';
import '../models/control.dart';
import '../utils/animations.dart';
import '../utils/colors.dart';
import '../utils/numbers.dart';
import '../widgets/error.dart';
import 'control_widget.dart';

class CupertinoAlertDialogControl extends StatefulWidget {
final Control control;
Expand Down Expand Up @@ -49,12 +48,12 @@ class _CupertinoAlertDialogControlState
}

Widget _createCupertinoAlertDialog() {
var titleControl = widget.control.child("title");
var contentControl = widget.control.child("content");
var actionControls = widget.control.children("actions");
if (titleControl == null &&
contentControl == null &&
actionControls.isEmpty) {
var title = widget.control.buildTextOrWidget("title");
var content = widget.control.buildWidget("content");
var actions = widget.control.buildWidgets("actions");
if (title == null &&
content == null &&
actions.isEmpty) {
return const ErrorControl(
"CupertinoAlertDialog has nothing to display. Provide at minimum one of the following: title, content, actions");
}
Expand All @@ -67,21 +66,9 @@ class _CupertinoAlertDialogControlState
return CupertinoAlertDialog(
insetAnimationCurve: insetAnimation.curve,
insetAnimationDuration: insetAnimation.duration,
title: titleControl != null
? ControlWidget(
control: titleControl,
)
: null,
content: contentControl != null
? ControlWidget(
control: contentControl,
)
: null,
actions: actionControls
.map((actionControl) => ControlWidget(
control: actionControl,
))
.toList(),
title: title,
content: content,
actions: actions,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class CupertinoContextMenuActionControl extends StatelessWidget {
"content (string or visible Control) must be provided");
}
return CupertinoContextMenuAction(
isDefaultAction: control.getBool("is_default_action", false)!,
isDestructiveAction: control.getBool("is_destructive_action", false)!,
isDefaultAction: control.getBool("default", false)!,
isDestructiveAction: control.getBool("destructive", false)!,
onPressed: () {
if (!control.disabled) {
control.triggerEvent("click");
Expand Down
20 changes: 11 additions & 9 deletions packages/flet/lib/src/controls/cupertino_dialog_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import '../extensions/control.dart';
import '../models/control.dart';
import '../utils/numbers.dart';
import '../utils/text.dart';
import '../widgets/error.dart';
import 'base_controls.dart';

class CupertinoDialogActionControl extends StatelessWidget {
Expand All @@ -16,17 +17,18 @@ class CupertinoDialogActionControl extends StatelessWidget {
Widget build(BuildContext context) {
debugPrint("CupertinoDialogAction build: ${control.id}");

var content = control.buildTextOrWidget("content");
if (content == null) {
return const ErrorControl(
"CupertinoDialogAction.content must be a string or visible Control");
}

var cupertinoDialogAction = CupertinoDialogAction(
isDefaultAction: control.getBool("is_default_action", false)!,
isDestructiveAction: control.getBool("is_destructive_action", false)!,
isDefaultAction: control.getBool("default", false)!,
isDestructiveAction: control.getBool("destructive", false)!,
textStyle: control.getTextStyle("text_style", Theme.of(context)),
onPressed: !control.disabled
? () {
control.triggerEvent("click");
}
: null,
child: control.buildWidget("content") ??
Text(control.getString("text", "")!),
onPressed: !control.disabled ? () => control.triggerEvent("click") : null,
child: content,
);

return BaseControl(control: control, child: cupertinoDialogAction);
Expand Down
23 changes: 11 additions & 12 deletions packages/flet/lib/src/controls/cupertino_textfield.dart
Original file line number Diff line number Diff line change
Expand Up @@ -294,21 +294,20 @@ class _CupertinoTextFieldControlState extends State<CupertinoTextFieldControl> {
child: textField);
}

if (widget.control.getInt("expand", 0)! > 0) {
if (widget.control.get("expand") == true ||
(widget.control.get("expand") is int &&
widget.control.getInt("expand", 0)! > 0)) {
return ConstrainedControl(control: widget.control, child: textField);
} else {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
if (constraints.maxWidth == double.infinity &&
widget.control.getDouble("width") == null) {
textField = ConstrainedBox(
constraints: const BoxConstraints.tightFor(width: 300),
child: textField,
);
}
double? width = widget.control.getDouble("width");

return ConstrainedControl(control: widget.control, child: textField);
},
return ConstrainedControl(
control: widget.control,
child: width == null
? ConstrainedBox(
constraints: const BoxConstraints.tightFor(width: 300),
child: textField)
: textField,
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/flet/lib/src/controls/dropdownm2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class _DropdownM2ControlState extends State<DropdownM2Control> {
}

var items = widget.control
.children("controls")
.children("options")
.map<DropdownMenuItem<String>>((Control item) {
var textStyle = item.getTextStyle("text_style", Theme.of(context));
if (item.disabled && textStyle != null) {
Expand Down
2 changes: 1 addition & 1 deletion packages/flet/lib/src/controls/list_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class ListTileControl extends StatelessWidget with FletStoreMixin {
tile = ListTileClicks(notifier: _clickNotifier, child: tile);
}

tile = Material(color: Colors.transparent, child: tile);
tile = Material(type: MaterialType.transparency, child: tile);

return ConstrainedControl(control: control, child: tile);
}
Expand Down
27 changes: 9 additions & 18 deletions packages/flet/lib/src/controls/textfield.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ class _TextFieldControlState extends State<TextFieldControl> {
var textVerticalAlign = widget.control.getDouble("text_vertical_align");

FocusNode focusNode = shiftEnter ? _shiftEnterfocusNode : _focusNode;

var focusValue = widget.control.getString("focus");
var blurValue = widget.control.getString("blur");
if (focusValue != null && focusValue != _lastFocusValue) {
Expand All @@ -159,7 +158,6 @@ class _TextFieldControlState extends State<TextFieldControl> {
}

var fitParentSize = widget.control.getBool("fit_parent_size", false)!;

var maxLength = widget.control.getInt("max_length");

Widget textField = TextFormField(
Expand Down Expand Up @@ -262,25 +260,18 @@ class _TextFieldControlState extends State<TextFieldControl> {
if (widget.control.get("expand") == true ||
(widget.control.get("expand") is int &&
widget.control.getInt("expand", 0)! > 0)) {
return ConstrainedControl(
control: widget.control,
child: textField,
);
return ConstrainedControl(control: widget.control, child: textField);
} else {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
if (constraints.maxWidth == double.infinity &&
widget.control.getDouble("width") == null) {
textField = ConstrainedBox(
constraints: const BoxConstraints.tightFor(width: 300),
child: textField,
);
}
double? width = widget.control.getDouble("width");

return ConstrainedControl(control: widget.control, child: textField);
},
return ConstrainedControl(
control: widget.control,
child: width == null
? ConstrainedBox(
constraints: const BoxConstraints.tightFor(width: 300),
child: textField)
: textField,
);
}
//});
}
}
Loading