Line data Source code
1 : import 'dart:ui';
2 :
3 : import 'package:flutter/material.dart';
4 :
5 26 : enum SendingStatus {
6 26 : SENDING,
7 26 : ERROR,
8 26 : SENT
9 : }
10 :
11 : /// use this to add a standard sending progress overlay function to all helper editors
12 : /// class _EditorSimpleHelperPage with EditorSendingOverlayMixin implements EditorSimpleHelperView
13 : /// _EditorSimpleHelperPage(this.context, this.scaffoldKey) {
14 : /// this.overlayContext = this.context;
15 : /// }
16 : /// ...
17 : /// }
18 : mixin EditorSendingOverlayMixin {
19 : EditorSendingOverlay sendingOverlay;
20 : BuildContext overlayContext;
21 :
22 9 : void closeLoadingScreen() => sendingOverlay.dismiss();
23 :
24 3 : Future showLoadingScreen(ValueNotifier<SendingStatus> status) async {
25 6 : sendingOverlay = EditorSendingOverlay(
26 : loadingOpacity: 1,
27 : loadingMessage: "Saving... please wait",
28 : successMessage: "Helper saved",
29 : errorMessage: "Error occured, please try again later",
30 : status: status
31 : );
32 12 : await sendingOverlay.show(overlayContext);
33 : }
34 : }
35 :
36 :
37 : class EditorSendingOverlay {
38 :
39 : double loadingOpacity;
40 : String loadingMessage;
41 : String successMessage;
42 : String errorMessage;
43 : ValueNotifier<SendingStatus> status;
44 :
45 : OverlayEntry _entry;
46 :
47 4 : EditorSendingOverlay({
48 : @required this.loadingOpacity,
49 : @required this.loadingMessage,
50 : @required this.successMessage,
51 : @required this.errorMessage,
52 : @required this.status
53 : });
54 :
55 4 : Future show(BuildContext context) async {
56 4 : if(_entry == null) {
57 8 : this._entry = OverlayEntry(
58 : opaque: false,
59 : maintainState: true,
60 8 : builder: (_) => Material(
61 : type: MaterialType.transparency,
62 4 : child: _build()
63 : )
64 : );
65 : }
66 12 : Overlay.of(context).insert(_entry);
67 : }
68 :
69 4 : dismiss() {
70 4 : if(_entry != null) {
71 8 : _entry.remove();
72 4 : _entry = null;
73 : }
74 : }
75 :
76 4 : Widget _build() {
77 4 : return ValueListenableBuilder<SendingStatus>(
78 4 : valueListenable: status,
79 4 : builder: (BuildContext context, SendingStatus currentStatus, Widget child)
80 4 : => AnimatedOpacity(
81 4 : duration: Duration(milliseconds: 400),
82 4 : opacity: loadingOpacity,
83 4 : child: Stack(
84 4 : children: [
85 4 : BackdropFilter(
86 : filter:
87 4 : ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0),
88 4 : child: Container(
89 : color: Colors.black54,
90 : ),
91 : ),
92 4 : Center(
93 4 : child: Column(
94 : crossAxisAlignment: CrossAxisAlignment.center,
95 : mainAxisAlignment: MainAxisAlignment.center,
96 4 : children: _getContent()
97 : ),
98 : ),
99 : ],
100 : ),
101 : )
102 : );
103 : }
104 :
105 4 : List<Widget> _getContent() {
106 8 : switch(status.value) {
107 4 : case SendingStatus.SENDING:
108 1 : return _buildLoadingScreen();
109 4 : case SendingStatus.ERROR:
110 3 : return _buildCreationStatusScreen(false);
111 4 : case SendingStatus.SENT:
112 4 : return _buildCreationStatusScreen(true);
113 : }
114 : }
115 :
116 2 : List<Widget> _buildLoadingScreen() => [
117 1 : CircularProgressIndicator(
118 1 : valueColor: new AlwaysStoppedAnimation<Color>(Colors.white),
119 : ),
120 1 : SizedBox(height: 25.0),
121 2 : Text(this.loadingMessage,
122 1 : style: TextStyle(
123 : color: Colors.white,
124 : fontSize: 22.0,
125 : ),
126 : ),
127 : ];
128 :
129 4 : List<Widget> _buildCreationStatusScreen(bool success) {
130 4 : return [
131 : success
132 4 : ? Icon(Icons.check, color: Colors.green, size: 100.0)
133 3 : : Icon(Icons.close, color: Colors.red, size: 100.0,
134 : ),
135 4 : SizedBox(height: 25.0),
136 4 : Text(
137 7 : success ? successMessage : errorMessage,
138 : textAlign: TextAlign.center,
139 4 : style: TextStyle(
140 : color: Colors.white,
141 : fontSize: 22.0,
142 : ),
143 : ),
144 : ];
145 : }
146 : }
147 :
|