✨ Maintain basic messaging websocket
| @@ -2,7 +2,7 @@ | |||||||
|     <application |     <application | ||||||
|         android:label="solian" |         android:label="solian" | ||||||
|         android:name="${applicationName}" |         android:name="${applicationName}" | ||||||
|         android:icon="@mipmap/ic_launcher"> |         android:icon="@mipmap/launcher_icon"> | ||||||
|         <activity |         <activity | ||||||
|             android:name=".MainActivity" |             android:name=".MainActivity" | ||||||
|             android:exported="true" |             android:exported="true" | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/mipmap-hdpi/launcher_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/mipmap-mdpi/launcher_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 9.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icon.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 69 KiB | 
| @@ -541,7 +541,7 @@ | |||||||
| 			isa = XCBuildConfiguration; | 			isa = XCBuildConfiguration; | ||||||
| 			buildSettings = { | 			buildSettings = { | ||||||
| 				ALWAYS_SEARCH_USER_PATHS = NO; | 				ALWAYS_SEARCH_USER_PATHS = NO; | ||||||
| 				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; | 				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; | ||||||
| 				CLANG_ANALYZER_NONNULL = YES; | 				CLANG_ANALYZER_NONNULL = YES; | ||||||
| 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | ||||||
| 				CLANG_CXX_LIBRARY = "libc++"; | 				CLANG_CXX_LIBRARY = "libc++"; | ||||||
| @@ -598,7 +598,7 @@ | |||||||
| 			isa = XCBuildConfiguration; | 			isa = XCBuildConfiguration; | ||||||
| 			buildSettings = { | 			buildSettings = { | ||||||
| 				ALWAYS_SEARCH_USER_PATHS = NO; | 				ALWAYS_SEARCH_USER_PATHS = NO; | ||||||
| 				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; | 				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; | ||||||
| 				CLANG_ANALYZER_NONNULL = YES; | 				CLANG_ANALYZER_NONNULL = YES; | ||||||
| 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | ||||||
| 				CLANG_CXX_LIBRARY = "libc++"; | 				CLANG_CXX_LIBRARY = "libc++"; | ||||||
|   | |||||||
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 63 KiB | 
| Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 625 B | 
| Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.4 KiB | 
| Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 2.3 KiB | 
| Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 958 B | 
| Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 2.2 KiB | 
| Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 3.7 KiB | 
| Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.4 KiB | 
| Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 3.3 KiB | 
| Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 5.6 KiB | 
| After Width: | Height: | Size: 1.8 KiB | 
| After Width: | Height: | Size: 4.5 KiB | 
| After Width: | Height: | Size: 2.1 KiB | 
| After Width: | Height: | Size: 5.3 KiB | 
| Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 5.6 KiB | 
| Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 8.9 KiB | 
| After Width: | Height: | Size: 2.9 KiB | 
| After Width: | Height: | Size: 6.8 KiB | 
| Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 3.1 KiB | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 7.4 KiB | 
| Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 8.0 KiB | 
| @@ -1,6 +1,7 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
|  | import 'package:solian/providers/chat.dart'; | ||||||
| import 'package:solian/providers/navigation.dart'; | import 'package:solian/providers/navigation.dart'; | ||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/utils/timeago.dart'; | import 'package:solian/utils/timeago.dart'; | ||||||
| @@ -37,6 +38,7 @@ class SolianApp extends StatelessWidget { | |||||||
|                 providers: [ |                 providers: [ | ||||||
|                   Provider(create: (_) => NavigationProvider()), |                   Provider(create: (_) => NavigationProvider()), | ||||||
|                   Provider(create: (_) => AuthProvider()), |                   Provider(create: (_) => AuthProvider()), | ||||||
|  |                   Provider(create: (_) => ChatProvider()), | ||||||
|                 ], |                 ], | ||||||
|                 child: child, |                 child: child, | ||||||
|               ); |               ); | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								lib/models/packet.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,23 @@ | |||||||
|  | class NetworkPackage { | ||||||
|  |   String method; | ||||||
|  |   String? message; | ||||||
|  |   Map<String, dynamic>? payload; | ||||||
|  |  | ||||||
|  |   NetworkPackage({ | ||||||
|  |     required this.method, | ||||||
|  |     this.message, | ||||||
|  |     this.payload, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   factory NetworkPackage.fromJson(Map<String, dynamic> json) => NetworkPackage( | ||||||
|  |     method: json["w"], | ||||||
|  |     message: json["m"], | ||||||
|  |     payload: json["p"], | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   Map<String, dynamic> toJson() => { | ||||||
|  |     "w": method, | ||||||
|  |     "m": message, | ||||||
|  |     "p": payload, | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								lib/providers/chat.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,29 @@ | |||||||
|  | import 'dart:async'; | ||||||
|  |  | ||||||
|  | import 'package:solian/providers/auth.dart'; | ||||||
|  | import 'package:solian/utils/service_url.dart'; | ||||||
|  | import 'package:web_socket_channel/web_socket_channel.dart'; | ||||||
|  |  | ||||||
|  | class ChatProvider { | ||||||
|  |   bool isOpened = false; | ||||||
|  |  | ||||||
|  |   Future<WebSocketChannel?> connect(AuthProvider auth) async { | ||||||
|  |     if (auth.client == null) await auth.pickClient(); | ||||||
|  |     if (!await auth.isAuthorized()) return null; | ||||||
|  |  | ||||||
|  |     await auth.refreshToken(); | ||||||
|  |  | ||||||
|  |     var ori = getRequestUri('messaging', '/api/unified'); | ||||||
|  |     var uri = Uri( | ||||||
|  |       scheme: ori.scheme.replaceFirst('http', 'ws'), | ||||||
|  |       host: ori.host, | ||||||
|  |       path: ori.path, | ||||||
|  |       queryParameters: {'tk': Uri.encodeComponent(auth.client!.credentials.accessToken)}, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     final channel = WebSocketChannel.connect(uri); | ||||||
|  |     await channel.ready; | ||||||
|  |  | ||||||
|  |     return channel; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -1,6 +1,5 @@ | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
|  |  | ||||||
| import 'package:flutter/cupertino.dart'; |  | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| @@ -9,6 +8,7 @@ import 'package:solian/models/message.dart'; | |||||||
| import 'package:solian/models/pagination.dart'; | import 'package:solian/models/pagination.dart'; | ||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
|  | import 'package:solian/widgets/chat/maintainer.dart'; | ||||||
| import 'package:solian/widgets/chat/message.dart'; | import 'package:solian/widgets/chat/message.dart'; | ||||||
| import 'package:solian/widgets/chat/message_editor.dart'; | import 'package:solian/widgets/chat/message_editor.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/indent_wrapper.dart'; | ||||||
| @@ -78,6 +78,14 @@ class _ChatScreenState extends State<ChatScreen> { | |||||||
|     return a.createdAt.difference(b.createdAt).inMinutes <= 5; |     return a.createdAt.difference(b.createdAt).inMinutes <= 5; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void addMessage(Message item) { | ||||||
|  |     WidgetsBinding.instance.addPostFrameCallback((_) { | ||||||
|  |       setState(() { | ||||||
|  |         _pagingController.itemList?.insert(0, item); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
|     Future.delayed(Duration.zero, () { |     Future.delayed(Duration.zero, () { | ||||||
| @@ -94,35 +102,43 @@ class _ChatScreenState extends State<ChatScreen> { | |||||||
|     return IndentWrapper( |     return IndentWrapper( | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       title: _channelMeta?.name ?? "Loading...", |       title: _channelMeta?.name ?? "Loading...", | ||||||
|       child: Column( |       child: ChatMaintainer( | ||||||
|         children: [ |         child: Column( | ||||||
|           Expanded( |           children: [ | ||||||
|             child: PagedListView<int, Message>( |             Expanded( | ||||||
|               pagingController: _pagingController, |               child: PagedListView<int, Message>( | ||||||
|               builderDelegate: PagedChildBuilderDelegate<Message>( |                 reverse: true, | ||||||
|                 itemBuilder: (context, item, index) { |                 pagingController: _pagingController, | ||||||
|                   bool isMerged = false, hasMerged = false; |                 builderDelegate: PagedChildBuilderDelegate<Message>( | ||||||
|                   if (index > 0) { |                   itemBuilder: (context, item, index) { | ||||||
|                     isMerged = getMessageMergeable(_pagingController.itemList?[index - 1], item); |                     bool isMerged = false, hasMerged = false; | ||||||
|                   } |                     if (index > 0) { | ||||||
|                   if (index + 1 < (_pagingController.itemList?.length ?? 0)) { |                       hasMerged = getMessageMergeable(_pagingController.itemList?[index - 1], item); | ||||||
|                     hasMerged = getMessageMergeable(item, _pagingController.itemList?[index + 1]); |                     } | ||||||
|                   } |                     if (index + 1 < (_pagingController.itemList?.length ?? 0)) { | ||||||
|                   return Container( |                       isMerged = getMessageMergeable(item, _pagingController.itemList?[index + 1]); | ||||||
|                     padding: EdgeInsets.only( |                     } | ||||||
|                       top: !isMerged ? 8 : 0, |                     return Container( | ||||||
|                       bottom: !hasMerged ? 8 : 0, |                       padding: EdgeInsets.only( | ||||||
|                       left: 12, |                         top: !isMerged ? 8 : 0, | ||||||
|                       right: 12, |                         bottom: !hasMerged ? 8 : 0, | ||||||
|                     ), |                         left: 12, | ||||||
|                     child: ChatMessage(item: item, underMerged: isMerged), |                         right: 12, | ||||||
|                   ); |                       ), | ||||||
|                 }, |                       child: ChatMessage( | ||||||
|  |                         key: Key('m${item.id}'), | ||||||
|  |                         item: item, | ||||||
|  |                         underMerged: isMerged, | ||||||
|  |                       ), | ||||||
|  |                     ); | ||||||
|  |                   }, | ||||||
|  |                 ), | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|           ), |             ChatMessageEditor(channel: widget.alias), | ||||||
|           ChatMessageEditor(channel: widget.alias), |           ], | ||||||
|         ], |         ), | ||||||
|  |         onNewMessage: (message) => addMessage(message), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								lib/widgets/chat/maintainer.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,45 @@ | |||||||
|  | import 'dart:convert'; | ||||||
|  |  | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:solian/models/message.dart'; | ||||||
|  | import 'package:solian/models/packet.dart'; | ||||||
|  | import 'package:solian/providers/auth.dart'; | ||||||
|  | import 'package:solian/providers/chat.dart'; | ||||||
|  |  | ||||||
|  | class ChatMaintainer extends StatefulWidget { | ||||||
|  |   final Widget child; | ||||||
|  |   final Function(Message val) onNewMessage; | ||||||
|  |  | ||||||
|  |   const ChatMaintainer({super.key, required this.child, required this.onNewMessage}); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   State<ChatMaintainer> createState() => _ChatMaintainerState(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class _ChatMaintainerState extends State<ChatMaintainer> { | ||||||
|  |   @override | ||||||
|  |   void initState() { | ||||||
|  |     Future.delayed(Duration.zero, () { | ||||||
|  |       final auth = context.read<AuthProvider>(); | ||||||
|  |       final chat = context.read<ChatProvider>(); | ||||||
|  |  | ||||||
|  |       chat.connect(auth).then((snapshot) { | ||||||
|  |         snapshot!.stream.listen((event) { | ||||||
|  |           final result = NetworkPackage.fromJson(jsonDecode(event)); | ||||||
|  |           switch (result.method) { | ||||||
|  |             case 'messages.new': | ||||||
|  |               widget.onNewMessage(Message.fromJson(result.payload!)); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     super.initState(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return widget.child; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -46,7 +46,11 @@ class ChatMessage extends StatelessWidget { | |||||||
|       return Row( |       return Row( | ||||||
|         children: [ |         children: [ | ||||||
|           const SizedBox(width: 40), |           const SizedBox(width: 40), | ||||||
|           Expanded(child: contentPart), |           Expanded( | ||||||
|  |             child: Column( | ||||||
|  |               children: [contentPart, renderAttachment()], | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|         ], |         ], | ||||||
|       ); |       ); | ||||||
|     } else { |     } else { | ||||||
|   | |||||||
| @@ -1,68 +1,68 @@ | |||||||
| { | { | ||||||
|   "images" : [ |     "info": { | ||||||
|     { |         "version": 1, | ||||||
|       "size" : "16x16", |         "author": "xcode" | ||||||
|       "idiom" : "mac", |  | ||||||
|       "filename" : "app_icon_16.png", |  | ||||||
|       "scale" : "1x" |  | ||||||
|     }, |     }, | ||||||
|     { |     "images": [ | ||||||
|       "size" : "16x16", |         { | ||||||
|       "idiom" : "mac", |             "size": "16x16", | ||||||
|       "filename" : "app_icon_32.png", |             "idiom": "mac", | ||||||
|       "scale" : "2x" |             "filename": "app_icon_16.png", | ||||||
|     }, |             "scale": "1x" | ||||||
|     { |         }, | ||||||
|       "size" : "32x32", |         { | ||||||
|       "idiom" : "mac", |             "size": "16x16", | ||||||
|       "filename" : "app_icon_32.png", |             "idiom": "mac", | ||||||
|       "scale" : "1x" |             "filename": "app_icon_32.png", | ||||||
|     }, |             "scale": "2x" | ||||||
|     { |         }, | ||||||
|       "size" : "32x32", |         { | ||||||
|       "idiom" : "mac", |             "size": "32x32", | ||||||
|       "filename" : "app_icon_64.png", |             "idiom": "mac", | ||||||
|       "scale" : "2x" |             "filename": "app_icon_32.png", | ||||||
|     }, |             "scale": "1x" | ||||||
|     { |         }, | ||||||
|       "size" : "128x128", |         { | ||||||
|       "idiom" : "mac", |             "size": "32x32", | ||||||
|       "filename" : "app_icon_128.png", |             "idiom": "mac", | ||||||
|       "scale" : "1x" |             "filename": "app_icon_64.png", | ||||||
|     }, |             "scale": "2x" | ||||||
|     { |         }, | ||||||
|       "size" : "128x128", |         { | ||||||
|       "idiom" : "mac", |             "size": "128x128", | ||||||
|       "filename" : "app_icon_256.png", |             "idiom": "mac", | ||||||
|       "scale" : "2x" |             "filename": "app_icon_128.png", | ||||||
|     }, |             "scale": "1x" | ||||||
|     { |         }, | ||||||
|       "size" : "256x256", |         { | ||||||
|       "idiom" : "mac", |             "size": "128x128", | ||||||
|       "filename" : "app_icon_256.png", |             "idiom": "mac", | ||||||
|       "scale" : "1x" |             "filename": "app_icon_256.png", | ||||||
|     }, |             "scale": "2x" | ||||||
|     { |         }, | ||||||
|       "size" : "256x256", |         { | ||||||
|       "idiom" : "mac", |             "size": "256x256", | ||||||
|       "filename" : "app_icon_512.png", |             "idiom": "mac", | ||||||
|       "scale" : "2x" |             "filename": "app_icon_256.png", | ||||||
|     }, |             "scale": "1x" | ||||||
|     { |         }, | ||||||
|       "size" : "512x512", |         { | ||||||
|       "idiom" : "mac", |             "size": "256x256", | ||||||
|       "filename" : "app_icon_512.png", |             "idiom": "mac", | ||||||
|       "scale" : "1x" |             "filename": "app_icon_512.png", | ||||||
|     }, |             "scale": "2x" | ||||||
|     { |         }, | ||||||
|       "size" : "512x512", |         { | ||||||
|       "idiom" : "mac", |             "size": "512x512", | ||||||
|       "filename" : "app_icon_1024.png", |             "idiom": "mac", | ||||||
|       "scale" : "2x" |             "filename": "app_icon_512.png", | ||||||
|     } |             "scale": "1x" | ||||||
|   ], |         }, | ||||||
|   "info" : { |         { | ||||||
|     "version" : 1, |             "size": "512x512", | ||||||
|     "author" : "xcode" |             "idiom": "mac", | ||||||
|   } |             "filename": "app_icon_1024.png", | ||||||
|  |             "scale": "2x" | ||||||
|  |         } | ||||||
|  |     ] | ||||||
| } | } | ||||||
| Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 63 KiB | 
| Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 6.0 KiB | 
| Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 480 B | 
| Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 29 KiB | 
| Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.5 KiB | 
							
								
								
									
										48
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						| @@ -41,6 +41,22 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "1.3.0" |     version: "1.3.0" | ||||||
|  |   checked_yaml: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: checked_yaml | ||||||
|  |       sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "2.0.3" | ||||||
|  |   cli_util: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: cli_util | ||||||
|  |       sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "0.4.1" | ||||||
|   clock: |   clock: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
| @@ -166,6 +182,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "2.2.0" |     version: "2.2.0" | ||||||
|  |   flutter_launcher_icons: | ||||||
|  |     dependency: "direct main" | ||||||
|  |     description: | ||||||
|  |       name: flutter_launcher_icons | ||||||
|  |       sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "0.13.1" | ||||||
|   flutter_lints: |   flutter_lints: | ||||||
|     dependency: "direct dev" |     dependency: "direct dev" | ||||||
|     description: |     description: | ||||||
| @@ -397,6 +421,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "0.6.7" |     version: "0.6.7" | ||||||
|  |   json_annotation: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: json_annotation | ||||||
|  |       sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "4.8.1" | ||||||
|   leak_tracker: |   leak_tracker: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
| @@ -962,6 +994,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "0.5.1" |     version: "0.5.1" | ||||||
|  |   web_socket_channel: | ||||||
|  |     dependency: "direct main" | ||||||
|  |     description: | ||||||
|  |       name: web_socket_channel | ||||||
|  |       sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "2.4.5" | ||||||
|   webview_flutter: |   webview_flutter: | ||||||
|     dependency: "direct main" |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
| @@ -1018,6 +1058,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "6.5.0" |     version: "6.5.0" | ||||||
|  |   yaml: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: yaml | ||||||
|  |       sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "3.1.2" | ||||||
| sdks: | sdks: | ||||||
|   dart: ">=3.3.3 <4.0.0" |   dart: ">=3.3.3 <4.0.0" | ||||||
|   flutter: ">=3.19.0" |   flutter: ">=3.19.0" | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								pubspec.yaml
									
									
									
									
									
								
							
							
						
						| @@ -57,6 +57,8 @@ dependencies: | |||||||
|   media_kit: ^1.1.10+1 |   media_kit: ^1.1.10+1 | ||||||
|   media_kit_libs_video: ^1.0.4 |   media_kit_libs_video: ^1.0.4 | ||||||
|   hive_flutter: ^1.1.0 |   hive_flutter: ^1.1.0 | ||||||
|  |   flutter_launcher_icons: ^0.13.1 | ||||||
|  |   web_socket_channel: ^2.4.5 | ||||||
|  |  | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   flutter_test: | ||||||
| @@ -111,3 +113,21 @@ flutter: | |||||||
|   # |   # | ||||||
|   # For details regarding fonts from package dependencies, |   # For details regarding fonts from package dependencies, | ||||||
|   # see https://flutter.dev/custom-fonts/#from-packages |   # see https://flutter.dev/custom-fonts/#from-packages | ||||||
|  |  | ||||||
|  | flutter_launcher_icons: | ||||||
|  |   android: "launcher_icon" | ||||||
|  |   ios: true | ||||||
|  |   image_path: "assets/icon.png" | ||||||
|  |   min_sdk_android: 21 | ||||||
|  |   web: | ||||||
|  |     generate: true | ||||||
|  |     image_path: "assets/icon.png" | ||||||
|  |     background_color: "#ffffff" | ||||||
|  |     theme_color: "#4b5094" | ||||||
|  |   windows: | ||||||
|  |     generate: true | ||||||
|  |     image_path: "assets/icon.png" | ||||||
|  |     icon_size: 256 | ||||||
|  |   macos: | ||||||
|  |     generate: true | ||||||
|  |     image_path: "assets/icon.png" | ||||||
							
								
								
									
										
											BIN
										
									
								
								web/favicon.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 917 B After Width: | Height: | Size: 480 B | 
| Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 9.6 KiB | 
| Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 29 KiB | 
| Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 9.6 KiB | 
| Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 29 KiB | 
| @@ -3,8 +3,8 @@ | |||||||
|     "short_name": "solian", |     "short_name": "solian", | ||||||
|     "start_url": ".", |     "start_url": ".", | ||||||
|     "display": "standalone", |     "display": "standalone", | ||||||
|     "background_color": "#0175C2", |     "background_color": "#ffffff", | ||||||
|     "theme_color": "#0175C2", |     "theme_color": "#4b5094", | ||||||
|     "description": "A new Flutter project.", |     "description": "A new Flutter project.", | ||||||
|     "orientation": "portrait-primary", |     "orientation": "portrait-primary", | ||||||
|     "prefer_related_applications": false, |     "prefer_related_applications": false, | ||||||
|   | |||||||
| Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 13 KiB |