added features and fixed bugs of focusNode
This commit is contained in:
		
							parent
							
								
									b03d939a11
								
							
						
					
					
						commit
						42e31f63c5
					
				
					 3 changed files with 240 additions and 48 deletions
				
			
		| 
						 | 
				
			
			@ -5,8 +5,8 @@ import 'dart:ui_web' as ui;
 | 
			
		|||
import 'dart:html' as html;
 | 
			
		||||
import 'augment.dart';
 | 
			
		||||
import 'dart:js' as js;
 | 
			
		||||
// import 'dart:js_util';
 | 
			
		||||
 | 
			
		||||
//data structure
 | 
			
		||||
class MailAddress {
 | 
			
		||||
  final String? name;
 | 
			
		||||
  final String address;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ class MailAddress {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//data structure
 | 
			
		||||
class SerializableMessage {
 | 
			
		||||
  final String name;
 | 
			
		||||
  final String from;
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +97,7 @@ class _EmailPageState extends State<EmailPage> {
 | 
			
		|||
      var url = Uri.http(
 | 
			
		||||
          '127.0.0.1:3001', 'sorted_threads_by_date', {'folder': folder});
 | 
			
		||||
      var response = await http.get(url);
 | 
			
		||||
      // print(response.body);
 | 
			
		||||
      print(response.body);
 | 
			
		||||
      // Map<String, dynamic> json = jsonDecode(response.body); original
 | 
			
		||||
 | 
			
		||||
      // json.forEach((key, value) {
 | 
			
		||||
| 
						 | 
				
			
			@ -109,12 +110,14 @@ class _EmailPageState extends State<EmailPage> {
 | 
			
		|||
      // new shit
 | 
			
		||||
      if (response.statusCode == 200) {
 | 
			
		||||
        List<dynamic> json = jsonDecode(response.body);
 | 
			
		||||
        for (var item in json) {
 | 
			
		||||
        for (var item in json.take(1)) { //each item in the json is a date
 | 
			
		||||
          if (item.length > 1 && item[0] is String && item[1] is List) {
 | 
			
		||||
            List<int> threadIDs = List<int>.from(item[1]);
 | 
			
		||||
            for (var threadId in threadIDs) {
 | 
			
		||||
              print(threadId);
 | 
			
		||||
              await fetchThreadMessages(threadId, allEmails);
 | 
			
		||||
            }
 | 
			
		||||
            //TODO: get exact thread with new api endpoint from chosen thread?
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +126,7 @@ class _EmailPageState extends State<EmailPage> {
 | 
			
		|||
    } catch (e) {
 | 
			
		||||
      print('_displayEmailsFromFolder caught error: $e');
 | 
			
		||||
    }
 | 
			
		||||
    print("Done");
 | 
			
		||||
    setState(() {
 | 
			
		||||
      emails.clear();
 | 
			
		||||
      // emails = messagesMap.values.toList().expand((list) => list).toList();
 | 
			
		||||
| 
						 | 
				
			
			@ -131,6 +135,9 @@ class _EmailPageState extends State<EmailPage> {
 | 
			
		|||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Future<void> fetchThreads(AboutDialog){
 | 
			
		||||
  // }
 | 
			
		||||
 | 
			
		||||
  Future<void> fetchThreadMessages(
 | 
			
		||||
      int threadId, List<SerializableMessage> allEmails) async {
 | 
			
		||||
    try {
 | 
			
		||||
| 
						 | 
				
			
			@ -368,7 +375,7 @@ class _EmailViewState extends State<EmailView> {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  void _scrollToNumber(String spanId) {
 | 
			
		||||
    AugmentClasses.handleJump(viewTypeId);
 | 
			
		||||
    AugmentClasses.handleJump(spanId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // void _invisibility(String )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										263
									
								
								lib/augment.dart
									
										
									
									
									
								
							
							
						
						
									
										263
									
								
								lib/augment.dart
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -22,40 +22,40 @@ class EmailToolbar extends StatefulWidget {
 | 
			
		|||
 | 
			
		||||
class _DynamicClassesAugment extends State<EmailToolbar> {
 | 
			
		||||
  String selectedClass = 'Class 1';
 | 
			
		||||
  TextEditingController _jumpController = TextEditingController();
 | 
			
		||||
  // TextEditingController _jumpController = TextEditingController();
 | 
			
		||||
 | 
			
		||||
  late final FocusNode _JumpItemfocusNode;
 | 
			
		||||
  late final FocusNode _viewSpecsfocusNode;
 | 
			
		||||
  // late final FocusNode _JumpItemfocusNode;
 | 
			
		||||
  // late final FocusNode _viewSpecsfocusNode;
 | 
			
		||||
 | 
			
		||||
  bool _jumpItemHasFocus = false;
 | 
			
		||||
  bool _viewSpecsHasFocus = false;
 | 
			
		||||
  // bool _jumpItemHasFocus = false;
 | 
			
		||||
  // bool _viewSpecsHasFocus = false;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    _JumpItemfocusNode = FocusNode();
 | 
			
		||||
    _viewSpecsfocusNode = FocusNode();
 | 
			
		||||
    // _JumpItemfocusNode = FocusNode();
 | 
			
		||||
    // _viewSpecsfocusNode = FocusNode();
 | 
			
		||||
 | 
			
		||||
    _JumpItemfocusNode.addListener(() {
 | 
			
		||||
      setState(() => _jumpItemHasFocus = _JumpItemfocusNode.hasFocus);
 | 
			
		||||
    });
 | 
			
		||||
    // _JumpItemfocusNode.addListener(() {
 | 
			
		||||
    //   setState(() => _jumpItemHasFocus = _JumpItemfocusNode.hasFocus);
 | 
			
		||||
    // });
 | 
			
		||||
 | 
			
		||||
    _viewSpecsfocusNode.addListener(() {
 | 
			
		||||
      setState(() => _viewSpecsHasFocus = _viewSpecsfocusNode.hasFocus);
 | 
			
		||||
    });
 | 
			
		||||
    // _viewSpecsfocusNode.addListener(() {
 | 
			
		||||
    //   setState(() => _viewSpecsHasFocus = _viewSpecsfocusNode.hasFocus);
 | 
			
		||||
    // });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    // _JumpItemfocusNode.dispose();
 | 
			
		||||
    // _viewSpecsfocusNode.dispose();
 | 
			
		||||
    _jumpController.dispose();
 | 
			
		||||
    // _jumpController.dispose();
 | 
			
		||||
    super.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    const animationDuration = Duration(milliseconds: 250);
 | 
			
		||||
    // const animationDuration = Duration(milliseconds: 250);
 | 
			
		||||
 | 
			
		||||
    return Column(children: [
 | 
			
		||||
      Row(
 | 
			
		||||
| 
						 | 
				
			
			@ -128,14 +128,14 @@ class _DynamicClassesAugment extends State<EmailToolbar> {
 | 
			
		|||
              //   width: 8,
 | 
			
		||||
              // ),
 | 
			
		||||
              Container(
 | 
			
		||||
                width: 150,
 | 
			
		||||
                width: 50,
 | 
			
		||||
                height: 30,
 | 
			
		||||
                child: TextField(
 | 
			
		||||
                  controller: _jumpController,
 | 
			
		||||
                  // controller: _jumpController,
 | 
			
		||||
                  decoration: InputDecoration(
 | 
			
		||||
                      labelText: 'Jump Item',
 | 
			
		||||
                    border: OutlineInputBorder(),
 | 
			
		||||
                      suffixIcon: Icon(Icons.search)),
 | 
			
		||||
                    // suffixIcon: Icon(Icons.search)
 | 
			
		||||
                  ),
 | 
			
		||||
                  onSubmitted: (value) {
 | 
			
		||||
                    print("onSubmitted");
 | 
			
		||||
                    if (value.isNotEmpty) {
 | 
			
		||||
| 
						 | 
				
			
			@ -172,14 +172,18 @@ class _DynamicClassesAugment extends State<EmailToolbar> {
 | 
			
		|||
              //       ),
 | 
			
		||||
              // ),
 | 
			
		||||
              SizedBox(width: 8),
 | 
			
		||||
              ElevatedButton(
 | 
			
		||||
                  onPressed: () => AugmentClasses.ViewSpecsButton(context),
 | 
			
		||||
                  child: Text('ViewSpecs:')),
 | 
			
		||||
              Container(
 | 
			
		||||
                width: 150,
 | 
			
		||||
                width: 50,
 | 
			
		||||
                height: 30,
 | 
			
		||||
                child: TextField(
 | 
			
		||||
                  decoration: InputDecoration(
 | 
			
		||||
                      labelText: 'viewSpecs',
 | 
			
		||||
                    labelText: '',
 | 
			
		||||
                    border: OutlineInputBorder(),
 | 
			
		||||
                      suffixIcon: Icon(Icons.style_rounded)),
 | 
			
		||||
                    // suffixIcon: Icon(Icons.style_rounded)
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
              ElevatedButton(
 | 
			
		||||
| 
						 | 
				
			
			@ -259,30 +263,209 @@ class AugmentClasses {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  static void invisibility(String htmlClass) {}
 | 
			
		||||
  static JumpButton(context) {
 | 
			
		||||
    showDialog(
 | 
			
		||||
 | 
			
		||||
  static Future<void> JumpButton(BuildContext context) async {
 | 
			
		||||
    // FocusNode textFieldFocusNode = FocusNode();
 | 
			
		||||
 | 
			
		||||
    AugmentClasses.disableIframePointerEvents();
 | 
			
		||||
    await showDialog(
 | 
			
		||||
      barrierDismissible: true,
 | 
			
		||||
      // barrierColor: Colors.yellow,
 | 
			
		||||
      context: context,
 | 
			
		||||
      builder: (context) => AlertDialog(
 | 
			
		||||
        title: Text('Jump Item:'),
 | 
			
		||||
        content: Column(
 | 
			
		||||
        content: Container(
 | 
			
		||||
          width: 200,
 | 
			
		||||
          height: 120,
 | 
			
		||||
          child: Column(
 | 
			
		||||
            mainAxisSize: MainAxisSize.min,
 | 
			
		||||
            children: [
 | 
			
		||||
              Text('Jump (to) Item (at)'),
 | 
			
		||||
            TextField(),
 | 
			
		||||
            // ElevatedButton(
 | 
			
		||||
            //   onPressed: AugmentClasses.ViewSpecsButton(context),
 | 
			
		||||
            //   child: Text('ViewSpecs'),
 | 
			
		||||
            // ),
 | 
			
		||||
          ] 
 | 
			
		||||
        ),
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
              SizedBox(height: 10),
 | 
			
		||||
              TextField(
 | 
			
		||||
                autofocus: true,
 | 
			
		||||
                decoration: InputDecoration(
 | 
			
		||||
                    labelText: '...',
 | 
			
		||||
                    border: OutlineInputBorder(),
 | 
			
		||||
                    suffixIcon: Icon(Icons.search)),
 | 
			
		||||
                onSubmitted: (value) {
 | 
			
		||||
                  print("onSubmitted: $value");
 | 
			
		||||
                  if (value.isNotEmpty) {
 | 
			
		||||
                    handleJump(value);
 | 
			
		||||
                    Navigator.of(context).pop();
 | 
			
		||||
                  }
 | 
			
		||||
  static ViewSpecsButton(context) {
 | 
			
		||||
    showDialog(
 | 
			
		||||
                },
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        actions: [
 | 
			
		||||
          TextButton(
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              Navigator.of(context).pop();
 | 
			
		||||
              // print('close pressed');
 | 
			
		||||
            },
 | 
			
		||||
            child: Text('close'),
 | 
			
		||||
          ),
 | 
			
		||||
          ElevatedButton(
 | 
			
		||||
              onPressed: () => ViewSpecsButton(context),
 | 
			
		||||
              child: Text('viewspecs'))
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    ).then((_) {
 | 
			
		||||
      AugmentClasses.enableIframePointerEvents();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future<void> ViewSpecsButton(context) async {
 | 
			
		||||
    //TODO: finish it
 | 
			
		||||
 | 
			
		||||
    bool blankLines = false;
 | 
			
		||||
    bool numbering = false;
 | 
			
		||||
    bool statementSignatures = false;
 | 
			
		||||
    AugmentClasses.disableIframePointerEvents();
 | 
			
		||||
    await showDialog(
 | 
			
		||||
        context: context,
 | 
			
		||||
      builder:(context) => AlertDialog(
 | 
			
		||||
        title: Text('Viewspecs(short)') ,
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
        builder: (context) => Container(
 | 
			
		||||
              height: 150,
 | 
			
		||||
              width: 300,
 | 
			
		||||
              child: AlertDialog(
 | 
			
		||||
                title: Text('Viewspecs(short)'),
 | 
			
		||||
                content: Container(
 | 
			
		||||
                  width: 400, // Set the width to simulate the Windows style
 | 
			
		||||
                  child: Column(
 | 
			
		||||
                    mainAxisSize: MainAxisSize.min,
 | 
			
		||||
                    crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                    children: [
 | 
			
		||||
                      Row(
 | 
			
		||||
                        children: [
 | 
			
		||||
                          // First section: Checkboxes for "Show"
 | 
			
		||||
                          Expanded(
 | 
			
		||||
                            child: Column(
 | 
			
		||||
                              crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Text('Show'),
 | 
			
		||||
                                Row(
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Text("y z"),
 | 
			
		||||
                                    Checkbox(
 | 
			
		||||
                                      value: blankLines,
 | 
			
		||||
                                      onChanged: (bool? value) {
 | 
			
		||||
                                        blankLines = value!;
 | 
			
		||||
                                      },
 | 
			
		||||
                                    ),
 | 
			
		||||
                                    Text('Blank lines'),
 | 
			
		||||
                                  ],
 | 
			
		||||
                                ),
 | 
			
		||||
                                Row(
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Text('m n'),
 | 
			
		||||
                                    Checkbox(
 | 
			
		||||
                                      value: numbering,
 | 
			
		||||
                                      onChanged: (bool? value) {
 | 
			
		||||
                                        numbering = value!;
 | 
			
		||||
                                      },
 | 
			
		||||
                                    ),
 | 
			
		||||
                                    Text('Numbering'),
 | 
			
		||||
                                  ],
 | 
			
		||||
                                ),
 | 
			
		||||
                                Row(
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Text('K L'),
 | 
			
		||||
                                    Checkbox(
 | 
			
		||||
                                      value: statementSignatures,
 | 
			
		||||
                                      onChanged: (bool? value) {
 | 
			
		||||
                                        statementSignatures = value!;
 | 
			
		||||
                                      },
 | 
			
		||||
                                    ),
 | 
			
		||||
                                    Text('Statement signatures'),
 | 
			
		||||
                                  ],
 | 
			
		||||
                                ),
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                          ),
 | 
			
		||||
                          // Second section: Numeric input for Outline, Levels, and Lines
 | 
			
		||||
                          Expanded(
 | 
			
		||||
                            child: Column(
 | 
			
		||||
                              crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Text('Outline'),
 | 
			
		||||
                                Row(
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Text('Levels'),
 | 
			
		||||
                                    SizedBox(width: 10),
 | 
			
		||||
                                    Container(
 | 
			
		||||
                                      width: 40,
 | 
			
		||||
                                      child: TextField(
 | 
			
		||||
                                        decoration: InputDecoration(
 | 
			
		||||
                                          isDense: true,
 | 
			
		||||
                                          border: OutlineInputBorder(),
 | 
			
		||||
                                        ),
 | 
			
		||||
                                        keyboardType: TextInputType.number,
 | 
			
		||||
                                      ),
 | 
			
		||||
                                    ),
 | 
			
		||||
                                  ],
 | 
			
		||||
                                ),
 | 
			
		||||
                                Row(
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Text('Lines'),
 | 
			
		||||
                                    SizedBox(width: 10),
 | 
			
		||||
                                    Container(
 | 
			
		||||
                                      width: 40,
 | 
			
		||||
                                      child: TextField(
 | 
			
		||||
                                        decoration: InputDecoration(
 | 
			
		||||
                                          isDense: true,
 | 
			
		||||
                                          border: OutlineInputBorder(),
 | 
			
		||||
                                        ),
 | 
			
		||||
                                        keyboardType: TextInputType.number,
 | 
			
		||||
                                      ),
 | 
			
		||||
                                    ),
 | 
			
		||||
                                  ],
 | 
			
		||||
                                ),
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                          ),
 | 
			
		||||
                        ],
 | 
			
		||||
                      ),
 | 
			
		||||
                      SizedBox(height: 20),
 | 
			
		||||
                      Row(
 | 
			
		||||
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                        children: [
 | 
			
		||||
                          ElevatedButton(onPressed: () {}, child: Text('OK')),
 | 
			
		||||
                          ElevatedButton(
 | 
			
		||||
                              onPressed: () {
 | 
			
		||||
                                Navigator.of(context).pop();
 | 
			
		||||
                              },
 | 
			
		||||
                              child: Text('Cancel')),
 | 
			
		||||
                          ElevatedButton(
 | 
			
		||||
                              onPressed: () {}, child: Text('Reset')),
 | 
			
		||||
                          ElevatedButton(onPressed: () {}, child: Text('Help')),
 | 
			
		||||
                        ],
 | 
			
		||||
                      ),
 | 
			
		||||
                    ],
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            )).then((_) {
 | 
			
		||||
      AugmentClasses.enableIframePointerEvents();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void disableIframePointerEvents() {
 | 
			
		||||
    final iframes = html.document.getElementsByTagName('iframe');
 | 
			
		||||
    for (var iframe in iframes) {
 | 
			
		||||
      if (iframe is html.Element) {
 | 
			
		||||
        iframe.style.pointerEvents = 'none'; // Disable pointer events
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void enableIframePointerEvents() {
 | 
			
		||||
    final iframes = html.document.getElementsByTagName('iframe');
 | 
			
		||||
    for (var iframe in iframes) {
 | 
			
		||||
      if (iframe is html.Element) {
 | 
			
		||||
        iframe.style.pointerEvents = 'auto'; // Re-enable pointer events
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,13 @@
 | 
			
		|||
import 'package:crab_ui/contact.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter/rendering.dart';
 | 
			
		||||
import 'home_page.dart';
 | 
			
		||||
import 'api_service.dart';
 | 
			
		||||
import 'dart:html' as html;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
  WidgetsFlutterBinding.ensureInitialized();
 | 
			
		||||
  // debugPaintSizeEnabled = true;
 | 
			
		||||
  runApp(const HyM());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue