android/ios-adaption feature, markdown, and augment #6
					 4 changed files with 206 additions and 132 deletions
				
			
		| 
						 | 
				
			
			@ -1,132 +1,3 @@
 | 
			
		|||
import 'dart:js_interop';
 | 
			
		||||
import 'package:web/web.dart' as web;
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'dart:ui_web' as ui;
 | 
			
		||||
import 'api_service.dart';
 | 
			
		||||
import 'structs.dart';
 | 
			
		||||
 | 
			
		||||
class CollapsableEmails extends StatefulWidget {
 | 
			
		||||
  final List<String> thread; // email id's in the form xyz@gmail.com
 | 
			
		||||
  final List<String> threadHTML;
 | 
			
		||||
  final String threadIDs;
 | 
			
		||||
 | 
			
		||||
  CollapsableEmails(
 | 
			
		||||
      {required this.thread,
 | 
			
		||||
      required this.threadHTML,
 | 
			
		||||
      required this.threadIDs});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<CollapsableEmails> createState() => _CollapsableEmailsState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _CollapsableEmailsState extends State<CollapsableEmails> {
 | 
			
		||||
  List<String> emailsHTML = []; //html of the emails in the thread
 | 
			
		||||
  // build attachments with the forldar name and id
 | 
			
		||||
  Set<int> _expandedEmails = {}; //open emails
 | 
			
		||||
  List viewtypeIDs = []; //IDs of the viewtypes, order matters
 | 
			
		||||
  List heightOfViewTypes = []; //the height of each viewtype
 | 
			
		||||
  List<SerializableMessage> emailsInThread = [];
 | 
			
		||||
  bool _isLoaded = false;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    // TODO: implement initState
 | 
			
		||||
    super.initState();
 | 
			
		||||
    _registerViewFactory(widget.threadHTML);
 | 
			
		||||
    _serializableData(widget.threadIDs);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void _registerViewFactory(List<String> currentContent) async {
 | 
			
		||||
    // setState(() { //update to do item per item
 | 
			
		||||
    // each item to have itsviewtype ID
 | 
			
		||||
    // is this necessarey here??
 | 
			
		||||
 | 
			
		||||
    //could just move to collapsable
 | 
			
		||||
 | 
			
		||||
    for (var emailHTML in widget.threadHTML) {
 | 
			
		||||
      String viewTypeId = 'email-${DateTime.now().millisecondsSinceEpoch}';
 | 
			
		||||
 | 
			
		||||
      final ghost = web.document.createElement('div') as web.HTMLDivElement
 | 
			
		||||
        ..style.visibility = 'hidden'
 | 
			
		||||
        ..style.position = 'absolute'
 | 
			
		||||
        ..style.width = '100%'
 | 
			
		||||
        ..style.overflow = 'auto'
 | 
			
		||||
        ..innerHTML = emailHTML
 | 
			
		||||
            .toJS; // temporarily index because it has to do all of them
 | 
			
		||||
      web.document.body?.append(ghost);
 | 
			
		||||
      await Future.delayed(Duration(milliseconds: 10));
 | 
			
		||||
 | 
			
		||||
      final heightOfEmail = ghost.scrollHeight;
 | 
			
		||||
      ghost.remove();
 | 
			
		||||
 | 
			
		||||
      final HTMLsnippet = web.document.createElement('div')
 | 
			
		||||
          as web.HTMLDivElement
 | 
			
		||||
        ..id = viewTypeId
 | 
			
		||||
        ..innerHTML = emailHTML
 | 
			
		||||
            .toJS; // temporarily index because it has to do all of them
 | 
			
		||||
      HTMLsnippet.style
 | 
			
		||||
        ..width = '100%'
 | 
			
		||||
        ..height = '${heightOfEmail}px'
 | 
			
		||||
        ..overflow = 'auto'
 | 
			
		||||
        ..scrollBehavior = 'smooth';
 | 
			
		||||
 | 
			
		||||
      ui.platformViewRegistry.registerViewFactory(
 | 
			
		||||
        viewTypeId,
 | 
			
		||||
        (int viewId) => HTMLsnippet,
 | 
			
		||||
      );
 | 
			
		||||
      viewtypeIDs.add(viewTypeId);
 | 
			
		||||
      heightOfViewTypes.add(heightOfEmail);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void _serializableData(String threadID) async {
 | 
			
		||||
    emailsInThread = await ApiService().threadsInSerializable(threadID);
 | 
			
		||||
    print("done thread serializable");
 | 
			
		||||
    if (!mounted) return;
 | 
			
		||||
    setState(() {
 | 
			
		||||
      _isLoaded = true;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return _isLoaded 
 | 
			
		||||
      ?Column(children: [
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: ListView.builder(
 | 
			
		||||
            itemCount: widget.thread.length,
 | 
			
		||||
            itemBuilder: (context, index) {
 | 
			
		||||
              final isExpanded =
 | 
			
		||||
                  _expandedEmails.contains(index); //check if email is expanded
 | 
			
		||||
              return Column(
 | 
			
		||||
                children: [
 | 
			
		||||
                  ListTile(
 | 
			
		||||
                    title: Text(emailsInThread[index].from),
 | 
			
		||||
                    trailing: Text(emailsInThread[index].date),
 | 
			
		||||
                    onTap: () {
 | 
			
		||||
                      setState(() {
 | 
			
		||||
                        if (isExpanded) {
 | 
			
		||||
                          _expandedEmails.remove(index);
 | 
			
		||||
                        } else {
 | 
			
		||||
                          _expandedEmails.add(index);
 | 
			
		||||
                        }
 | 
			
		||||
                      });
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                  if (isExpanded)
 | 
			
		||||
                    // if(viewtypeIDs[index] == null || heightOfViewTypes[index] == null)
 | 
			
		||||
                    //   const SizedBox(height: 100, child: Center(child: CircularProgressIndicator())),
 | 
			
		||||
                    SizedBox(
 | 
			
		||||
                      height: heightOfViewTypes[index].toDouble(),
 | 
			
		||||
                      child: HtmlElementView(
 | 
			
		||||
                          key: UniqueKey(), viewType: viewtypeIDs[index]),
 | 
			
		||||
                    ),
 | 
			
		||||
                  Divider(),
 | 
			
		||||
                ],
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        )
 | 
			
		||||
    ]): const Center(child:CircularProgressIndicator());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
export 'collapsableEmailsStub.dart'
 | 
			
		||||
  if (dart.library.io) 'collapsableEmailsAndroid.dart'
 | 
			
		||||
  if (dart.library.js_interop) 'collapsableEmailsWeb.dart';
 | 
			
		||||
							
								
								
									
										48
									
								
								lib/collapsableEmailsAndroid.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								lib/collapsableEmailsAndroid.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
import 'structs.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
 | 
			
		||||
 | 
			
		||||
class CollapsableEmails extends StatefulWidget {
 | 
			
		||||
  final List<String> thread; // email id's in the form xyz@gmail.com
 | 
			
		||||
  final List<String> threadHTML;
 | 
			
		||||
  final String threadIDs;
 | 
			
		||||
 | 
			
		||||
  CollapsableEmails(
 | 
			
		||||
      {required this.thread,
 | 
			
		||||
      required this.threadHTML,
 | 
			
		||||
      required this.threadIDs});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<CollapsableEmails> createState() => _CollapsableEmailsState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _CollapsableEmailsState extends State<CollapsableEmails> {
 | 
			
		||||
  List<String> emailsHTML = []; //html of the emails in the thread
 | 
			
		||||
  // build attachments with the forldar name and id
 | 
			
		||||
  Set<int> _expandedEmails = {}; //open emails
 | 
			
		||||
  List viewtypeIDs = []; //IDs of the viewtypes, order matters
 | 
			
		||||
  List heightOfViewTypes = []; //the height of each viewtype
 | 
			
		||||
  List<SerializableMessage> emailsInThread = [];
 | 
			
		||||
  bool _isLoaded = false;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    //html
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      body: ListView(
 | 
			
		||||
        children: [
 | 
			
		||||
          HtmlWidget(
 | 
			
		||||
            widget.threadHTML[0],
 | 
			
		||||
            // renderMode: RenderMode.listView,
 | 
			
		||||
          )
 | 
			
		||||
        ]
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								lib/collapsableEmailsStub.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/collapsableEmailsStub.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
import 'structs.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class CollapsableEmails extends StatefulWidget {
 | 
			
		||||
  final List<String> thread; // email id's in the form xyz@gmail.com
 | 
			
		||||
  final List<String> threadHTML;
 | 
			
		||||
  final String threadIDs;
 | 
			
		||||
 | 
			
		||||
  CollapsableEmails(
 | 
			
		||||
      {required this.thread,
 | 
			
		||||
      required this.threadHTML,
 | 
			
		||||
      required this.threadIDs});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<CollapsableEmails> createState() => _CollapsableEmailsState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _CollapsableEmailsState extends State<CollapsableEmails> {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(body: Text("collapsable stud"));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								lib/collapsableEmailsWeb.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								lib/collapsableEmailsWeb.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,132 @@
 | 
			
		|||
import 'dart:js_interop';
 | 
			
		||||
import 'package:web/web.dart' as web;
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'dart:ui_web' as ui;
 | 
			
		||||
import 'api_service.dart';
 | 
			
		||||
import 'structs.dart';
 | 
			
		||||
 | 
			
		||||
class CollapsableEmails extends StatefulWidget {
 | 
			
		||||
  final List<String> thread; // email id's in the form xyz@gmail.com
 | 
			
		||||
  final List<String> threadHTML;
 | 
			
		||||
  final String threadIDs;
 | 
			
		||||
 | 
			
		||||
  CollapsableEmails(
 | 
			
		||||
      {required this.thread,
 | 
			
		||||
      required this.threadHTML,
 | 
			
		||||
      required this.threadIDs});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<CollapsableEmails> createState() => _CollapsableEmailsState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _CollapsableEmailsState extends State<CollapsableEmails> {
 | 
			
		||||
  List<String> emailsHTML = []; //html of the emails in the thread
 | 
			
		||||
  // build attachments with the forldar name and id
 | 
			
		||||
  Set<int> _expandedEmails = {}; //open emails
 | 
			
		||||
  List viewtypeIDs = []; //IDs of the viewtypes, order matters
 | 
			
		||||
  List heightOfViewTypes = []; //the height of each viewtype
 | 
			
		||||
  List<SerializableMessage> emailsInThread = [];
 | 
			
		||||
  bool _isLoaded = false;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    // TODO: implement initState
 | 
			
		||||
    super.initState();
 | 
			
		||||
    _registerViewFactory(widget.threadHTML);
 | 
			
		||||
    _serializableData(widget.threadIDs);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void _registerViewFactory(List<String> currentContent) async {
 | 
			
		||||
    // setState(() { //update to do item per item
 | 
			
		||||
    // each item to have itsviewtype ID
 | 
			
		||||
    // is this necessarey here??
 | 
			
		||||
 | 
			
		||||
    //could just move to collapsable
 | 
			
		||||
 | 
			
		||||
    for (var emailHTML in widget.threadHTML) {
 | 
			
		||||
      String viewTypeId = 'email-${DateTime.now().millisecondsSinceEpoch}';
 | 
			
		||||
 | 
			
		||||
      final ghost = web.document.createElement('div') as web.HTMLDivElement
 | 
			
		||||
        ..style.visibility = 'hidden'
 | 
			
		||||
        ..style.position = 'absolute'
 | 
			
		||||
        ..style.width = '100%'
 | 
			
		||||
        ..style.overflow = 'auto'
 | 
			
		||||
        ..innerHTML = emailHTML
 | 
			
		||||
            .toJS; // temporarily index because it has to do all of them
 | 
			
		||||
      web.document.body?.append(ghost);
 | 
			
		||||
      await Future.delayed(Duration(milliseconds: 10));
 | 
			
		||||
 | 
			
		||||
      final heightOfEmail = ghost.scrollHeight;
 | 
			
		||||
      ghost.remove();
 | 
			
		||||
 | 
			
		||||
      final HTMLsnippet = web.document.createElement('div')
 | 
			
		||||
          as web.HTMLDivElement
 | 
			
		||||
        ..id = viewTypeId
 | 
			
		||||
        ..innerHTML = emailHTML
 | 
			
		||||
            .toJS; // temporarily index because it has to do all of them
 | 
			
		||||
      HTMLsnippet.style
 | 
			
		||||
        ..width = '100%'
 | 
			
		||||
        ..height = '${heightOfEmail}px'
 | 
			
		||||
        ..overflow = 'auto'
 | 
			
		||||
        ..scrollBehavior = 'smooth';
 | 
			
		||||
 | 
			
		||||
      ui.platformViewRegistry.registerViewFactory(
 | 
			
		||||
        viewTypeId,
 | 
			
		||||
        (int viewId) => HTMLsnippet,
 | 
			
		||||
      );
 | 
			
		||||
      viewtypeIDs.add(viewTypeId);
 | 
			
		||||
      heightOfViewTypes.add(heightOfEmail);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void _serializableData(String threadID) async {
 | 
			
		||||
    emailsInThread = await ApiService().threadsInSerializable(threadID);
 | 
			
		||||
    print("done thread serializable");
 | 
			
		||||
    if (!mounted) return;
 | 
			
		||||
    setState(() {
 | 
			
		||||
      _isLoaded = true;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return _isLoaded 
 | 
			
		||||
      ?Column(children: [
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: ListView.builder(
 | 
			
		||||
            itemCount: widget.thread.length,
 | 
			
		||||
            itemBuilder: (context, index) {
 | 
			
		||||
              final isExpanded =
 | 
			
		||||
                  _expandedEmails.contains(index); //check if email is expanded
 | 
			
		||||
              return Column(
 | 
			
		||||
                children: [
 | 
			
		||||
                  ListTile(
 | 
			
		||||
                    title: Text(emailsInThread[index].from),
 | 
			
		||||
                    trailing: Text(emailsInThread[index].date),
 | 
			
		||||
                    onTap: () {
 | 
			
		||||
                      setState(() {
 | 
			
		||||
                        if (isExpanded) {
 | 
			
		||||
                          _expandedEmails.remove(index);
 | 
			
		||||
                        } else {
 | 
			
		||||
                          _expandedEmails.add(index);
 | 
			
		||||
                        }
 | 
			
		||||
                      });
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                  if (isExpanded)
 | 
			
		||||
                    // if(viewtypeIDs[index] == null || heightOfViewTypes[index] == null)
 | 
			
		||||
                    //   const SizedBox(height: 100, child: Center(child: CircularProgressIndicator())),
 | 
			
		||||
                    SizedBox(
 | 
			
		||||
                      height: heightOfViewTypes[index].toDouble(),
 | 
			
		||||
                      child: HtmlElementView(
 | 
			
		||||
                          key: UniqueKey(), viewType: viewtypeIDs[index]),
 | 
			
		||||
                    ),
 | 
			
		||||
                  Divider(),
 | 
			
		||||
                ],
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        )
 | 
			
		||||
    ]): const Center(child:CircularProgressIndicator());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue