Skip to content

Commit

Permalink
CupertinoAlertDialog, CupertinoDialogAction, adaptive property for Al…
Browse files Browse the repository at this point in the history
…ertDialog (flet-dev#2365)

* initial commit

* adaptive property for AlertDialog

* CupertinoDialogAction control

* update cupertino_dialog_action

* Update __init__.py

removed duplicate imports

* is_default_active, is_destructive_action properties

* updated properties

* Update cupertino_dialog_action.dart

refactor

* Update cupertino_dialog_action.dart

refactor

* text_style property

* Update cupertino_alert_dialog.dart

refactor

* Update cupertino_alert_dialog.py

refactor

* added code examples

* changed action from constrainedControl to baseControl

* text_style property

* refactor

* ignore Podfile.lock

* sorted imports

* include CupertinoAlertDialog in dialog types

* changed to CupertinoDialogActionControl to StatelessWidget

---------

Co-authored-by: ndonkoHenri <[email protected]>
  • Loading branch information
2 people authored and zrr1999 committed Jul 17, 2024
1 parent 84bcbe0 commit b531b70
Show file tree
Hide file tree
Showing 11 changed files with 517 additions and 69 deletions.
1 change: 1 addition & 0 deletions client/macos/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Flutter-related
**/Flutter/ephemeral/
**/Pods/
Podfile.lock

# Xcode-related
**/dgph
Expand Down
60 changes: 0 additions & 60 deletions client/macos/Podfile.lock

This file was deleted.

14 changes: 14 additions & 0 deletions package/lib/src/controls/alert_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';

Expand All @@ -10,6 +11,7 @@ import '../utils/alignment.dart';
import '../utils/borders.dart';
import '../utils/edge_insets.dart';
import 'create_control.dart';
import 'cupertino_alert_dialog.dart';
import 'error.dart';

class AlertDialogControl extends StatefulWidget {
Expand Down Expand Up @@ -71,6 +73,18 @@ class _AlertDialogControlState extends State<AlertDialogControl> {
Widget build(BuildContext context) {
debugPrint("AlertDialog build ($hashCode): ${widget.control.id}");

bool adaptive = widget.control.attrBool("adaptive", false)!;
if (adaptive &&
(defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.macOS)) {
return CupertinoAlertDialogControl(
control: widget.control,
parentDisabled: widget.parentDisabled,
children: widget.children,
nextChild: widget.nextChild,
);
}

var server = FletAppServices.of(context).server;

bool lastOpen = widget.control.state["open"] ?? false;
Expand Down
20 changes: 17 additions & 3 deletions package/lib/src/controls/create_control.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'dart:math';

import 'package:flutter/material.dart';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';

import '../flet_app_services.dart';
Expand All @@ -13,7 +12,6 @@ import '../models/page_media_view_model.dart';
import '../utils/animations.dart';
import '../utils/theme.dart';
import '../utils/transforms.dart';

import 'alert_dialog.dart';
import 'animated_switcher.dart';
import 'audio.dart';
Expand All @@ -30,7 +28,9 @@ import 'circle_avatar.dart';
import 'clipboard.dart';
import 'column.dart';
import 'container.dart';
import 'cupertino_alert_dialog.dart';
import 'cupertino_checkbox.dart';
import 'cupertino_dialog_action.dart';
import 'cupertino_navigation_bar.dart';
import 'cupertino_radio.dart';
import 'cupertino_slider.dart';
Expand Down Expand Up @@ -284,6 +284,13 @@ Widget createWidget(Key? key, ControlViewModel controlView, Control? parent,
control: controlView.control,
children: controlView.children,
parentDisabled: parentDisabled);
case "cupertinodialogaction":
return CupertinoDialogActionControl(
key: key,
parent: parent,
control: controlView.control,
children: controlView.children,
parentDisabled: parentDisabled);
case "iconbutton":
return IconButtonControl(
key: key,
Expand Down Expand Up @@ -619,6 +626,13 @@ Widget createWidget(Key? key, ControlViewModel controlView, Control? parent,
children: controlView.children,
parentDisabled: parentDisabled,
nextChild: nextChild);
case "cupertinoalertdialog":
return CupertinoAlertDialogControl(
parent: parent,
control: controlView.control,
children: controlView.children,
parentDisabled: parentDisabled,
nextChild: nextChild);
case "bottomsheet":
return BottomSheetControl(
parent: parent,
Expand Down
127 changes: 127 additions & 0 deletions package/lib/src/controls/cupertino_alert_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';

import '../actions.dart';
import '../flet_app_services.dart';
import '../models/app_state.dart';
import '../models/control.dart';
import '../protocol/update_control_props_payload.dart';
import 'create_control.dart';
import 'error.dart';

class CupertinoAlertDialogControl extends StatefulWidget {
final Control? parent;
final Control control;
final List<Control> children;
final bool parentDisabled;
final Widget? nextChild;

const CupertinoAlertDialogControl(
{super.key,
this.parent,
required this.control,
required this.children,
required this.parentDisabled,
required this.nextChild});

@override
State<CupertinoAlertDialogControl> createState() =>
_CupertinoAlertDialogControlState();
}

class _CupertinoAlertDialogControlState
extends State<CupertinoAlertDialogControl> {
Widget _createCupertinoAlertDialog() {
bool disabled = widget.control.isDisabled || widget.parentDisabled;
var titleCtrls =
widget.children.where((c) => c.name == "title" && c.isVisible);
var contentCtrls =
widget.children.where((c) => c.name == "content" && c.isVisible);
var actionCtrls =
widget.children.where((c) => c.name == "action" && c.isVisible);
if (titleCtrls.isEmpty && contentCtrls.isEmpty && actionCtrls.isEmpty) {
return const ErrorControl(
"CupertinoAlertDialog does not have any content.");
}

return CupertinoAlertDialog(
title: titleCtrls.isNotEmpty
? createControl(widget.control, titleCtrls.first.id, disabled)
: null,
content: contentCtrls.isNotEmpty
? createControl(widget.control, contentCtrls.first.id, disabled)
: null,
actions: actionCtrls
.map((c) => createControl(widget.control, c.id, disabled))
.toList(),
);
}

@override
Widget build(BuildContext context) {
debugPrint("CupertinoAlertDialog build ($hashCode): ${widget.control.id}");

var server = FletAppServices.of(context).server;

bool lastOpen = widget.control.state["open"] ?? false;

return StoreConnector<AppState, Function>(
distinct: true,
converter: (store) => store.dispatch,
builder: (context, dispatch) {
debugPrint(
"CupertinoAlertDialog StoreConnector build: ${widget.control.id}");

var open = widget.control.attrBool("open", false)!;
var modal = widget.control.attrBool("modal", false)!;

debugPrint("Current open state: $lastOpen");
debugPrint("New open state: $open");

if (open && (open != lastOpen)) {
var dialog = _createCupertinoAlertDialog();
if (dialog is ErrorControl) {
return dialog;
}

// close previous dialog
if (ModalRoute.of(context)?.isCurrent != true) {
Navigator.of(context).pop();
}

widget.control.state["open"] = open;

WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
barrierDismissible: !modal,
useRootNavigator: false,
context: context,
builder: (context) => dialog).then((value) {
lastOpen = widget.control.state["open"] ?? false;
debugPrint("Dialog should be dismissed ($hashCode): $lastOpen");
bool shouldDismiss = lastOpen;
widget.control.state["open"] = false;

if (shouldDismiss) {
List<Map<String, String>> props = [
{"i": widget.control.id, "open": "false"}
];
dispatch(UpdateControlPropsAction(
UpdateControlPropsPayload(props: props)));
server.updateControlProps(props: props);
server.sendPageEvent(
eventTarget: widget.control.id,
eventName: "dismiss",
eventData: "");
}
});
});
} else if (open != lastOpen && lastOpen) {
Navigator.of(context).pop();
}

return widget.nextChild ?? const SizedBox.shrink();
});
}
}
56 changes: 56 additions & 0 deletions package/lib/src/controls/cupertino_dialog_action.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../flet_app_services.dart';
import '../models/control.dart';
import '../utils/text.dart';
import 'create_control.dart';

class CupertinoDialogActionControl extends StatelessWidget {
final Control? parent;
final Control control;
final List<Control> children;
final bool parentDisabled;

const CupertinoDialogActionControl(
{Key? key,
this.parent,
required this.control,
required this.children,
required this.parentDisabled})
: super(key: key);

@override
Widget build(BuildContext context) {
debugPrint("CupertinoDialogAction build: ${control.id}");

final server = FletAppServices.of(context).server;

String text = control.attrString("text", "")!;
var contentCtrls = children.where((c) => c.name == "content");
bool isDefaultAction = control.attrBool("isDefaultAction", false)!;
bool isDestructiveAction = control.attrBool("isDestructiveAction", false)!;
bool disabled = control.isDisabled || parentDisabled;

Function()? onPressed = !disabled
? () {
debugPrint("CupertinoDialogAction ${control.id} clicked!");
server.sendPageEvent(
eventTarget: control.id, eventName: "click", eventData: "");
}
: null;

CupertinoDialogAction? cupertinoDialogAction;

cupertinoDialogAction = CupertinoDialogAction(
onPressed: onPressed,
isDefaultAction: isDefaultAction,
isDestructiveAction: isDestructiveAction,
textStyle: parseTextStyle(Theme.of(context), control, "textStyle"),
child: contentCtrls.isNotEmpty
? createControl(control, contentCtrls.first.id, disabled)
: Text(text));

return baseControl(context, cupertinoDialogAction, parent, control);
}
}
2 changes: 2 additions & 0 deletions sdk/python/packages/flet-core/src/flet_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,6 @@
from flet_core.vertical_divider import VerticalDivider
from flet_core.view import View
from flet_core.webview import WebView
from flet_core.cupertino_alert_dialog import CupertinoAlertDialog
from flet_core.cupertino_dialog_action import CupertinoDialogAction
from flet_core.window_drag_area import WindowDragArea
12 changes: 11 additions & 1 deletion sdk/python/packages/flet-core/src/flet_core/alert_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ def __init__(
actions_alignment: MainAxisAlignment = MainAxisAlignment.NONE,
shape: Optional[OutlinedBorder] = None,
inset_padding: PaddingValue = None,
adaptive: Optional[bool] = None,
on_dismiss=None,
):

Control.__init__(
self,
ref=ref,
Expand All @@ -105,6 +105,7 @@ def __init__(
self.actions_alignment = actions_alignment
self.shape = shape
self.inset_padding = inset_padding
self.adaptive = adaptive
self.on_dismiss = on_dismiss

def _get_control_name(self):
Expand Down Expand Up @@ -149,6 +150,15 @@ def modal(self) -> Optional[bool]:
def modal(self, value: Optional[bool]):
self._set_attr("modal", value)

# adaptive
@property
def adaptive(self) -> Optional[bool]:
return self._get_attr("adaptive", data_type="bool", def_value=False)

@adaptive.setter
def adaptive(self, value: Optional[bool]):
self._set_attr("adaptive", value)

# title
@property
def title(self):
Expand Down
Loading

0 comments on commit b531b70

Please sign in to comment.