Created project base structure, state management, router and login
This commit is contained in:
9
lib/utils/http_overrides.dart
Normal file
9
lib/utils/http_overrides.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
210
lib/utils/http_request_client.dart
Normal file
210
lib/utils/http_request_client.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
lib/utils/process_modal.dart
Normal file
29
lib/utils/process_modal.dart
Normal 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
22
lib/utils/snackbar.dart
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user