Compare commits

...

3 commits

10 changed files with 149 additions and 190 deletions

View file

@ -28,6 +28,14 @@ android {
targetSdk = flutter.targetSdkVersion targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode versionCode = flutter.versionCode
versionName = flutter.versionName versionName = flutter.versionName
ndk {
abiFilters.addAll(listOf("arm64-v8a", "x86_64"))
}
sourceSets {
getByName("main") {
jniLibs.srcDirs("src/main/jniLibs")
}
}
} }
buildTypes { buildTypes {

View file

@ -49,6 +49,7 @@ class ApiService {
return []; return [];
} }
} }
Future<List<GetThreadResponse>> fetchEmailsFromFolderReversed( Future<List<GetThreadResponse>> fetchEmailsFromFolderReversed(
String folder, int pagenitaion) async { String folder, int pagenitaion) async {
try { try {
@ -57,7 +58,7 @@ class ApiService {
'limit': '50', 'limit': '50',
'offset': pagenitaion.toString(), 'offset': pagenitaion.toString(),
}); });
var response = await http.get(url); var response = await http.get(url);
List<GetThreadResponse> allEmails = []; List<GetThreadResponse> allEmails = [];
@ -82,6 +83,7 @@ class ApiService {
return []; return [];
} }
} }
Future<void> fetchThreads( Future<void> fetchThreads(
//populates allEmails, which is the List that contains all the emails in a thread //populates allEmails, which is the List that contains all the emails in a thread
int threadId, int threadId,
@ -214,7 +216,6 @@ class ApiService {
// SerializableMessage firstMail = mailsInSerializable[0]; // SerializableMessage firstMail = mailsInSerializable[0];
try { try {
for (SerializableMessage mail in mailsInSerializable) { for (SerializableMessage mail in mailsInSerializable) {
Map<String, String> requestBody = { Map<String, String> requestBody = {
@ -223,18 +224,19 @@ class ApiService {
'to': "Deleted Crabmail", 'to': "Deleted Crabmail",
}; };
var response = await http.post( var response = await http.post(
url, url,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: jsonEncode(requestBody), body: jsonEncode(requestBody),
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
print('response body ${response.body}'); print('response body ${response.body}');
return true; return true;
} else { } else {
print('error ${response.statusCode} ${response.body}'); print('error ${response.statusCode} ${response.body}');
}} }
}
} catch (e) { } catch (e) {
print("failed trying to post move_email, with error: $e"); print("failed trying to post move_email, with error: $e");
} }
@ -251,6 +253,17 @@ class ApiService {
return []; return [];
} }
} }
Future<List<String>> fetchContacts() async {
try {
var url = Uri.http('$ip:$port', 'get_contacts');
var response = await http.get(url);
return List<String>.from(json.decode(response.body));
} catch (e) {
print('fetchFolders caught error: $e');
return [];
}
}
Future<void> createFolder(String folderName) async { Future<void> createFolder(String folderName) async {
var url = Uri.http('$ip:$port', 'create_folder'); var url = Uri.http('$ip:$port', 'create_folder');
@ -416,6 +429,7 @@ class ApiService {
try { try {
var url = Uri.http( var url = Uri.http(
'$ip:$port', 'post_seen_thread', {'id': thread_id.toString()}); '$ip:$port', 'post_seen_thread', {'id': thread_id.toString()});
print("url: $url");
var response = await http.get(url); var response = await http.get(url);
if (response.statusCode == 200) { if (response.statusCode == 200) {
var result = response.body; var result = response.body;
@ -430,6 +444,7 @@ class ApiService {
try { try {
var url = Uri.http( var url = Uri.http(
'$ip:$port', 'post_unseen_thread', {'id': thread_id.toString()}); '$ip:$port', 'post_unseen_thread', {'id': thread_id.toString()});
print("url: $url");
var response = await http.get(url); var response = await http.get(url);
if (response.statusCode == 200) { if (response.statusCode == 200) {
var result = response.body; var result = response.body;

View file

@ -1,6 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// import 'package:http/http.dart' as http;
// import 'package:flutter_html/flutter_html.dart';
class ContactsPage extends StatefulWidget { class ContactsPage extends StatefulWidget {
const ContactsPage({super.key}); const ContactsPage({super.key});

View file

@ -78,6 +78,8 @@ class _EmailListScreenState extends State<EmailListScreen>
selectedEmails[email].seen = read; selectedEmails[email].seen = read;
ApiService() ApiService()
.markAsSeen(selectedEmails[email].id); //the remote or .json .markAsSeen(selectedEmails[email].id); //the remote or .json
print(selectedEmails[email].id);
} }
} else { } else {
//unread //unread
@ -85,7 +87,7 @@ class _EmailListScreenState extends State<EmailListScreen>
selectedEmails[email].seen = read; selectedEmails[email].seen = read;
ApiService() ApiService()
.markAsUnseen(selectedEmails[email].id); //the remote or .json .markAsUnseen(selectedEmails[email].id); //the remote or .json
print(selectedEmails[email].subject); print(selectedEmails[email].id);
} }
} }
}); });

View file

@ -44,19 +44,18 @@ class _EmailViewState extends State<EmailView> {
subject: widget.subject, subject: widget.subject,
rootAugment: localCollapsable.getAugmentRoot(), 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,
);
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 = [ final hardcodedMarkers = [
{'id': 'marker1', 'x': 50, 'y': 100}, {'id': 'marker1', 'x': 50, 'y': 100},
@ -75,6 +74,8 @@ class _EmailViewState extends State<EmailView> {
.emailContent; //html of the email/ actually entire thread, gives me little space to play in between .emailContent; //html of the email/ actually entire thread, gives me little space to play in between
// i wonder if the other attributes change? because if so i have to add like some zooms in and out of the emails, as in collapse // i wonder if the other attributes change? because if so i have to add like some zooms in and out of the emails, as in collapse
// _registerViewFactory(currentContent); // _registerViewFactory(currentContent);
print("email content in Collapsable ${widget.emailContent}");
} }
void _scrollToNumber(String spanId) { void _scrollToNumber(String spanId) {
@ -99,7 +100,6 @@ class _EmailViewState extends State<EmailView> {
}); });
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
ApiService.currThreadID = widget.id; ApiService.currThreadID = widget.id;

View file

@ -1,4 +1,5 @@
import 'package:crab_ui/sonicEmailView.dart'; import 'package:crab_ui/sonicEmailView.dart';
import 'package:go_router/go_router.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'folder_drawer.dart'; import 'folder_drawer.dart';
@ -223,14 +224,22 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
leading: Icon(Icons.home), leading: Icon(Icons.home),
onTap: () { onTap: () {
// Navigate to Home // Navigate to Home
context.go("/home");
}, },
), ),
ListTile( // ListTile(
leading: Icon(Icons.settings), // leading: Icon(Icons.settings),
onTap: () { // onTap: () {
// Navigate to Settings // // Navigate to Settings
}, // },
), // ),
// ListTile(
// leading: Icon(Icons.contact_mail),
// onTap: () {
// // Navigate to Contacts
// },
// ),
ListTile( ListTile(
leading: Icon(Icons.email), leading: Icon(Icons.email),
onTap: () { onTap: () {
@ -534,8 +543,9 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
"Selected folder: $selectedFolder"); "Selected folder: $selectedFolder");
// Store the selected folder or perform any action // Store the selected folder or perform any action
// ApiService.currFolder = selectedFolder!; // ApiService.currFolder = selectedFolder!;
_emailPageKey.currentState! //the one selected _emailPageKey
.moveSelectedOfFolder(selectedFolder!); .currentState! //the one selected
.moveSelectedOfFolder(selectedFolder!);
_overlayEntry _overlayEntry
?.remove(); ?.remove();
} else { } else {

View file

@ -12,21 +12,21 @@ import 'package:flutter/services.dart' show rootBundle;
class AuthService extends ChangeNotifier { class AuthService extends ChangeNotifier {
Future<bool> isUserLoggedIn() async { Future<bool> isUserLoggedIn() async {
ApiService.ip = '192.168.2.38'; // ApiService.ip = '127.0.0.1';
ApiService.port = '3001'; // ApiService.port = '3001';
print("setted up"); // print("setted up");
return true; // return true;
try { try {
final response = final response =
await http.get(Uri.http('localhost:6823', 'read-config')); await http.get(Uri.http('127.0.0.1:6767', 'login_check'));
// await http.get(Uri.parse('http://localhost:6823/read-config'));
print(response.statusCode); print(response.statusCode);
print(response.body); print(response.body);
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
// return data['config']; // print(data['state']);
// return true;
try { try {
var url = Uri.http('${data['ip']}:${data['port']}', 'is_logged_in'); var url = Uri.http('${data['ip']}:${data['port']}', 'is_logged_in');
var response = await http.get(url); var response = await http.get(url);
@ -106,18 +106,25 @@ class _SplashScreenState extends State<SplashScreen> {
} }
Future<void> _checkLoginStatus() async { Future<void> _checkLoginStatus() async {
// SharedPreferences prefs = await SharedPreferences.getInstance(); try {
// print(prefs); final response =
// bool isLoggedIn = prefs.getBool('isLoggedIn') ?? false; await http.get(Uri.parse('http://127.0.0.1:6767/login_check'));
await Future.delayed(const Duration(seconds: 1)); print(response.statusCode);
bool isLoggedIn = await _authService.isUserLoggedIn(); print(response.body);
print("is logged in $isLoggedIn"); if (response.statusCode == 200) {
if (isLoggedIn) { final data = jsonDecode(response.body);
context.go("/home"); print(data['state']);
// Navigator.pushReplacementNamed(context, '/home'); if (data['state']) {
} else { context.go("/home");
} else {
context.go("/login");
}
} else {
context.go("/login");
}
} catch (e) {
print("caught in checkloginstatus in login $e");
context.go("/login"); context.go("/login");
// Navigator.pushReplacementNamed(context, '/login');
} }
} }
@ -139,14 +146,10 @@ class _LoginPageState extends State<LoginPage> {
final TextEditingController _emailController = TextEditingController(); final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController(); final TextEditingController _passwordController = TextEditingController();
// final ConfigManager _configManager =
// ConfigManager("${Directory.current.parent}../crabmail2.conf");
// Key to identify the form
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
Future<bool> setIp(String ip) async { Future<bool> setIp(String ip) async {
//this is not done :sob: :skull: //this is not done :sob: :skull:
// _configManager.setField("api_addr", ip);
return false; return false;
} }
@ -155,31 +158,16 @@ class _LoginPageState extends State<LoginPage> {
} }
Future<void> login() async { Future<void> login() async {
bool result = await _handleLogin(); var result = await _handleLogin();
if (result) { if (result[0]) {
Navigator.pushReplacementNamed(context, '/home'); ApiService.ip = result[1];
ApiService.port = result[2];
context.go('/home');
} }
} }
// Future<bool> _checkConfiguration() async {
// return false;
// }
// void checkLogin() async {
// try {
// var url = Uri.http('127.0.0.1:3001', 'is_logged_in');
// var response = await http.get(url);
// print(response.body);
// if (response.statusCode == 200) {
// print('all good on the west');
// }
// } catch (e) {
// print(e);
// }
// // bool isLoggedIn = await _authService.isUserLoggedIn();
// }
// Function to handle login action // Function to handle login action
Future<bool> _handleLogin() async { Future<List> _handleLogin() async {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
// Perform login action (e.g., authenticate with backend) // Perform login action (e.g., authenticate with backend)
String ip = _ipController.text; String ip = _ipController.text;
@ -193,96 +181,64 @@ class _LoginPageState extends State<LoginPage> {
print(ip); print(ip);
print(port); print(port);
String baseUrl = "http://$ip:$port";
print("baseurl " + baseUrl);
print(baseUrl);
try { try {
final response = Map<String, String> requestBody = {
await http.get(Uri.parse('http://localhost:6823/read-config')); "user": email,
"password": password,
"ip": ip,
"port": port,
};
var url = Uri.http("$ip:6767", "login");
final response = await http.post(url,
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode(
requestBody)); //keep the port but change the ip to the server that will process it?
print(response.statusCode); print(response.statusCode);
print(response.body); print(response.body);
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
// return data['config']; if (data["state"] == true) {
try {
final response = await http
.get(Uri.parse('http://127.0.0.1:6767/login_check'));
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
print(data['state']);
if (data['state']) {
context.go("/home");
} else {
context.go("/login");
}
} else {
context.go("/login");
}
} catch (e) {
print("caught in checkloginstatus in login $e");
context.go("/login");
}
}
return [true, ip, port];
} }
return [false];
} catch (e) { } catch (e) {
print("caught in catch"); print("caught in catch");
print(e); print(e);
return false; return [false];
} }
Map<String, dynamic> updates = {
// "username": email,
// "password": password,
"ip": ip,
"port": port,
};
print("past");
try {
final sending = await http.post(
Uri.parse('http://localhost:6823/update-config'),
headers: {'Content-Type': "application/json"},
body: jsonEncode(updates));
print("sending");
} catch (e) {
print(e);
return false;
}
try {
// String status = await http.post(Uri.parse(''))
var url_log = Uri.http('$ip:$port', 'log_in');
Map<String, dynamic> filteredData = {
"email": email,
"password": password,
// 'email': updates['username'],
// 'password': updates['password']
};
print(filteredData);
var status = await http.post(
url_log,
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode(filteredData),
);
if (status.statusCode == 200) {
print('response status ${status.body}');
if (status.body == "Successful log in") {
ApiService.ip = ip;
ApiService.port = port;
return true;
}
}
} catch (e) {
print(e);
return false;
}
print("after");
return false;
// final content = await _authService.readConfFile();
// final config = await _authService.parseConfFile(content);
// print("BASE URL ${config["base_url"]}");
// print("api address ${config["api_addr"]}");
// print(config);
// const url = ''
// Clear the input fields
// _ipController.clear();
// _portController.clear();
// _emailController.clear();
// _passwordController.clear();
} }
return false; return [false];
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// try { _ipController.text = "127.0.0.1";
// _configManager.loadConfig(); _portController.text = "3001";
// print(_configManager.getField('base_url'));
// } catch (e) {
// print("broke at build $e");
// }
// _configManager.
return Center( return Center(
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
@ -317,14 +273,6 @@ class _LoginPageState extends State<LoginPage> {
return 'Please enter your ip'; return 'Please enter your ip';
} }
}, },
// onSaved: (value) async {
// final content = await _authService.readConfFile();
// final config =
// await _authService.parseConfFile(content);
// print("BASE URL ${config["base_url"]}");
// print("api address ${config["api_addr"]}");
// //TODO: call a function to set the field ip in conf
// },
), ),
), ),
Container( Container(
@ -403,17 +351,6 @@ class _LoginPageState extends State<LoginPage> {
child: const Text('Login'), child: const Text('Login'),
), ),
), ),
// SizedBox(
// width: 200,
// child: ElevatedButton(
// // onPressed: checkLogin,
// onPressed: () async {
// await _authService.isUserLoggedIn();
// // print(result);
// },
// child: const Text('checker'),
// ),
// )
], ],
), ),
), ),

