Hive, requestlog, etc
This commit is contained in:
parent
227d7871c2
commit
7e347a70c2
10
flutter/Makefile
Normal file
10
flutter/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
run:
|
||||
dart run build_runner build
|
||||
flutter run
|
||||
|
||||
|
||||
gen:
|
||||
dart run build_runner build
|
||||
|
@ -11,7 +11,7 @@
|
||||
- https://pub.dev/packages/sqflite
|
||||
- https://pub.dev/packages/sqflite_common_ffi
|
||||
|
||||
|
||||
- https://pub.dev/packages/hive
|
||||
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:fl_toast/fl_toast.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:simplecloudnotifier/models/api_error.dart';
|
||||
import 'package:simplecloudnotifier/models/key_token_auth.dart';
|
||||
import 'package:simplecloudnotifier/models/user.dart';
|
||||
import 'package:simplecloudnotifier/state/globals.dart';
|
||||
import 'package:simplecloudnotifier/state/request_log.dart';
|
||||
|
||||
import '../models/channel.dart';
|
||||
import '../models/message.dart';
|
||||
@ -21,69 +26,141 @@ enum ChannelSelector {
|
||||
class APIClient {
|
||||
static const String _base = 'https://simplecloudnotifier.de/api/v2';
|
||||
|
||||
static Future<bool> verifyToken(String uid, String tok) async {
|
||||
final uri = Uri.parse('$_base/users/$uid');
|
||||
final response = await http.get(uri, headers: {'Authorization': 'SCN $tok'});
|
||||
static Future<T> _request<T>({
|
||||
required String name,
|
||||
required String method,
|
||||
required String relURL,
|
||||
Map<String, String>? query,
|
||||
required T Function(Map<String, dynamic> json)? fn,
|
||||
dynamic jsonBody,
|
||||
KeyTokenAuth? auth,
|
||||
Map<String, String>? header,
|
||||
}) async {
|
||||
final t0 = DateTime.now();
|
||||
|
||||
return (response.statusCode == 200);
|
||||
}
|
||||
final uri = Uri.parse('$_base/$relURL').replace(queryParameters: query ?? {});
|
||||
|
||||
static Future<User> getUser(String uid, String tok) async {
|
||||
final uri = Uri.parse('$_base/users/$uid');
|
||||
final response = await http.get(uri, headers: {'Authorization': 'SCN $tok'});
|
||||
final req = http.Request(method, uri);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('API request failed');
|
||||
if (jsonBody != null) {
|
||||
req.body = jsonEncode(jsonBody);
|
||||
req.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
return User.fromJson(jsonDecode(response.body));
|
||||
if (auth != null) {
|
||||
req.headers['Authorization'] = 'SCN ${auth.token}';
|
||||
}
|
||||
|
||||
req.headers['User-Agent'] = 'simplecloudnotifier/flutter/${Globals().platform.replaceAll(' ', '_')} ${Globals().version}+${Globals().buildNumber}';
|
||||
|
||||
if (header != null && !header.isEmpty) {
|
||||
req.headers.addAll(header);
|
||||
}
|
||||
|
||||
int responseStatusCode = 0;
|
||||
String responseBody = '';
|
||||
Map<String, String> responseHeaders = {};
|
||||
|
||||
try {
|
||||
final response = await req.send();
|
||||
responseBody = await response.stream.bytesToString();
|
||||
responseStatusCode = response.statusCode;
|
||||
responseHeaders = response.headers;
|
||||
} catch (exc, trace) {
|
||||
RequestLog.addRequestException(name, t0, method, uri, req.body, req.headers, exc, trace);
|
||||
showPlatformToast(child: Text('Request "${name}" is fehlgeschlagen'), context: ToastProvider.context);
|
||||
rethrow;
|
||||
}
|
||||
|
||||
if (responseStatusCode != 200) {
|
||||
try {
|
||||
final apierr = APIError.fromJson(jsonDecode(responseBody));
|
||||
|
||||
RequestLog.addRequestAPIError(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders, apierr);
|
||||
showPlatformToast(child: Text('Request "${name}" is fehlgeschlagen'), context: ToastProvider.context);
|
||||
throw Exception(apierr.message);
|
||||
} catch (_) {}
|
||||
|
||||
RequestLog.addRequestErrorStatuscode(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders);
|
||||
showPlatformToast(child: Text('Request "${name}" is fehlgeschlagen'), context: ToastProvider.context);
|
||||
throw Exception('API request failed with status code ${responseStatusCode}');
|
||||
}
|
||||
|
||||
try {
|
||||
final data = jsonDecode(responseBody);
|
||||
|
||||
if (fn != null) {
|
||||
final result = fn(data);
|
||||
RequestLog.addRequestSuccess(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders);
|
||||
return result;
|
||||
} else {
|
||||
RequestLog.addRequestSuccess(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders);
|
||||
return null as T;
|
||||
}
|
||||
} catch (exc, trace) {
|
||||
RequestLog.addRequestDecodeError(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders, exc, trace);
|
||||
showPlatformToast(child: Text('Request "${name}" is fehlgeschlagen'), context: ToastProvider.context);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================================================================================================
|
||||
|
||||
static Future<bool> verifyToken(String uid, String tok) async {
|
||||
try {
|
||||
await _request<void>(
|
||||
name: 'verifyToken',
|
||||
method: 'GET',
|
||||
relURL: '/users/$uid',
|
||||
fn: null,
|
||||
auth: KeyTokenAuth(userId: uid, token: tok),
|
||||
);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<User> getUser(KeyTokenAuth auth, String uid) async {
|
||||
return await _request(
|
||||
name: 'getUser',
|
||||
method: 'GET',
|
||||
relURL: 'users/$uid',
|
||||
fn: User.fromJson,
|
||||
auth: auth,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<List<ChannelWithSubscription>> getChannelList(KeyTokenAuth auth, ChannelSelector sel) async {
|
||||
var url = '$_base/users/${auth.userId}/channels?selector=${sel.apiKey}';
|
||||
final uri = Uri.parse(url);
|
||||
|
||||
final response = await http.get(uri, headers: {'Authorization': 'SCN ${auth.token}'});
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('API request failed');
|
||||
}
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
return data['channels'].map<ChannelWithSubscription>((e) => ChannelWithSubscription.fromJson(e)).toList() as List<ChannelWithSubscription>;
|
||||
return await _request(
|
||||
name: 'getChannelList',
|
||||
method: 'GET',
|
||||
relURL: 'users/${auth.userId}/channels',
|
||||
query: {'selector': sel.apiKey},
|
||||
fn: (json) => ChannelWithSubscription.fromJsonArray(json['channels']),
|
||||
auth: auth,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<(String, List<Message>)> getMessageList(KeyTokenAuth auth, String pageToken, int? pageSize) async {
|
||||
var url = '$_base/messages?next_page_token=$pageToken';
|
||||
if (pageSize != null) {
|
||||
url += '&page_size=$pageSize';
|
||||
}
|
||||
final uri = Uri.parse(url);
|
||||
|
||||
final response = await http.get(uri, headers: {'Authorization': 'SCN ${auth.token}'});
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('API request failed');
|
||||
}
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
final npt = data['next_page_token'] as String;
|
||||
|
||||
final messages = data['messages'].map<Message>((e) => Message.fromJson(e)).toList() as List<Message>;
|
||||
|
||||
return (npt, messages);
|
||||
return await _request(
|
||||
name: 'getMessageList',
|
||||
method: 'GET',
|
||||
relURL: 'messages',
|
||||
query: {'next_page_token': pageToken, if (pageSize != null) 'page_size': pageSize.toString()},
|
||||
fn: (json) => Message.fromPaginatedJsonArray(json, 'messages', 'next_page_token'),
|
||||
auth: auth,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Message> getMessage(KeyTokenAuth auth, String msgid) async {
|
||||
final uri = Uri.parse('$_base/messages/$msgid');
|
||||
final response = await http.get(uri, headers: {'Authorization': 'SCN ${auth.token}'});
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('API request failed');
|
||||
}
|
||||
|
||||
return Message.fromJson(jsonDecode(response.body));
|
||||
return await _request(
|
||||
name: 'getMessage',
|
||||
method: 'GET',
|
||||
relURL: 'messages/$msgid',
|
||||
query: {},
|
||||
fn: Message.fromJson,
|
||||
auth: auth,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,34 @@
|
||||
import 'package:fl_toast/fl_toast.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/state/database.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
|
||||
import 'package:simplecloudnotifier/nav_layout.dart';
|
||||
import 'package:simplecloudnotifier/state/app_theme.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/globals.dart';
|
||||
import 'package:simplecloudnotifier/state/request_log.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
|
||||
void main() async {
|
||||
await SCNDatabase.create();
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
await Hive.initFlutter();
|
||||
await Globals().init();
|
||||
|
||||
Hive.registerAdapter(SCNRequestAdapter());
|
||||
Hive.registerAdapter(SCNLogAdapter());
|
||||
|
||||
try {
|
||||
await Hive.openBox<SCNRequest>('scn-requests');
|
||||
await Hive.openBox<SCNLog>('scn-logs');
|
||||
} catch (e) {
|
||||
print(e);
|
||||
Hive.deleteBoxFromDisk('scn-requests');
|
||||
Hive.deleteBoxFromDisk('scn-logs');
|
||||
await Hive.openBox<SCNRequest>('scn-requests');
|
||||
await Hive.openBox<SCNLog>('scn-logs');
|
||||
}
|
||||
|
||||
runApp(
|
||||
MultiProvider(
|
||||
@ -31,7 +52,7 @@ class SCNApp extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Provider.of<UserAccount>(context); // ensure UserAccount is loaded
|
||||
Provider.of<UserAccount>(context); // ensure UserAccount is loaded (unneccessary if lazy: false is set in MultiProvider ??)
|
||||
|
||||
return Consumer<AppTheme>(
|
||||
builder: (context, appTheme, child) => MaterialApp(
|
||||
@ -40,7 +61,7 @@ class SCNApp extends StatelessWidget {
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue, brightness: appTheme.darkMode ? Brightness.dark : Brightness.light),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const SCNNavLayout(),
|
||||
home: const ToastProvider(child: SCNNavLayout()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
22
flutter/lib/models/api_error.dart
Normal file
22
flutter/lib/models/api_error.dart
Normal file
@ -0,0 +1,22 @@
|
||||
class APIError {
|
||||
final String success;
|
||||
final String error;
|
||||
final String errhighlight;
|
||||
final String message;
|
||||
|
||||
const APIError({
|
||||
required this.success,
|
||||
required this.error,
|
||||
required this.errhighlight,
|
||||
required this.message,
|
||||
});
|
||||
|
||||
factory APIError.fromJson(Map<String, dynamic> json) {
|
||||
return APIError(
|
||||
success: json['success'],
|
||||
error: json['error'],
|
||||
errhighlight: json['errhighlight'],
|
||||
message: json['message'],
|
||||
);
|
||||
}
|
||||
}
|
@ -24,31 +24,17 @@ class Channel {
|
||||
});
|
||||
|
||||
factory Channel.fromJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
'channel_id': String channelID,
|
||||
'owner_user_id': String ownerUserID,
|
||||
'internal_name': String internalName,
|
||||
'display_name': String displayName,
|
||||
'description_name': String? descriptionName,
|
||||
'subscribe_key': String? subscribeKey,
|
||||
'timestamp_created': String timestampCreated,
|
||||
'timestamp_lastsent': String? timestampLastSent,
|
||||
'messages_sent': int messagesSent,
|
||||
} =>
|
||||
Channel(
|
||||
channelID: channelID,
|
||||
ownerUserID: ownerUserID,
|
||||
internalName: internalName,
|
||||
displayName: displayName,
|
||||
descriptionName: descriptionName,
|
||||
subscribeKey: subscribeKey,
|
||||
timestampCreated: timestampCreated,
|
||||
timestampLastSent: timestampLastSent,
|
||||
messagesSent: messagesSent,
|
||||
),
|
||||
_ => throw const FormatException('Failed to decode Channel.'),
|
||||
};
|
||||
return Channel(
|
||||
channelID: json['channel_id'],
|
||||
ownerUserID: json['owner_user_id'],
|
||||
internalName: json['internal_name'],
|
||||
displayName: json['display_name'],
|
||||
descriptionName: json['description_name'],
|
||||
subscribeKey: json['subscribe_key'],
|
||||
timestampCreated: json['timestamp_created'],
|
||||
timestampLastSent: json['timestamp_lastsent'],
|
||||
messagesSent: json['messages_sent'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,32 +55,21 @@ class ChannelWithSubscription extends Channel {
|
||||
});
|
||||
|
||||
factory ChannelWithSubscription.fromJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
'channel_id': String channelID,
|
||||
'owner_user_id': String ownerUserID,
|
||||
'internal_name': String internalName,
|
||||
'display_name': String displayName,
|
||||
'description_name': String? descriptionName,
|
||||
'subscribe_key': String? subscribeKey,
|
||||
'timestamp_created': String timestampCreated,
|
||||
'timestamp_lastsent': String? timestampLastSent,
|
||||
'messages_sent': int messagesSent,
|
||||
'subscription': dynamic subscription,
|
||||
} =>
|
||||
ChannelWithSubscription(
|
||||
channelID: channelID,
|
||||
ownerUserID: ownerUserID,
|
||||
internalName: internalName,
|
||||
displayName: displayName,
|
||||
descriptionName: descriptionName,
|
||||
subscribeKey: subscribeKey,
|
||||
timestampCreated: timestampCreated,
|
||||
timestampLastSent: timestampLastSent,
|
||||
messagesSent: messagesSent,
|
||||
subscription: Subscription.fromJson(subscription),
|
||||
),
|
||||
_ => throw const FormatException('Failed to decode Channel.'),
|
||||
};
|
||||
return ChannelWithSubscription(
|
||||
channelID: json['channel_id'],
|
||||
ownerUserID: json['owner_user_id'],
|
||||
internalName: json['internal_name'],
|
||||
displayName: json['display_name'],
|
||||
descriptionName: json['description_name'],
|
||||
subscribeKey: json['subscribe_key'],
|
||||
timestampCreated: json['timestamp_created'],
|
||||
timestampLastSent: json['timestamp_lastsent'],
|
||||
messagesSent: json['messages_sent'],
|
||||
subscription: Subscription.fromJson(json['subscription']),
|
||||
);
|
||||
}
|
||||
|
||||
static List<ChannelWithSubscription> fromJsonArray(List<dynamic> jsonArr) {
|
||||
return jsonArr.map<ChannelWithSubscription>((e) => ChannelWithSubscription.fromJson(e)).toList();
|
||||
}
|
||||
}
|
||||
|
@ -30,38 +30,28 @@ class Message {
|
||||
});
|
||||
|
||||
factory Message.fromJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
'message_id': String messageID,
|
||||
'sender_user_id': String senderUserID,
|
||||
'channel_internal_name': String channelInternalName,
|
||||
'channel_id': String channelID,
|
||||
'sender_name': String? senderName,
|
||||
'sender_ip': String senderIP,
|
||||
'timestamp': String timestamp,
|
||||
'title': String title,
|
||||
'content': String? content,
|
||||
'priority': int priority,
|
||||
'usr_message_id': String? userMessageID,
|
||||
'used_key_id': String usedKeyID,
|
||||
'trimmed': bool trimmed,
|
||||
} =>
|
||||
Message(
|
||||
messageID: messageID,
|
||||
senderUserID: senderUserID,
|
||||
channelInternalName: channelInternalName,
|
||||
channelID: channelID,
|
||||
senderName: senderName,
|
||||
senderIP: senderIP,
|
||||
timestamp: timestamp,
|
||||
title: title,
|
||||
content: content,
|
||||
priority: priority,
|
||||
userMessageID: userMessageID,
|
||||
usedKeyID: usedKeyID,
|
||||
trimmed: trimmed,
|
||||
),
|
||||
_ => throw const FormatException('Failed to decode Message.'),
|
||||
};
|
||||
return Message(
|
||||
messageID: json['message_id'],
|
||||
senderUserID: json['sender_user_id'],
|
||||
channelInternalName: json['channel_internal_name'],
|
||||
channelID: json['channel_id'],
|
||||
senderName: json['sender_name'],
|
||||
senderIP: json['sender_ip'],
|
||||
timestamp: json['timestamp'],
|
||||
title: json['title'],
|
||||
content: json['content'],
|
||||
priority: json['priority'],
|
||||
userMessageID: json['usr_message_id'],
|
||||
usedKeyID: json['used_key_id'],
|
||||
trimmed: json['trimmed'],
|
||||
);
|
||||
}
|
||||
|
||||
static fromPaginatedJsonArray(Map<String, dynamic> data, String keyMessages, String keyToken) {
|
||||
final npt = data[keyToken] as String;
|
||||
|
||||
final messages = (data[keyMessages] as List<dynamic>).map<Message>((e) => Message.fromJson(e)).toList();
|
||||
|
||||
return (npt, messages);
|
||||
}
|
||||
}
|
||||
|
@ -18,26 +18,14 @@ class Subscription {
|
||||
});
|
||||
|
||||
factory Subscription.fromJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
'subscription_id': String subscriptionID,
|
||||
'subscriber_user_id': String subscriberUserID,
|
||||
'channel_owner_user_id': String channelOwnerUserID,
|
||||
'channel_id': String channelID,
|
||||
'channel_internal_name': String channelInternalName,
|
||||
'timestamp_created': String timestampCreated,
|
||||
'confirmed': bool confirmed,
|
||||
} =>
|
||||
Subscription(
|
||||
subscriptionID: subscriptionID,
|
||||
subscriberUserID: subscriberUserID,
|
||||
channelOwnerUserID: channelOwnerUserID,
|
||||
channelID: channelID,
|
||||
channelInternalName: channelInternalName,
|
||||
timestampCreated: timestampCreated,
|
||||
confirmed: confirmed,
|
||||
),
|
||||
_ => throw const FormatException('Failed to decode Subscription.'),
|
||||
};
|
||||
return Subscription(
|
||||
subscriptionID: json['subscription_id'],
|
||||
subscriberUserID: json['subscriber_user_id'],
|
||||
channelOwnerUserID: json['channel_owner_user_id'],
|
||||
channelID: json['channel_id'],
|
||||
channelInternalName: json['channel_internal_name'],
|
||||
timestampCreated: json['timestamp_created'],
|
||||
confirmed: json['confirmed'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -40,48 +40,25 @@ class User {
|
||||
});
|
||||
|
||||
factory User.fromJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
'user_id': String userID,
|
||||
'username': String? username,
|
||||
'timestamp_created': String timestampCreated,
|
||||
'timestamp_lastread': String? timestampLastRead,
|
||||
'timestamp_lastsent': String? timestampLastSent,
|
||||
'messages_sent': int messagesSent,
|
||||
'quota_used': int quotaUsed,
|
||||
'quota_remaining': int quotaRemaining,
|
||||
'quota_max': int quotaPerDay,
|
||||
'is_pro': bool isPro,
|
||||
'default_channel': String defaultChannel,
|
||||
'max_body_size': int maxBodySize,
|
||||
'max_title_length': int maxTitleLength,
|
||||
'default_priority': int defaultPriority,
|
||||
'max_channel_name_length': int maxChannelNameLength,
|
||||
'max_channel_description_length': int maxChannelDescriptionLength,
|
||||
'max_sender_name_length': int maxSenderNameLength,
|
||||
'max_user_message_id_length': int maxUserMessageIDLength,
|
||||
} =>
|
||||
User(
|
||||
userID: userID,
|
||||
username: username,
|
||||
timestampCreated: timestampCreated,
|
||||
timestampLastRead: timestampLastRead,
|
||||
timestampLastSent: timestampLastSent,
|
||||
messagesSent: messagesSent,
|
||||
quotaUsed: quotaUsed,
|
||||
quotaRemaining: quotaRemaining,
|
||||
quotaPerDay: quotaPerDay,
|
||||
isPro: isPro,
|
||||
defaultChannel: defaultChannel,
|
||||
maxBodySize: maxBodySize,
|
||||
maxTitleLength: maxTitleLength,
|
||||
defaultPriority: defaultPriority,
|
||||
maxChannelNameLength: maxChannelNameLength,
|
||||
maxChannelDescriptionLength: maxChannelDescriptionLength,
|
||||
maxSenderNameLength: maxSenderNameLength,
|
||||
maxUserMessageIDLength: maxUserMessageIDLength,
|
||||
),
|
||||
_ => throw const FormatException('Failed to decode User.'),
|
||||
};
|
||||
return User(
|
||||
userID: json['user_id'],
|
||||
username: json['username'],
|
||||
timestampCreated: json['timestamp_created'],
|
||||
timestampLastRead: json['timestamp_lastread'],
|
||||
timestampLastSent: json['timestamp_lastsent'],
|
||||
messagesSent: json['messages_sent'],
|
||||
quotaUsed: json['quota_used'],
|
||||
quotaRemaining: json['quota_remaining'],
|
||||
quotaPerDay: json['quota_max'],
|
||||
isPro: json['is_pro'],
|
||||
defaultChannel: json['default_channel'],
|
||||
maxBodySize: json['max_body_size'],
|
||||
maxTitleLength: json['max_title_length'],
|
||||
defaultPriority: json['default_priority'],
|
||||
maxChannelNameLength: json['max_channel_name_length'],
|
||||
maxChannelDescriptionLength: json['max_channel_description_length'],
|
||||
maxSenderNameLength: json['max_sender_name_length'],
|
||||
maxUserMessageIDLength: json['max_user_message_id_length'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
13
flutter/lib/pages/debug/debug_logs.dart
Normal file
13
flutter/lib/pages/debug/debug_logs.dart
Normal file
@ -0,0 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugLogsPage extends StatefulWidget {
|
||||
@override
|
||||
_DebugLogsPageState createState() => _DebugLogsPageState();
|
||||
}
|
||||
|
||||
class _DebugLogsPageState extends State<DebugLogsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(/* Add your UI components here */);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/pages/debug/debug_colors.dart';
|
||||
import 'package:simplecloudnotifier/pages/debug/debug_logs.dart';
|
||||
import 'package:simplecloudnotifier/pages/debug/debug_persistence.dart';
|
||||
import 'package:simplecloudnotifier/pages/debug/debug_requests.dart';
|
||||
|
||||
@ -9,13 +10,14 @@ class DebugMainPage extends StatefulWidget {
|
||||
_DebugMainPageState createState() => _DebugMainPageState();
|
||||
}
|
||||
|
||||
enum DebugMainPageSubPage { colors, requests, persistence }
|
||||
enum DebugMainPageSubPage { colors, requests, persistence, logs }
|
||||
|
||||
class _DebugMainPageState extends State<DebugMainPage> {
|
||||
final Map<DebugMainPageSubPage, Widget> _subpages = {
|
||||
DebugMainPageSubPage.colors: DebugColorsPage(),
|
||||
DebugMainPageSubPage.requests: DebugRequestsPage(),
|
||||
DebugMainPageSubPage.persistence: DebugPersistencePage(),
|
||||
DebugMainPageSubPage.logs: DebugLogsPage(),
|
||||
};
|
||||
|
||||
DebugMainPageSubPage _subPage = DebugMainPageSubPage.colors;
|
||||
@ -52,6 +54,7 @@ class _DebugMainPageState extends State<DebugMainPage> {
|
||||
ButtonSegment<DebugMainPageSubPage>(value: DebugMainPageSubPage.colors, label: Text('Theme')),
|
||||
ButtonSegment<DebugMainPageSubPage>(value: DebugMainPageSubPage.requests, label: Text('Requests')),
|
||||
ButtonSegment<DebugMainPageSubPage>(value: DebugMainPageSubPage.persistence, label: Text('Persistence')),
|
||||
ButtonSegment<DebugMainPageSubPage>(value: DebugMainPageSubPage.logs, label: Text('Logs')),
|
||||
],
|
||||
selected: <DebugMainPageSubPage>{_subPage},
|
||||
onSelectionChanged: (Set<DebugMainPageSubPage> v) {
|
||||
|
87
flutter/lib/pages/debug/debug_request_view.dart
Normal file
87
flutter/lib/pages/debug/debug_request_view.dart
Normal file
@ -0,0 +1,87 @@
|
||||
import 'package:fl_toast/fl_toast.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/state/request_log.dart';
|
||||
|
||||
class DebugRequestViewPage extends StatelessWidget {
|
||||
final SCNRequest request;
|
||||
|
||||
DebugRequestViewPage({required this.request});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SCNScaffold(
|
||||
title: 'Request',
|
||||
showSearch: false,
|
||||
showDebug: false,
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
...buildRow(context, "Name", request.name),
|
||||
...buildRow(context, "Timestamp (Start)", request.timestampStart.toString()),
|
||||
...buildRow(context, "Timestamp (End)", request.timestampEnd.toString()),
|
||||
...buildRow(context, "Duration", request.timestampEnd.difference(request.timestampStart).toString()),
|
||||
Divider(),
|
||||
...buildRow(context, "Method", request.method),
|
||||
...buildRow(context, "URL", request.url),
|
||||
if (request.requestHeaders.isNotEmpty) ...buildRow(context, "Request->Headers", request.requestHeaders.entries.map((v) => '${v.key} = ${v.value}').join('\n')),
|
||||
if (request.requestBody != '') ...buildRow(context, "Request->Body", request.requestBody),
|
||||
Divider(),
|
||||
if (request.responseStatusCode != 0) ...buildRow(context, "Response->Statuscode", request.responseStatusCode.toString()),
|
||||
if (request.responseBody != '') ...buildRow(context, "Reponse->Body", request.responseBody),
|
||||
if (request.responseHeaders.isNotEmpty) ...buildRow(context, "Reponse->Headers", request.responseHeaders.entries.map((v) => '${v.key} = ${v.value}').join('\n')),
|
||||
Divider(),
|
||||
if (request.error != '') ...buildRow(context, "Error", request.error),
|
||||
if (request.stackTrace != '') ...buildRow(context, "Stacktrace", request.stackTrace),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> buildRow(BuildContext context, String title, String value) {
|
||||
return [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(title, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
),
|
||||
IconButton(
|
||||
icon: FaIcon(
|
||||
FontAwesomeIcons.copy,
|
||||
),
|
||||
iconSize: 14,
|
||||
padding: EdgeInsets.fromLTRB(0, 0, 4, 0),
|
||||
constraints: BoxConstraints(),
|
||||
onPressed: () {
|
||||
Clipboard.setData(new ClipboardData(text: value));
|
||||
showPlatformToast(child: Text('Copied to clipboard'), context: ToastProvider.context);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Card.filled(
|
||||
shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)),
|
||||
color: request.type == 'SUCCESS' ? null : Theme.of(context).colorScheme.errorContainer,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 6.0),
|
||||
child: SelectableText(
|
||||
value,
|
||||
minLines: 1,
|
||||
maxLines: 10,
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:simplecloudnotifier/pages/debug/debug_request_view.dart';
|
||||
import 'package:simplecloudnotifier/state/request_log.dart';
|
||||
|
||||
class DebugRequestsPage extends StatefulWidget {
|
||||
@override
|
||||
@ -6,8 +10,82 @@ class DebugRequestsPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DebugRequestsPageState extends State<DebugRequestsPage> {
|
||||
Box<SCNRequest> requestsBox = Hive.box<SCNRequest>('scn-requests');
|
||||
|
||||
static final _dateFormat = DateFormat('yyyy-MM-dd kk:mm');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(/* Add your UI components here */);
|
||||
return Container(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: requestsBox.listenable(),
|
||||
builder: (context, Box<SCNRequest> box, _) {
|
||||
return ListView.builder(
|
||||
itemCount: requestsBox.length,
|
||||
itemBuilder: (context, listIndex) {
|
||||
final req = requestsBox.getAt(requestsBox.length - listIndex - 1)!;
|
||||
if (req.type == 'SUCCESS') {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 2.0),
|
||||
child: GestureDetector(
|
||||
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => DebugRequestViewPage(request: req))),
|
||||
child: ListTile(
|
||||
title: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 120,
|
||||
child: Text(_dateFormat.format(req.timestampStart), style: TextStyle(fontSize: 12)),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(req.name, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
),
|
||||
SizedBox(width: 2),
|
||||
Text('${req.timestampEnd.difference(req.timestampStart).inMilliseconds}ms', style: TextStyle(fontSize: 12)),
|
||||
],
|
||||
),
|
||||
subtitle: Text(req.type),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 2.0),
|
||||
child: GestureDetector(
|
||||
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => DebugRequestViewPage(request: req))),
|
||||
child: ListTile(
|
||||
tileColor: Theme.of(context).colorScheme.errorContainer,
|
||||
textColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||
title: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 120,
|
||||
child: Text(_dateFormat.format(req.timestampStart), style: TextStyle(fontSize: 12)),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(req.name, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
),
|
||||
SizedBox(width: 2),
|
||||
Text('${req.timestampEnd.difference(req.timestampStart).inMilliseconds}ms', style: TextStyle(fontSize: 12)),
|
||||
],
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(req.type),
|
||||
Text(
|
||||
req.error,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,29 @@
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
|
||||
part 'application_log.g.dart';
|
||||
|
||||
class ApplicationLog {}
|
||||
|
||||
enum SCNLogLevel { debug, info, warning, error, fatal }
|
||||
|
||||
@HiveType(typeId: 101)
|
||||
class SCNLog extends HiveObject {
|
||||
@HiveField(0)
|
||||
final DateTime timestamp;
|
||||
@HiveField(1)
|
||||
final SCNLogLevel level;
|
||||
@HiveField(2)
|
||||
final String message;
|
||||
@HiveField(3)
|
||||
final String additional;
|
||||
@HiveField(4)
|
||||
final String trace;
|
||||
|
||||
SCNLog(
|
||||
this.timestamp,
|
||||
this.level,
|
||||
this.message,
|
||||
this.additional,
|
||||
this.trace,
|
||||
);
|
||||
}
|
||||
|
53
flutter/lib/state/application_log.g.dart
Normal file
53
flutter/lib/state/application_log.g.dart
Normal file
@ -0,0 +1,53 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'application_log.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class SCNLogAdapter extends TypeAdapter<SCNLog> {
|
||||
@override
|
||||
final int typeId = 101;
|
||||
|
||||
@override
|
||||
SCNLog read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return SCNLog(
|
||||
fields[0] as DateTime,
|
||||
fields[1] as SCNLogLevel,
|
||||
fields[2] as String,
|
||||
fields[3] as String,
|
||||
fields[4] as String,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, SCNLog obj) {
|
||||
writer
|
||||
..writeByte(5)
|
||||
..writeByte(0)
|
||||
..write(obj.timestamp)
|
||||
..writeByte(1)
|
||||
..write(obj.level)
|
||||
..writeByte(2)
|
||||
..write(obj.message)
|
||||
..writeByte(3)
|
||||
..write(obj.additional)
|
||||
..writeByte(4)
|
||||
..write(obj.trace);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is SCNLogAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||
import 'dart:io';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
class SCNDatabase {
|
||||
static SCNDatabase? instance = null;
|
||||
|
||||
final Database _db;
|
||||
|
||||
SCNDatabase._(this._db) {}
|
||||
|
||||
static create() async {
|
||||
var docPath = await getApplicationDocumentsDirectory();
|
||||
var dbpath = path.join(docPath.absolute.path, 'scn.db');
|
||||
|
||||
if (Platform.isWindows || Platform.isLinux) {
|
||||
sqfliteFfiInit();
|
||||
}
|
||||
|
||||
var db = await databaseFactoryFfi.openDatabase(dbpath,
|
||||
options: OpenDatabaseOptions(
|
||||
version: 1,
|
||||
onCreate: (db, version) async {
|
||||
initDatabase(db);
|
||||
},
|
||||
onUpgrade: (db, oldVersion, newVersion) async {
|
||||
upgradeDatabase(db, oldVersion, newVersion);
|
||||
},
|
||||
));
|
||||
|
||||
return instance = SCNDatabase._(db);
|
||||
}
|
||||
|
||||
static void initDatabase(Database db) async {
|
||||
await db.execute('CREATE TABLE requests (id INTEGER PRIMARY KEY, timestamp DATETIME, name TEXT, url TEXT, response_code INTEGER, response TEXT, status TEXT)');
|
||||
|
||||
await db.execute('CREATE TABLE logs (id INTEGER PRIMARY KEY, timestamp DATETIME, level TEXT, text TEXT, additional TEXT)');
|
||||
|
||||
await db.execute('CREATE TABLE messages (message_id INTEGER PRIMARY KEY, receive_timestamp DATETIME, channel_id TEXT, timestamp TEXT, data JSON)');
|
||||
}
|
||||
|
||||
static void upgradeDatabase(Database db, int oldVersion, int newVersion) {
|
||||
// ...
|
||||
}
|
||||
}
|
31
flutter/lib/state/globals.dart
Normal file
31
flutter/lib/state/globals.dart
Normal file
@ -0,0 +1,31 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
class Globals {
|
||||
static final Globals _singleton = Globals._internal();
|
||||
|
||||
factory Globals() {
|
||||
return _singleton;
|
||||
}
|
||||
|
||||
Globals._internal();
|
||||
|
||||
String appName = '';
|
||||
String packageName = '';
|
||||
String version = '';
|
||||
String buildNumber = '';
|
||||
String platform = '';
|
||||
String hostname = '';
|
||||
|
||||
init() async {
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
|
||||
this.appName = packageInfo.appName;
|
||||
this.packageName = packageInfo.packageName;
|
||||
this.version = packageInfo.version;
|
||||
this.buildNumber = packageInfo.buildNumber;
|
||||
this.platform = Platform.operatingSystem;
|
||||
this.hostname = Platform.localHostname;
|
||||
}
|
||||
}
|
@ -1 +1,144 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:simplecloudnotifier/models/api_error.dart';
|
||||
|
||||
part 'request_log.g.dart';
|
||||
|
||||
class RequestLog {
|
||||
static void addRequestException(String name, DateTime tStart, String method, Uri uri, String reqbody, Map<String, String> reqheaders, dynamic e, StackTrace trace) {
|
||||
Hive.box<SCNRequest>('scn-requests').add(SCNRequest(
|
||||
timestampStart: tStart,
|
||||
timestampEnd: DateTime.now(),
|
||||
name: name,
|
||||
method: method,
|
||||
url: uri.toString(),
|
||||
requestHeaders: reqheaders,
|
||||
requestBody: reqbody,
|
||||
responseStatusCode: 0,
|
||||
responseHeaders: {},
|
||||
responseBody: '',
|
||||
type: 'EXCEPTION',
|
||||
error: (e is Exception) ? e.toString() : '$e',
|
||||
stackTrace: trace.toString(),
|
||||
));
|
||||
}
|
||||
|
||||
static void addRequestAPIError(String name, DateTime t0, String method, Uri uri, String reqbody, Map<String, String> reqheaders, int responseStatusCode, String responseBody, Map<String, String> responseHeaders, APIError apierr) {
|
||||
Hive.box<SCNRequest>('scn-requests').add(SCNRequest(
|
||||
timestampStart: t0,
|
||||
timestampEnd: DateTime.now(),
|
||||
name: name,
|
||||
method: method,
|
||||
url: uri.toString(),
|
||||
requestHeaders: reqheaders,
|
||||
requestBody: reqbody,
|
||||
responseStatusCode: responseStatusCode,
|
||||
responseHeaders: responseHeaders,
|
||||
responseBody: responseBody,
|
||||
type: 'API_ERROR',
|
||||
error: apierr.message,
|
||||
stackTrace: '',
|
||||
));
|
||||
}
|
||||
|
||||
static void addRequestErrorStatuscode(String name, DateTime t0, String method, Uri uri, String reqbody, Map<String, String> reqheaders, int responseStatusCode, String responseBody, Map<String, String> responseHeaders) {
|
||||
Hive.box<SCNRequest>('scn-requests').add(SCNRequest(
|
||||
timestampStart: t0,
|
||||
timestampEnd: DateTime.now(),
|
||||
name: name,
|
||||
method: method,
|
||||
url: uri.toString(),
|
||||
requestHeaders: reqheaders,
|
||||
requestBody: reqbody,
|
||||
responseStatusCode: responseStatusCode,
|
||||
responseHeaders: responseHeaders,
|
||||
responseBody: responseBody,
|
||||
type: 'ERROR_STATUSCODE',
|
||||
error: 'API request failed with status code $responseStatusCode',
|
||||
stackTrace: '',
|
||||
));
|
||||
}
|
||||
|
||||
static void addRequestSuccess(String name, DateTime t0, String method, Uri uri, String reqbody, Map<String, String> reqheaders, int responseStatusCode, String responseBody, Map<String, String> responseHeaders) {
|
||||
Hive.box<SCNRequest>('scn-requests').add(SCNRequest(
|
||||
timestampStart: t0,
|
||||
timestampEnd: DateTime.now(),
|
||||
name: name,
|
||||
method: method,
|
||||
url: uri.toString(),
|
||||
requestHeaders: reqheaders,
|
||||
requestBody: reqbody,
|
||||
responseStatusCode: responseStatusCode,
|
||||
responseHeaders: responseHeaders,
|
||||
responseBody: responseBody,
|
||||
type: 'SUCCESS',
|
||||
error: '',
|
||||
stackTrace: '',
|
||||
));
|
||||
}
|
||||
|
||||
static void addRequestDecodeError(String name, DateTime t0, String method, Uri uri, String reqbody, Map<String, String> reqheaders, int responseStatusCode, String responseBody, Map<String, String> responseHeaders, Object exc, StackTrace trace) {
|
||||
Hive.box<SCNRequest>('scn-requests').add(SCNRequest(
|
||||
timestampStart: t0,
|
||||
timestampEnd: DateTime.now(),
|
||||
name: name,
|
||||
method: method,
|
||||
url: uri.toString(),
|
||||
requestHeaders: reqheaders,
|
||||
requestBody: reqbody,
|
||||
responseStatusCode: responseStatusCode,
|
||||
responseHeaders: responseHeaders,
|
||||
responseBody: responseBody,
|
||||
type: 'DECODE_ERROR',
|
||||
error: (exc is Exception) ? exc.toString() : '$exc',
|
||||
stackTrace: trace.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@HiveType(typeId: 100)
|
||||
class SCNRequest extends HiveObject {
|
||||
@HiveField(0)
|
||||
final DateTime timestampStart;
|
||||
@HiveField(1)
|
||||
final DateTime timestampEnd;
|
||||
@HiveField(2)
|
||||
final String name;
|
||||
@HiveField(3)
|
||||
final String type;
|
||||
@HiveField(4)
|
||||
final String error;
|
||||
@HiveField(5)
|
||||
final String stackTrace;
|
||||
|
||||
@HiveField(6)
|
||||
final String method;
|
||||
@HiveField(7)
|
||||
final String url;
|
||||
@HiveField(8)
|
||||
final Map<String, String> requestHeaders;
|
||||
@HiveField(12)
|
||||
final String requestBody;
|
||||
|
||||
@HiveField(9)
|
||||
final int responseStatusCode;
|
||||
@HiveField(10)
|
||||
final Map<String, String> responseHeaders;
|
||||
@HiveField(11)
|
||||
final String responseBody;
|
||||
|
||||
SCNRequest({
|
||||
required this.timestampStart,
|
||||
required this.timestampEnd,
|
||||
required this.name,
|
||||
required this.method,
|
||||
required this.url,
|
||||
required this.requestHeaders,
|
||||
required this.requestBody,
|
||||
required this.responseStatusCode,
|
||||
required this.responseHeaders,
|
||||
required this.responseBody,
|
||||
required this.type,
|
||||
required this.error,
|
||||
required this.stackTrace,
|
||||
});
|
||||
}
|
||||
|
77
flutter/lib/state/request_log.g.dart
Normal file
77
flutter/lib/state/request_log.g.dart
Normal file
@ -0,0 +1,77 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'request_log.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class SCNRequestAdapter extends TypeAdapter<SCNRequest> {
|
||||
@override
|
||||
final int typeId = 100;
|
||||
|
||||
@override
|
||||
SCNRequest read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return SCNRequest(
|
||||
timestampStart: fields[0] as DateTime,
|
||||
timestampEnd: fields[1] as DateTime,
|
||||
name: fields[2] as String,
|
||||
method: fields[6] as String,
|
||||
url: fields[7] as String,
|
||||
requestHeaders: (fields[8] as Map).cast<String, String>(),
|
||||
requestBody: fields[12] as String,
|
||||
responseStatusCode: fields[9] as int,
|
||||
responseHeaders: (fields[10] as Map).cast<String, String>(),
|
||||
responseBody: fields[11] as String,
|
||||
type: fields[3] as String,
|
||||
error: fields[4] as String,
|
||||
stackTrace: fields[5] as String,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, SCNRequest obj) {
|
||||
writer
|
||||
..writeByte(13)
|
||||
..writeByte(0)
|
||||
..write(obj.timestampStart)
|
||||
..writeByte(1)
|
||||
..write(obj.timestampEnd)
|
||||
..writeByte(2)
|
||||
..write(obj.name)
|
||||
..writeByte(3)
|
||||
..write(obj.type)
|
||||
..writeByte(4)
|
||||
..write(obj.error)
|
||||
..writeByte(5)
|
||||
..write(obj.stackTrace)
|
||||
..writeByte(6)
|
||||
..write(obj.method)
|
||||
..writeByte(7)
|
||||
..write(obj.url)
|
||||
..writeByte(8)
|
||||
..write(obj.requestHeaders)
|
||||
..writeByte(12)
|
||||
..write(obj.requestBody)
|
||||
..writeByte(9)
|
||||
..write(obj.responseStatusCode)
|
||||
..writeByte(10)
|
||||
..write(obj.responseHeaders)
|
||||
..writeByte(11)
|
||||
..write(obj.responseBody);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is SCNRequestAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
@ -71,7 +71,7 @@ class UserAccount extends ChangeNotifier {
|
||||
throw Exception('Not authenticated');
|
||||
}
|
||||
|
||||
final user = await APIClient.getUser(_auth!.userId, _auth!.token);
|
||||
final user = await APIClient.getUser(_auth!, _auth!.userId);
|
||||
|
||||
setUser(user);
|
||||
|
||||
|
@ -5,11 +5,13 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
import url_launcher_macos
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
|
@ -1,6 +1,30 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "67.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -17,6 +41,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.9"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.3.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -25,6 +113,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -33,6 +129,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.10.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -41,6 +145,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -49,6 +169,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.6"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -73,6 +201,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
fl_toast:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fl_toast
|
||||
sha256: "0f7bbce90d1b75463a414c6a5476e45bd93fa7c4adccce1690076f4d1ef77c42"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -111,6 +255,54 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "10.7.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
hive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: hive
|
||||
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
hive_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: hive_flutter
|
||||
sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
hive_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: hive_generator
|
||||
sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -119,6 +311,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -143,6 +343,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.1"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -175,6 +399,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -199,6 +431,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -207,6 +447,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -279,6 +543,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -287,6 +559,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
qr:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -359,6 +647,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -372,6 +676,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.12"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
source_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_helper
|
||||
sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.4"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -380,30 +700,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
sqflite_common_ffi:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sqflite_common_ffi
|
||||
sha256: "4d6137c29e930d6e4a8ff373989dd9de7bac12e3bc87bce950f6e844e8ad3bb5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.3"
|
||||
sqlite3:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqlite3
|
||||
sha256: b384f598b813b347c5a7e5ffad82cbaff1bec3d1561af267041e66f6f0899295
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -420,6 +716,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -428,14 +732,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -452,6 +748,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -540,6 +844,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -548,6 +860,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.5"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -564,6 +884,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=3.19.0"
|
||||
|
@ -1,40 +1,16 @@
|
||||
name: simplecloudnotifier
|
||||
description: "A new Flutter project."
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
publish_to: 'none'
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 2.0.0+100
|
||||
|
||||
environment:
|
||||
sdk: '>=3.2.6 <4.0.0'
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
# the latest version available on pub.dev. To see which dependencies have newer
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
font_awesome_flutter: '>= 4.7.0'
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
http: ^1.2.0
|
||||
provider: ^6.1.1
|
||||
@ -43,8 +19,11 @@ dependencies:
|
||||
url_launcher: ^6.2.4
|
||||
infinite_scroll_pagination: ^4.0.0
|
||||
intl: ^0.19.0
|
||||
sqflite_common_ffi: ^2.3.3
|
||||
path_provider: ^2.1.3
|
||||
hive: ^2.2.3
|
||||
hive_flutter: ^1.1.0
|
||||
package_info_plus: ^8.0.0
|
||||
fl_toast: ^3.2.0
|
||||
|
||||
|
||||
dependency_overrides:
|
||||
@ -56,51 +35,9 @@ dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^4.0.0
|
||||
hive_generator: ^2.0.1
|
||||
build_runner: ^2.1.4
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
|
Loading…
Reference in New Issue
Block a user