14
14
* limitations under the License.
15
15
*/
16
16
17
+ import 'dart:io' ;
18
+
17
19
import 'package:flutter/foundation.dart' ;
18
20
import 'package:flutter/material.dart' ;
19
21
import 'package:flutter/semantics.dart' ;
@@ -33,6 +35,10 @@ import 'package:illinois/ui/widgets/PopupDialog.dart';
33
35
import 'package:illinois/ui/widgets/RoundedButton.dart' ;
34
36
import 'package:illinois/utils/Utils.dart' ;
35
37
import 'package:url_launcher/url_launcher.dart' ;
38
+ import 'package:flutter/services.dart' show rootBundle;
39
+ import 'package:flutter_html_to_pdf/flutter_html_to_pdf.dart' ;
40
+ import 'package:path_provider/path_provider.dart' ;
41
+ import 'package:share/share.dart' ;
36
42
37
43
class HealthHistoryPanel extends StatefulWidget {
38
44
@override
@@ -433,6 +439,7 @@ class _HealthHistoryEntryState extends State<_HealthHistoryEntry> with SingleTic
433
439
bool _expanded = false ;
434
440
AnimationController _controller;
435
441
442
+ bool _sharing = false ;
436
443
bool _isLoadingLocation = false ;
437
444
438
445
@override
@@ -472,10 +479,7 @@ class _HealthHistoryEntryState extends State<_HealthHistoryEntry> with SingleTic
472
479
473
480
content.add (Container (height: 16 ,));
474
481
475
- return Container (
476
- padding: EdgeInsets .symmetric (),
477
- child: Column (children: content,),
478
- );
482
+ return Column (children: content,);
479
483
}
480
484
481
485
Widget _buildCommonInfo (){
@@ -566,13 +570,16 @@ class _HealthHistoryEntryState extends State<_HealthHistoryEntry> with SingleTic
566
570
}
567
571
568
572
return Semantics (sortKey: OrdinalSortKey (1 ), container: true , child:
569
- Container (color: Styles ().colors.white, padding: EdgeInsets .symmetric (horizontal: 16 , vertical: 16 ), child:
570
- Row (children: < Widget > [
571
- Expanded (child:
572
- Column (crossAxisAlignment: CrossAxisAlignment .start, children: contentList,)
573
- ),
574
- ]),
575
- ),
573
+ Stack (children: [
574
+ Container (color: Styles ().colors.white, padding: EdgeInsets .symmetric (horizontal: 16 , vertical: 16 ), child:
575
+ Row (children: < Widget > [
576
+ Expanded (child:
577
+ Column (crossAxisAlignment: CrossAxisAlignment .start, children: contentList,),
578
+ ),
579
+ ]),
580
+ ),
581
+ _buildShareButton (),
582
+ ]),
576
583
);
577
584
}
578
585
@@ -727,6 +734,33 @@ class _HealthHistoryEntryState extends State<_HealthHistoryEntry> with SingleTic
727
734
);
728
735
}
729
736
737
+ Widget _buildShareButton () {
738
+ return Visibility (visible: (widget.historyEntry.isTest == true ), child:
739
+ Align (alignment: Alignment .topRight, child:
740
+ Semantics (button: true , label: "Share" , child:
741
+ GestureDetector (onTap: () { _onTapShare (); }, child:
742
+ Container (width: 36 , height: 36 , child:
743
+ Stack (children: [
744
+ Align (alignment: Alignment .center, child:
745
+ Semantics (excludeSemantics: true , child:
746
+ Image .asset ('images/icon-share.png' )
747
+ ),
748
+ ),
749
+ Visibility (visible: _sharing, child:
750
+ Align (alignment: Alignment .center, child:
751
+ Container (width: 16 , height: 16 , child:
752
+ CircularProgressIndicator (valueColor: AlwaysStoppedAnimation <Color >(Styles ().colors.fillColorSecondary), strokeWidth: 2 ,)
753
+ ),
754
+ ),
755
+ ),
756
+ ],),
757
+ ),
758
+ ),
759
+ ),
760
+ ),
761
+ );
762
+ }
763
+
730
764
void _onTapLocation () {
731
765
Analytics ().logSelect (target: widget.historyEntry? .blob? .locationId);
732
766
String locationId = widget.historyEntry? .blob? .locationId;
@@ -787,4 +821,48 @@ class _HealthHistoryEntryState extends State<_HealthHistoryEntry> with SingleTic
787
821
Analytics .instance.logSelect (target: "Close Disclaimer" );
788
822
Navigator .of (context).pop ();
789
823
}
824
+
825
+ void _onTapShare () {
826
+ if (! _sharing) {
827
+ setState (() {
828
+ _sharing = true ;
829
+ });
830
+ _createTestResultPdf ().then ((File pdfFile) {
831
+ if (mounted) {
832
+ setState (() {
833
+ _sharing = false ;
834
+ });
835
+ if (pdfFile != null ) {
836
+ String subject = "${widget ?.historyEntry ?.blob ?.testType } test result" ;
837
+ String text = "${widget ?.historyEntry ?.blob ?.testType } test result" ;
838
+ String mimeType = "application/pdf" ;
839
+ String pdfFilePath = pdfFile.path;
840
+ try {
841
+ Share .shareFiles ([pdfFilePath], subject: subject, text: text, mimeTypes: [mimeType]);
842
+ }
843
+ catch (e) {
844
+ print (e? .toString ());
845
+ AppAlert .showDialogResult (context, "Unable to share test result document" );
846
+ }
847
+ }
848
+ else {
849
+ AppAlert .showDialogResult (context, "Unable to prepare test result document" );
850
+ }
851
+ }
852
+ });
853
+ }
854
+ }
855
+
856
+ Future <File > _createTestResultPdf () async {
857
+ String htmlSource = await rootBundle.loadString ('assets/test.result.html' );
858
+
859
+ Directory appDocDir = await getTemporaryDirectory ();
860
+ String targetPath = appDocDir.path;
861
+ String targetFileName = "test-result" ;
862
+
863
+ try { return await FlutterHtmlToPdf .convertFromHtmlContent (htmlSource, targetPath, targetFileName); }
864
+ catch (e) { print (e? .toString ()); }
865
+ return null ;
866
+ }
867
+
790
868
}
0 commit comments