Compare commits
9 Commits
bde05197ae
...
71707bd1c0
Author | SHA1 | Date | |
---|---|---|---|
71707bd1c0 | |||
b961be3e8b | |||
c025fbe07a | |||
214a60ce1b | |||
07091eb708 | |||
dda581bda0 | |||
433394a74a | |||
2465201b0b | |||
4d75674e8e |
165
lib/Compose.dart
Normal file
165
lib/Compose.dart
Normal file
@ -0,0 +1,165 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:super_editor/super_editor.dart';
|
||||
import 'package:super_editor_markdown/super_editor_markdown.dart';
|
||||
|
||||
class ComposeEmail extends StatefulWidget {
|
||||
final VoidCallback onClose;
|
||||
final Function(String) onMinimize;
|
||||
final Function(String) onSendMessage;
|
||||
const ComposeEmail({
|
||||
Key? key,
|
||||
required this.onMinimize,
|
||||
required this.onClose,
|
||||
required this.onSendMessage,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ComposeEmailState createState() => _ComposeEmailState();
|
||||
}
|
||||
|
||||
class _ComposeEmailState extends State<ComposeEmail> {
|
||||
// if one were to alter a mutableDocument, one should only alter the document through EditRequest to the Editor
|
||||
late final Editor _editor;
|
||||
late final MutableDocument _document;
|
||||
late final MutableDocumentComposer _composer;
|
||||
TextEditingController _emailRecipientController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_document = MutableDocument(nodes: [
|
||||
ParagraphNode(
|
||||
id: Editor.createNodeId(),
|
||||
text: AttributedText("hello world!"),
|
||||
)
|
||||
]);
|
||||
_composer = MutableDocumentComposer();
|
||||
_editor =
|
||||
createDefaultDocumentEditor(document: _document!, composer: _composer!);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_editor.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned(
|
||||
bottom: 10.0,
|
||||
right: 10.0,
|
||||
child: Material(
|
||||
elevation: 8.0,
|
||||
child: Container(
|
||||
width: 600.0,
|
||||
height: 616.0,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(children: [
|
||||
AppBar(
|
||||
title: const Text("new message"),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
//TODO: implement minimize, and submit email to drafts
|
||||
widget.onClose();
|
||||
},
|
||||
icon: Icon(Icons.minimize, color: Colors.grey[600])),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
//TODO: implement that maximizing
|
||||
},
|
||||
icon: Icon(Icons.maximize, color: Colors.grey[600])),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
widget.onClose();
|
||||
},
|
||||
icon: Icon(Icons.close, color: Colors.grey[600])),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
// TODO: WHEN NOT CLICKED ITS ONLY A TEXTFIELD WITH A HINT, AND THEN WHEN CLICKED THIS
|
||||
width: 500.0,
|
||||
height: 40.0,
|
||||
child: Row(
|
||||
children: [
|
||||
TextButton(onPressed: () {}, child: Text("To:")),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _emailRecipientController,
|
||||
),
|
||||
),
|
||||
TextButton(onPressed: () {}, child: Text("Cc")),
|
||||
SizedBox(
|
||||
width: 4.0,
|
||||
),
|
||||
TextButton(onPressed: () {}, child: Text("Bcc")),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
//here the widget goes
|
||||
child: SuperEditor(
|
||||
editor: _editor!,
|
||||
plugins: {MarkdownInlineUpstreamSyntaxPlugin()},
|
||||
stylesheet: Stylesheet(
|
||||
rules: [StyleRule(BlockSelector.all, (doc, docNode) {
|
||||
return {
|
||||
Styles.maxWidth: 640.0,
|
||||
Styles.padding: const CascadingPadding.symmetric(horizontal: 24),
|
||||
Styles.textStyle: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 15,
|
||||
height: 1.4,
|
||||
),
|
||||
};
|
||||
}),],
|
||||
inlineTextStyler: defaultInlineTextStyler)
|
||||
),
|
||||
)
|
||||
])),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class OverlayService {
|
||||
static final OverlayService _instance = OverlayService._internal();
|
||||
factory OverlayService() => _instance;
|
||||
OverlayService._internal();
|
||||
OverlayEntry? _overlayEntry;
|
||||
|
||||
void showPersistentWidget(BuildContext context) {
|
||||
if (_overlayEntry != null) {
|
||||
print("overlay visible");
|
||||
return;
|
||||
}
|
||||
_overlayEntry = OverlayEntry(
|
||||
builder: (context) => ComposeEmail(
|
||||
onClose: () {
|
||||
removeComposeWidget();
|
||||
},
|
||||
onMinimize: (String content) {
|
||||
minimizeComposeWidget(content);
|
||||
},
|
||||
onSendMessage: (message) {
|
||||
print('msg senf form overlay $message');
|
||||
},
|
||||
));
|
||||
Navigator.of(context).overlay?.insert(_overlayEntry!);
|
||||
print("inserted into tree");
|
||||
}
|
||||
|
||||
void removeComposeWidget() {
|
||||
_overlayEntry?.remove();
|
||||
_overlayEntry = null;
|
||||
}
|
||||
|
||||
String minimizeComposeWidget(String content) {
|
||||
//just hide the overlay but keep its info
|
||||
return '';
|
||||
}
|
||||
}
|
@ -101,6 +101,7 @@ class _SonicEmailViewState extends State<SonicEmailView> {
|
||||
onJumpToNumbering: _scrollToNumber,
|
||||
onViewspecs: _handleViewspecs,
|
||||
onFiltering: _handleFiltering,
|
||||
emails: [widget.email.name], subject: '', rootAugment: null,
|
||||
),
|
||||
Row(
|
||||
// title of email
|
||||
|
@ -90,6 +90,11 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
List<String> getThreads() {
|
||||
return widget.thread;
|
||||
}
|
||||
|
||||
void _add2Tree(AugmentTree tree, md.Element node2add) {
|
||||
// adds node to its corresponding place
|
||||
AugmentTree newNode = AugmentTree();
|
||||
|
@ -9,13 +9,22 @@ class CollapsableEmails extends StatefulWidget {
|
||||
CollapsableEmails(
|
||||
{required this.thread,
|
||||
required this.threadMarkdown,
|
||||
required this.threadIDs, String? targetJumpNumbering, String? targetViewspecs, String? targetFiltering});
|
||||
required this.threadIDs, String? targetJumpNumbering, String? targetViewspecs, String? targetFiltering, required String nameOfDocument});
|
||||
|
||||
get getThreads => null;
|
||||
|
||||
get getAugmentRoot => null;
|
||||
|
||||
@override
|
||||
State<CollapsableEmails> createState() => _CollapsableEmailsState();
|
||||
}
|
||||
|
||||
class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
|
||||
List<String> getThreads() {
|
||||
return widget.thread;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(body: Text("collapsable stud"));
|
||||
|
@ -176,22 +176,9 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
AugmentTree temp = AugmentTree();
|
||||
temp.data = node.textContent;
|
||||
temp.ogTag = node.tag;
|
||||
if (node.tag == 'h1') {
|
||||
// make this O(1)
|
||||
//why did i do this???
|
||||
if ( hirarchyDict.containsKey(node.tag)) {
|
||||
_add2Tree(zoomTreeRoot, node);
|
||||
} else if (node.tag == 'h2') {
|
||||
// i dont add any since i dont have it, maybe the function makes sense
|
||||
_add2Tree(zoomTreeRoot, node); // fix this
|
||||
} else if (node.tag == 'h3') {
|
||||
_add2Tree(zoomTreeRoot, node);
|
||||
} else if (node.tag == 'h4') {
|
||||
_add2Tree(zoomTreeRoot, node); // change to temp
|
||||
} else if (node.tag == 'h5') {
|
||||
_add2Tree(zoomTreeRoot, node);
|
||||
} else if (node.tag == 'h6') {
|
||||
_add2Tree(zoomTreeRoot, node); // fix this
|
||||
} else if (node.tag == 'p' || node.tag == 'ul' || node.tag == 'li') {
|
||||
_add2Tree(zoomTreeRoot, node); // fix this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ class _EmailViewState extends State<EmailView> {
|
||||
onJumpToNumbering: _scrollToNumber,
|
||||
onViewspecs: _viewSpecs,
|
||||
onFiltering: _filteringQuery,
|
||||
emails: widget.messages, subject: '', rootAugment: null,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:ui_web' as ui;
|
||||
import 'augment.dart';
|
||||
// import 'dart:js_interop' as js; //eventually for manipulating css
|
||||
import 'collapsableEmails.dart';
|
||||
import 'api_service.dart';
|
||||
|
||||
@ -35,8 +34,30 @@ class _EmailViewState extends State<EmailView> {
|
||||
late Key iframeKey;
|
||||
late String currentContent;
|
||||
late String viewTypeId; //make this a list too???
|
||||
Future<List<Map<String, dynamic>>>? _markerPositionsFuture;
|
||||
// TextEditingController _jumpController = TextEditingController();
|
||||
late EmailToolbar toolbarInstance = EmailToolbar(
|
||||
onJumpToNumbering: _handleJumpRequest,
|
||||
onViewspecs: _handleViewspecsRequest,
|
||||
onButtonPressed: () => {print("email tool bar pressed")},
|
||||
onFiltering: _handleFiltering,
|
||||
emails: widget.messages,
|
||||
subject: widget.subject,
|
||||
rootAugment: localCollapsable.getAugmentRoot(),
|
||||
);
|
||||
|
||||
late CollapsableEmails localCollapsable = CollapsableEmails(
|
||||
//change here
|
||||
thread: widget.messages, //this wont work in serializable
|
||||
// threadHTML: widget.emailContent, // old html
|
||||
threadMarkdown: widget.emailContent,
|
||||
threadIDs: widget.id,
|
||||
targetJumpNumbering: _targetJumpNumbering,
|
||||
targetViewspecs: _targetViewspecs,
|
||||
targetFiltering: _queryFiltering,
|
||||
nameOfDocument: widget.subject,
|
||||
);
|
||||
|
||||
|
||||
final hardcodedMarkers = [
|
||||
{'id': 'marker1', 'x': 50, 'y': 100},
|
||||
{'id': 'marker2', 'x': 150, 'y': 200},
|
||||
@ -78,11 +99,11 @@ class _EmailViewState extends State<EmailView> {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: void _invisibility(String ) //to make purple numbers not visible
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ApiService.currThreadID = widget.id;
|
||||
// AugmentClasses localAugment = AugmentClasses(localCollapsable);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.name),
|
||||
@ -91,12 +112,7 @@ class _EmailViewState extends State<EmailView> {
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
EmailToolbar(
|
||||
onJumpToNumbering: _handleJumpRequest,
|
||||
onViewspecs: _handleViewspecsRequest,
|
||||
onButtonPressed: () => {print("email tool bar pressed")},
|
||||
onFiltering: _handleFiltering,
|
||||
),
|
||||
toolbarInstance,
|
||||
Row(
|
||||
// title of email
|
||||
children: [
|
||||
@ -133,16 +149,7 @@ class _EmailViewState extends State<EmailView> {
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: CollapsableEmails(
|
||||
//change here
|
||||
thread: widget.messages, //this wont work in serializable
|
||||
// threadHTML: widget.emailContent, // old html
|
||||
threadMarkdown: widget.emailContent,
|
||||
threadIDs: widget.id,
|
||||
targetJumpNumbering: _targetJumpNumbering,
|
||||
targetViewspecs: _targetViewspecs,
|
||||
targetFiltering: _queryFiltering,
|
||||
),
|
||||
child: localCollapsable,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -5,6 +5,7 @@ import 'structs.dart';
|
||||
import 'api_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'email.dart';
|
||||
import 'Compose.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
@override
|
||||
@ -44,50 +45,51 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
});
|
||||
}
|
||||
|
||||
void _showOptionsSearchDialog () async {
|
||||
void _showOptionsSearchDialog() async {
|
||||
List<String> folders = await apiService.fetchFolders();
|
||||
|
||||
if (mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Choose an Option'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: folders.map((option) {
|
||||
return ListTile(
|
||||
title: Text(option),
|
||||
leading: Radio<String>(
|
||||
value: option,
|
||||
groupValue: _selectedOption, // Bind with _selectedOption
|
||||
onChanged: (String? value) {
|
||||
setState(() {
|
||||
_selectedOption = value;
|
||||
});
|
||||
Navigator.of(context).pop(); // Close the dialog on selection
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
actions: <Widget>[
|
||||
ElevatedButton(
|
||||
child: Text('Submit'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text('You selected: $_selectedOption'),
|
||||
));
|
||||
},
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Choose an Option'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: folders.map((option) {
|
||||
return ListTile(
|
||||
title: Text(option),
|
||||
leading: Radio<String>(
|
||||
value: option,
|
||||
groupValue: _selectedOption, // Bind with _selectedOption
|
||||
onChanged: (String? value) {
|
||||
setState(() {
|
||||
_selectedOption = value;
|
||||
});
|
||||
Navigator.of(context)
|
||||
.pop(); // Close the dialog on selection
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);}
|
||||
actions: <Widget>[
|
||||
ElevatedButton(
|
||||
child: Text('Submit'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text('You selected: $_selectedOption'),
|
||||
));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Remove a tab
|
||||
void _removeTab(int index) {
|
||||
if (_tabs[index] != 'Emails') {
|
||||
@ -119,7 +121,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
body: ListView.separated(
|
||||
itemCount: result.length,
|
||||
itemBuilder: (context, index) {
|
||||
final SerializableMessage email = result[index];
|
||||
final SerializableMessage email = result[index];
|
||||
return ListTile(
|
||||
title: Text(email.from,
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
@ -132,27 +134,24 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
// print('tapped');
|
||||
// List<String> emailContent =
|
||||
// await apiService.fetchEmailContent([email.id], email.list);
|
||||
//call the foldable
|
||||
//call the foldable
|
||||
|
||||
List<String> emailContent = // list of the html
|
||||
await apiService.fetchEmailContent([email.id], email.list);
|
||||
await apiService
|
||||
.fetchEmailContent([email.id], email.list);
|
||||
// List<String> emailIds = email.messages;
|
||||
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>SonicEmailView(
|
||||
email: email,
|
||||
emailHTML: emailContent[0])
|
||||
),
|
||||
builder: (context) => SonicEmailView(
|
||||
email: email, emailHTML: emailContent[0])),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => Divider(),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -170,7 +169,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.onPrimary,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 20, 0 , 20),
|
||||
padding: const EdgeInsets.fromLTRB(0, 20, 0, 20),
|
||||
child: Scaffold(
|
||||
key: _scaffoldKey,
|
||||
drawer: FolderDrawer(
|
||||
@ -195,6 +194,12 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: Icon(Icons.edit_note_sharp),
|
||||
onTap: () {
|
||||
OverlayService()
|
||||
.showPersistentWidget(context);
|
||||
}),
|
||||
ListTile(
|
||||
leading: Icon(Icons.home),
|
||||
onTap: () {
|
||||
@ -219,7 +224,8 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
child: Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.close, color: Colors.white),
|
||||
icon:
|
||||
Icon(Icons.close, color: Colors.white),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isSidebarOpen = false;
|
||||
@ -256,7 +262,8 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
),
|
||||
onSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
_performSearch(value, _selectedOption);
|
||||
_performSearch(
|
||||
value, _selectedOption);
|
||||
}
|
||||
//this is the input box i mentioned
|
||||
// if (value == '') {
|
||||
@ -314,8 +321,10 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
Text(entry.value),
|
||||
if (entry.value != 'Emails')
|
||||
GestureDetector(
|
||||
onTap: () => _removeTab(entry.key),
|
||||
child: Icon(Icons.close, size: 16),
|
||||
onTap: () =>
|
||||
_removeTab(entry.key),
|
||||
child: Icon(Icons.close,
|
||||
size: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -333,14 +342,17 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_emailPageKey.currentState!.isBackDisabled ? null: _emailPageKey.currentState
|
||||
?.updatePagenation('back');
|
||||
_emailPageKey.currentState!.isBackDisabled
|
||||
? null
|
||||
: _emailPageKey.currentState
|
||||
?.updatePagenation('back');
|
||||
},
|
||||
child: Icon(Icons.navigate_before),
|
||||
),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final emailState = _emailPageKey.currentState;
|
||||
final emailState =
|
||||
_emailPageKey.currentState;
|
||||
if (emailState == null) {
|
||||
// Schedule a rebuild once the state is available
|
||||
Future.microtask(() => setState(() {}));
|
||||
@ -348,8 +360,10 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
}
|
||||
|
||||
return ValueListenableBuilder<int>(
|
||||
valueListenable: emailState.currentPageNotifier,
|
||||
builder: (context, value, _) => Text('$value'),
|
||||
valueListenable:
|
||||
emailState.currentPageNotifier,
|
||||
builder: (context, value, _) =>
|
||||
Text('$value'),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -1,15 +1,22 @@
|
||||
import 'dart:convert';
|
||||
// import 'package:crab_ui/api_service.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'api_service.dart';
|
||||
import 'home_page.dart';
|
||||
// import 'home_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
// import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
// import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
|
||||
class AuthService {
|
||||
class AuthService extends ChangeNotifier {
|
||||
Future<bool> isUserLoggedIn() async {
|
||||
ApiService.ip = '192.168.2.38';
|
||||
ApiService.port = '3001';
|
||||
print("setted up");
|
||||
|
||||
return true;
|
||||
try {
|
||||
final response =
|
||||
await http.get(Uri.http('localhost:6823', 'read-config'));
|
||||
@ -83,6 +90,7 @@ class LoginPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
//entry point
|
||||
@override
|
||||
_SplashScreenState createState() => _SplashScreenState();
|
||||
}
|
||||
@ -92,19 +100,24 @@ class _SplashScreenState extends State<SplashScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_checkLoginStatus();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_checkLoginStatus();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _checkLoginStatus() async {
|
||||
// SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// print(prefs);
|
||||
// bool isLoggedIn = prefs.getBool('isLoggedIn') ?? false;
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
bool isLoggedIn = await _authService.isUserLoggedIn();
|
||||
print("is loogeed in $isLoggedIn");
|
||||
print("is logged in $isLoggedIn");
|
||||
if (isLoggedIn) {
|
||||
Navigator.pushReplacementNamed(context, '/home');
|
||||
context.go("/home");
|
||||
// Navigator.pushReplacementNamed(context, '/home');
|
||||
} else {
|
||||
Navigator.pushReplacementNamed(context, '/login');
|
||||
context.go("/login");
|
||||
// Navigator.pushReplacementNamed(context, '/login');
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +125,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Scaffold(
|
||||
body: Center(child: CircularProgressIndicator()),
|
||||
body: Center(child: CircularProgressIndicator()), //nothing happens
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -132,6 +145,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
Future<bool> setIp(String ip) async {
|
||||
//this is not done :sob: :skull:
|
||||
// _configManager.setField("api_addr", ip);
|
||||
return false;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
import 'package:markdown_widget/markdown_widget.dart';
|
||||
import 'api_service.dart';
|
||||
import 'structs.dart';
|
||||
|
||||
class Routinghandler extends StatefulWidget {
|
||||
Routinghandler(String link, emailID) {
|
||||
@ -133,6 +134,7 @@ class Routinghandler extends StatefulWidget {
|
||||
class _RoutingHandlerState extends State<Routinghandler> {
|
||||
List<String> markdownContent = [];
|
||||
bool _isLoaded = false;
|
||||
AugmentTree? aug;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -143,13 +145,15 @@ class _RoutingHandlerState extends State<Routinghandler> {
|
||||
|
||||
Future<void> _loadMarkdown() async {
|
||||
String folder = ApiService.currFolder;
|
||||
// print(folder);
|
||||
print(widget.getEmailID());
|
||||
String emailID = widget.emailID;
|
||||
print("inside _loadMarkdown in routinghandler $emailID");
|
||||
markdownContent =
|
||||
await ApiService().fetchMarkdownContent([emailID], "INBOX");
|
||||
await ApiService().fetchMarkdownContent([emailID], folder);
|
||||
// print(markdownContent);
|
||||
aug = AugmentTree.fromMD(markdownContent[0]);
|
||||
aug!.addNumbering();
|
||||
|
||||
setState(() {
|
||||
_isLoaded = true;
|
||||
});
|
||||
@ -162,44 +166,58 @@ class _RoutingHandlerState extends State<Routinghandler> {
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("Routing Handler"),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
GoRouter.of(context).go('/home');
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back_ios)),
|
||||
),
|
||||
body: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: 100,
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.7,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child:MarkdownBlock(data: markdownContent[0]))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LinkViewer extends StatefulWidget {
|
||||
const LinkViewer({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _LinkViewerState();
|
||||
}
|
||||
|
||||
class _LinkViewerState extends State<LinkViewer> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// this should be a class that opens a popup of the email on the view it wants
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('url viewer'),
|
||||
title: Text("Routing Handler"),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
GoRouter.of(context).go('/home');
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back_ios)),
|
||||
),
|
||||
body: Column(
|
||||
children: [],
|
||||
));
|
||||
body: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: 100,
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.7,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
//inside here put the bunch rows
|
||||
//make rows of markdownBlocks, but firstly i need to conveert the content into a tree
|
||||
// child:MarkdownBlock(data: markdownContent[0])
|
||||
|
||||
child: Column(children: [
|
||||
for (int i = 0; i < this.aug!.children![0]!.children.length; i++)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// if (leftNumbering)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 10, 5, 0),
|
||||
child: Text(
|
||||
aug!.children![0]!.children![i]!.numbering,
|
||||
style: TextStyle(
|
||||
color: Color(Colors.purple[400]!.value)),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Wrap(children: [
|
||||
MarkdownBlock(
|
||||
data: aug!.children![0]!.children![i]!.data ?? ''),
|
||||
],)
|
||||
)
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 10, 5, 0),
|
||||
child: Text(
|
||||
aug!.children![0]!.children![i]!.numbering,
|
||||
style: TextStyle(
|
||||
color: Color(Colors.purple[400]!.value)),
|
||||
),
|
||||
),
|
||||
]),
|
||||
]))));
|
||||
}
|
||||
}
|
||||
|
100
lib/structs.dart
100
lib/structs.dart
@ -1,6 +1,7 @@
|
||||
//data structures
|
||||
|
||||
import 'dart:typed_data';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
|
||||
class GetThreadResponse {
|
||||
final int id;
|
||||
@ -157,6 +158,94 @@ class AugmentTree {
|
||||
AugmentTree? parent;
|
||||
String ogTag = '';
|
||||
String numbering = '';
|
||||
Map<String, int> hirarchyDict = {
|
||||
"h1": 1,
|
||||
"h2": 2,
|
||||
"h3": 3,
|
||||
"h4": 4,
|
||||
"h5": 5,
|
||||
"h6": 6,
|
||||
"p": 8,
|
||||
"ul": 8,
|
||||
"li": 8,
|
||||
};
|
||||
|
||||
AugmentTree();
|
||||
|
||||
AugmentTree.fromMD(String rawMD) {
|
||||
//makes raw MD into an augmentTree
|
||||
print("started markdown2tree");
|
||||
final List<md.Node> nakedList = md.Document().parseLines(rawMD.split(
|
||||
'\n')); //emails md is the index of the email in the thread, since this only handles one thus it shall be removed
|
||||
// AugmentTree zoomTreeRoot = AugmentTree();
|
||||
for (var node in nakedList) {
|
||||
//maybe do an add function, but isn't this it?
|
||||
if (node is md.Element) {
|
||||
AugmentTree temp = AugmentTree();
|
||||
temp.data = node.textContent;
|
||||
temp.ogTag = node.tag;
|
||||
if (hirarchyDict.containsKey(node.tag)) {
|
||||
// make this O(1)
|
||||
_add2Tree(this, node);
|
||||
// print(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.addNumbering();
|
||||
}
|
||||
|
||||
void _add2Tree(AugmentTree tree, md.Element node2add) {
|
||||
// adds node to its corresponding place
|
||||
AugmentTree newNode = AugmentTree();
|
||||
newNode.setData(node2add.textContent);
|
||||
newNode.ogTag = node2add.tag;
|
||||
// cases,
|
||||
//1. a node that comes is lower than the root.children last, if so it goes beneath it
|
||||
if (tree.children.isEmpty) {
|
||||
// new level to be created when totally empty
|
||||
tree.children.add(newNode);
|
||||
newNode.parent = tree;
|
||||
} else if (tree.children.isNotEmpty &&
|
||||
tree.children.last.ogTag.isNotEmpty) {
|
||||
if ((hirarchyDict[node2add.tag] ??
|
||||
-1) < // e.g. new node is h1 and old is h2, heapify
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1)) {
|
||||
//have to figure out the borthers
|
||||
//assuming it all goes right
|
||||
if ((hirarchyDict[node2add.tag] ?? -1) == -1 ||
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1) == -1) {
|
||||
print(
|
||||
'failed and got -1 at _add2Tree \n ${hirarchyDict[node2add.tag] ?? -1} < ${hirarchyDict[tree.children.last.ogTag] ?? -1}');
|
||||
return;
|
||||
} else if (tree.children.last.parent == null) {
|
||||
// becomes the new top level
|
||||
for (AugmentTree brother in tree.children) {
|
||||
brother.parent = newNode;
|
||||
}
|
||||
tree.children = [newNode];
|
||||
} else {
|
||||
newNode.parent = tree;
|
||||
tree.children.add(newNode);
|
||||
}
|
||||
} else if ((hirarchyDict[node2add.tag] ??
|
||||
-1) > // go down e.g. new node is h3 and old is h2 or something
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1)) {
|
||||
if ((hirarchyDict[node2add.tag] ?? -1) == -1 ||
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1) == -1) {
|
||||
print(
|
||||
'failed and got -1 at _add2Tree \n ${hirarchyDict[node2add.tag] ?? -1} > ${hirarchyDict[tree.children.last.ogTag] ?? -1}');
|
||||
print("-1 ${tree.children.last.ogTag}");
|
||||
return;
|
||||
}
|
||||
|
||||
_add2Tree(tree.children.last, node2add);
|
||||
} else if ((hirarchyDict[node2add.tag] ?? -1) ==
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1)) {
|
||||
tree.children.add(newNode);
|
||||
newNode.parent = tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setData(String data) {
|
||||
this.data = data;
|
||||
@ -176,7 +265,7 @@ class AugmentTree {
|
||||
parentIsLettered = false;
|
||||
} else {
|
||||
parentIsLettered = prefix.runes.last >= 'a'.runes.first &&
|
||||
prefix.runes.last <= 'z'.runes.first;
|
||||
prefix.runes.last <= 'z'.runes.first;
|
||||
}
|
||||
|
||||
if (prefix.isEmpty) {
|
||||
@ -197,14 +286,19 @@ class AugmentTree {
|
||||
}
|
||||
}
|
||||
|
||||
//perhaps make a struct that builds augment tree, since its so complex and needs to be like recursive
|
||||
|
||||
class MarkdownParsed{
|
||||
class MarkdownParsed {
|
||||
//struct for holding the MD given in endpoint //not used
|
||||
final String text;
|
||||
MarkdownParsed({required this.text});
|
||||
factory MarkdownParsed.fromJson(Map<String, String> json){
|
||||
factory MarkdownParsed.fromJson(Map<String, String> json) {
|
||||
return MarkdownParsed(
|
||||
text: json['md'] ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//should make an md to tree class/struct
|
||||
|
||||
// make a for loop of rows with markdown
|
||||
|
@ -31,6 +31,8 @@ dependencies:
|
||||
markdown_widget: ^2.3.2+8
|
||||
markdown: ^7.3.0
|
||||
go_router: ^16.0.0
|
||||
super_editor: ^0.3.0-dev.27
|
||||
super_editor_markdown: 0.1.8
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user