View file

@ -22,7 +22,6 @@ class HyM extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final GoRouter _router = GoRouter( final GoRouter _router = GoRouter(
// refreshListenable: ,
initialLocation: '/', initialLocation: '/',
routes: [ routes: [
GoRoute( GoRoute(
@ -48,7 +47,8 @@ class HyM extends StatelessWidget {
final target = state.pathParameters['target']!; final target = state.pathParameters['target']!;
final viewspecs = state.pathParameters['viewspecs']!; final viewspecs = state.pathParameters['viewspecs']!;
final emailId = state.pathParameters['emailID']!; final emailId = state.pathParameters['emailID']!;
return Routinghandler.fromParameters("main anchor", subject, target, viewspecs, emailId); return Routinghandler.fromParameters(
"main anchor", subject, target, viewspecs, emailId);
}), }),
]); ]);
return MaterialApp.router( return MaterialApp.router(
@ -59,18 +59,6 @@ class HyM extends StatelessWidget {
), ),
title: 'HyM', title: 'HyM',
routerConfig: _router, routerConfig: _router,
// home: HomeScreen(),
// routes: {
// "/": (context) => SplashScreen(),
// "/login": (context) => const LoginPage(),
// "/home": (context) => HomeScreen(),
// "/contacts": (context) => ContactsPage(),
// GoRoute(
// path:
// )
// "/email": (context) => EmailListScreen(),
// },
); );
} }
} }

View file

@ -81,7 +81,7 @@ class SerializableMessage {
required this.subject, required this.subject,
required this.date, required this.date,
required this.uid, required this.uid,
required this.list, //email list??? required this.list, //folder
required this.id, required this.id,
required this.in_reply_to, required this.in_reply_to,
}); });

View file

@ -33,6 +33,7 @@ dependencies:
go_router: ^16.0.0 go_router: ^16.0.0
super_editor: ^0.3.0-dev.27 super_editor: ^0.3.0-dev.27
super_editor_markdown: 0.1.8 super_editor_markdown: 0.1.8
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: