Created project base structure, state management, router and login

This commit is contained in:
Juan Gilsanz Polo
2024-02-21 23:53:22 +01:00
commit 460e13b2e9
168 changed files with 6966 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
import 'dart:io';
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
}
}

View File

@@ -0,0 +1,210 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:my_linkding/models/server_instance.dart';
enum ExceptionType { socket, timeout, handshake, http, unknown }
class HttpResponse {
final bool successful;
final String? body;
final int? statusCode;
final ExceptionType? exception;
const HttpResponse({
required this.successful,
required this.body,
required this.statusCode,
this.exception,
});
}
String getConnectionString({
required ServerInstance server,
required String urlPath,
}) {
return "${server.method}://${server.ipDomain}${server.port != null ? ':${server.port}' : ""}${server.path ?? ""}/api$urlPath";
}
class HttpRequestClient {
static Future<HttpResponse> get({
required String urlPath,
required ServerInstance server,
int timeout = 10,
}) async {
final String connectionString = getConnectionString(server: server, urlPath: urlPath);
try {
HttpClient httpClient = HttpClient();
HttpClientRequest request = await httpClient.getUrl(Uri.parse(connectionString));
request.headers.set('Authorization', 'Token ${server.token}');
HttpClientResponse response = await request.close().timeout(
Duration(seconds: timeout),
);
String reply = await response.transform(utf8.decoder).join();
httpClient.close();
return HttpResponse(
successful: response.statusCode >= 400 ? false : true,
body: reply,
statusCode: response.statusCode,
);
} on SocketException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.socket,
);
} on TimeoutException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.timeout,
);
} on HandshakeException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.handshake,
);
} on HttpException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.http,
);
} catch (e) {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.unknown,
);
}
}
static Future<HttpResponse> post({
required String urlPath,
required ServerInstance server,
dynamic body,
int timeout = 10,
}) async {
final String connectionString = getConnectionString(server: server, urlPath: urlPath);
try {
HttpClient httpClient = HttpClient();
HttpClientRequest request = await httpClient.postUrl(Uri.parse(connectionString));
request.headers.set('Authorization', 'Token ${server.token}');
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(body)));
HttpClientResponse response = await request.close().timeout(
Duration(seconds: timeout),
);
String reply = await response.transform(utf8.decoder).join();
httpClient.close();
return HttpResponse(
successful: response.statusCode >= 400 ? false : true,
body: reply,
statusCode: response.statusCode,
);
} on SocketException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.socket,
);
} on TimeoutException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.timeout,
);
} on HttpException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.http,
);
} on HandshakeException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.handshake,
);
} catch (e) {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.unknown,
);
}
}
static Future<HttpResponse> put({
required String urlPath,
required ServerInstance server,
dynamic body,
int timeout = 10,
}) async {
final String connectionString = getConnectionString(server: server, urlPath: urlPath);
try {
HttpClient httpClient = HttpClient();
HttpClientRequest request = await httpClient.putUrl(Uri.parse(connectionString));
request.headers.set('Authorization', 'Token ${server.token}');
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(body)));
HttpClientResponse response = await request.close().timeout(
Duration(seconds: timeout),
);
String reply = await response.transform(utf8.decoder).join();
httpClient.close();
return HttpResponse(
successful: response.statusCode >= 400 ? false : true,
body: reply,
statusCode: response.statusCode,
);
} on SocketException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.socket,
);
} on TimeoutException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.timeout,
);
} on HttpException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.http,
);
} on HandshakeException {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.handshake,
);
} catch (e) {
return const HttpResponse(
successful: false,
body: null,
statusCode: null,
exception: ExceptionType.unknown,
);
}
}
}

View File

@@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
import 'package:my_linkding/widgets/process_dialog.dart';
import 'package:my_linkding/router/routes.dart';
class ProcessModal {
void open(String message) async {
await Future.delayed(
const Duration(seconds: 0),
() => {
showDialog(
context: rootNavigatorKey.currentContext!,
builder: (ctx) {
return ProcessDialog(
message: message,
);
},
barrierDismissible: false,
useSafeArea: true,
),
},
);
}
void close() {
Navigator.pop(rootNavigatorKey.currentContext!);
}
}

22
lib/utils/snackbar.dart Normal file
View File

@@ -0,0 +1,22 @@
// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'package:my_linkding/constants/global_keys.dart';
void showSnacbkar({
required String label,
required Color color,
Color? labelColor,
GlobalKey<ScaffoldMessengerState>? key,
}) async {
final GlobalKey<ScaffoldMessengerState> scaffoldKey = key ?? scaffoldMessengerGlobalKey;
final snackBar = SnackBar(
content: Text(
label,
style: TextStyle(color: labelColor ?? Colors.white),
),
backgroundColor: color,
);
scaffoldKey.currentState?.showSnackBar(snackBar);
}