Compare commits
	
		
			11 Commits
		
	
	
		
			3.1.0+121
			...
			c061ef2132
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c061ef2132 | |||
| c378309bdd | |||
| b2c5d64fc5 | |||
|  | 5371637b16 | ||
| c5cbf0af37 | |||
| 1a31e22450 | |||
|  | 49db54529d | ||
| 8e0c0c6054 | |||
| f3d1183076 | |||
| a9f7f0cce0 | |||
| f2943f8411 | 
| @@ -51,6 +51,12 @@ android { | ||||
|     buildTypes { | ||||
|         release { | ||||
|             signingConfig = signingConfigs.getByName("release") | ||||
|  | ||||
|             isMinifyEnabled = true | ||||
|             proguardFiles( | ||||
|                 getDefaultProguardFile("proguard-android-optimize.txt"), | ||||
|                 "proguard-rules.pro" | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -58,7 +64,7 @@ android { | ||||
| dependencies { | ||||
|     implementation("com.google.android.material:material:1.12.0") | ||||
|     implementation("com.github.bumptech.glide:glide:4.16.0") | ||||
|     implementation("com.squareup.okhttp3:okhttp:4.12.0") | ||||
|     implementation("com.squareup.okhttp3:okhttp:5.1.0") | ||||
| } | ||||
|  | ||||
| flutter { | ||||
|   | ||||
							
								
								
									
										5
									
								
								android/app/proguard-rules.pro
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								android/app/proguard-rules.pro
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| # JNI Zero initialization (required for WebRTC native method registration) | ||||
| -keep class livekit.org.jni_zero.JniInit { | ||||
|     # Keep the init method un-obfuscated for native code callback | ||||
|     private static java.lang.Object[] init(); | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable/ic_notification.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable/ic_notification.png
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 70 KiB | 
| @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| zipStorePath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip | ||||
|   | ||||
| @@ -18,11 +18,11 @@ pluginManagement { | ||||
|  | ||||
| plugins { | ||||
|     id("dev.flutter.flutter-plugin-loader") version "1.0.0" | ||||
|     id("com.android.application") version "8.10.1" apply false | ||||
|     id("com.android.application") version "8.12.0" apply false | ||||
|     // START: FlutterFire Configuration | ||||
|     id("com.google.gms.google-services") version("4.3.15") apply false | ||||
|     // END: FlutterFire Configuration | ||||
|     id("org.jetbrains.kotlin.android") version "1.8.22" apply false | ||||
|     id("org.jetbrains.kotlin.android") version("2.2.0") apply false | ||||
| } | ||||
|  | ||||
| include(":app") | ||||
|   | ||||
| @@ -789,5 +789,6 @@ | ||||
|   "linkKey": "Link Name", | ||||
|   "linkValue": "URL", | ||||
|   "debugOptions": "Debug Options", | ||||
|   "joinedAt": "Joined at {}" | ||||
|   "joinedAt": "Joined at {}", | ||||
|   "searchAccounts": "Search accounts..." | ||||
| } | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -34,7 +34,7 @@ class NotifyDelegate: UIResponder, UNUserNotificationCenterDelegate { | ||||
|         } | ||||
|          | ||||
|         let serverUrl = UserDefaults.standard.getServerUrl() | ||||
|         let url = "\(serverUrl)/chat/\(metadata["room_id"] ?? "")/messages" | ||||
|         let url = "\(serverUrl)/sphere/chat/\(metadata["room_id"] ?? "")/messages" | ||||
|          | ||||
|         let parameters: [String: Any?] = [ | ||||
|             "content": textResponse.userText, | ||||
|   | ||||
| @@ -28,6 +28,7 @@ import 'package:relative_time/relative_time.dart'; | ||||
| import 'package:shared_preferences/shared_preferences.dart'; | ||||
| import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; | ||||
| import 'package:flutter_native_splash/flutter_native_splash.dart'; | ||||
| import 'package:island/widgets/keyboard_navigation.dart'; | ||||
| import 'package:url_launcher/url_launcher_string.dart'; | ||||
| import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect; | ||||
|  | ||||
| @@ -244,30 +245,32 @@ class IslandApp extends HookConsumerWidget { | ||||
|  | ||||
|     final router = ref.watch(routerProvider); | ||||
|  | ||||
|     return MaterialApp.router( | ||||
|       theme: theme?.light, | ||||
|       darkTheme: theme?.dark, | ||||
|       themeMode: ThemeMode.system, | ||||
|       routerConfig: router, | ||||
|       supportedLocales: context.supportedLocales, | ||||
|       localizationsDelegates: [ | ||||
|         ...context.localizationDelegates, | ||||
|         CroppyLocalizations.delegate, | ||||
|         RelativeTimeLocalizations.delegate, | ||||
|       ], | ||||
|       locale: context.locale, | ||||
|       builder: (context, child) { | ||||
|         return Overlay( | ||||
|           key: globalOverlay, | ||||
|           initialEntries: [ | ||||
|             OverlayEntry( | ||||
|               builder: | ||||
|                   (_) => | ||||
|                       WindowScaffold(child: child ?? const SizedBox.shrink()), | ||||
|             ), | ||||
|           ], | ||||
|         ); | ||||
|       }, | ||||
|     return KeyboardNavigation( | ||||
|       child: MaterialApp.router( | ||||
|         theme: theme?.light, | ||||
|         darkTheme: theme?.dark, | ||||
|         themeMode: ThemeMode.system, | ||||
|         routerConfig: router, | ||||
|         supportedLocales: context.supportedLocales, | ||||
|         localizationsDelegates: [ | ||||
|           ...context.localizationDelegates, | ||||
|           CroppyLocalizations.delegate, | ||||
|           RelativeTimeLocalizations.delegate, | ||||
|         ], | ||||
|         locale: context.locale, | ||||
|         builder: (context, child) { | ||||
|           return Overlay( | ||||
|             key: globalOverlay, | ||||
|             initialEntries: [ | ||||
|               OverlayEntry( | ||||
|                 builder: | ||||
|                     (_) => | ||||
|                         WindowScaffold(child: child ?? const SizedBox.shrink()), | ||||
|               ), | ||||
|             ], | ||||
|           ); | ||||
|         }, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -216,6 +216,7 @@ class RelationshipScreen extends HookConsumerWidget { | ||||
|       final result = await showModalBottomSheet( | ||||
|         context: context, | ||||
|         useRootNavigator: true, | ||||
|         isScrollControlled: true, | ||||
|         builder: (context) => AccountPickerSheet(), | ||||
|       ); | ||||
|       if (result == null) return; | ||||
|   | ||||
| @@ -227,6 +227,7 @@ class ChatListScreen extends HookConsumerWidget { | ||||
|       final result = await showModalBottomSheet( | ||||
|         context: context, | ||||
|         useRootNavigator: true, | ||||
|         isScrollControlled: true, | ||||
|         builder: (context) => const AccountPickerSheet(), | ||||
|       ); | ||||
|       if (result == null) return; | ||||
|   | ||||
| @@ -339,7 +339,7 @@ class ChatRoomScreen extends HookConsumerWidget { | ||||
|                             } | ||||
|  | ||||
|                             await apiClient.post( | ||||
|                               '/chat/${chatRoom.value!.id}/members/me', | ||||
|                               '/sphere/chat/${chatRoom.value!.id}/members/me', | ||||
|                             ); | ||||
|                             ref.invalidate(chatroomIdentityProvider(id)); | ||||
|                           } catch (err) { | ||||
| @@ -929,7 +929,7 @@ class ChatRoomScreen extends HookConsumerWidget { | ||||
|                             if (attachment.isOnCloud) { | ||||
|                               final client = ref.watch(apiClientProvider); | ||||
|                               await client.delete( | ||||
|                                 '/files/${attachment.data.id}', | ||||
|                                 '/drive/files/${attachment.data.id}', | ||||
|                               ); | ||||
|                             } | ||||
|                             final clone = List.of(attachments.value); | ||||
|   | ||||
| @@ -589,6 +589,7 @@ class _ChatMemberListSheet extends HookConsumerWidget { | ||||
|       final result = await showModalBottomSheet( | ||||
|         context: context, | ||||
|         useRootNavigator: true, | ||||
|         isScrollControlled: true, | ||||
|         builder: (context) => const AccountPickerSheet(), | ||||
|       ); | ||||
|       if (result == null) return; | ||||
| @@ -727,7 +728,7 @@ class _ChatMemberListSheet extends HookConsumerWidget { | ||||
|                                       apiClientProvider, | ||||
|                                     ); | ||||
|                                     await apiClient.delete( | ||||
|                                       '/chat/$roomId/members/${member.accountId}', | ||||
|                                       '/sphere/chat/$roomId/members/${member.accountId}', | ||||
|                                     ); | ||||
|                                     // Refresh both providers | ||||
|                                     memberNotifier.reset(); | ||||
|   | ||||
| @@ -708,6 +708,7 @@ class _PublisherMemberListSheet extends HookConsumerWidget { | ||||
|  | ||||
|     Future<void> invitePerson() async { | ||||
|       final result = await showModalBottomSheet( | ||||
|         useRootNavigator: true, | ||||
|         isScrollControlled: true, | ||||
|         context: context, | ||||
|         builder: (context) => const AccountPickerSheet(), | ||||
|   | ||||
| @@ -180,6 +180,7 @@ class StickerPackDetailScreen extends HookConsumerWidget { | ||||
|                                               .pushNamed( | ||||
|                                                 'creatorStickerEdit', | ||||
|                                                 pathParameters: { | ||||
|                                                   'name': pubName, | ||||
|                                                   'packId': id, | ||||
|                                                   'id': sticker.id, | ||||
|                                                 }, | ||||
|   | ||||
| @@ -31,7 +31,7 @@ class StickersScreen extends HookConsumerWidget { | ||||
|               context | ||||
|                   .pushNamed( | ||||
|                     'creatorStickerPackNew', | ||||
|                     queryParameters: {'name': pubName}, | ||||
|                     pathParameters: {'name': pubName}, | ||||
|                   ) | ||||
|                   .then((value) { | ||||
|                     if (value != null) { | ||||
| @@ -187,10 +187,8 @@ class EditStickerPacksScreen extends HookConsumerWidget { | ||||
|             'description': descriptionController.text, | ||||
|             'prefix': prefixController.text, | ||||
|           }, | ||||
|           options: Options( | ||||
|             method: packId == null ? 'POST' : 'PATCH', | ||||
|             headers: {'X-Pub': pubName}, | ||||
|           ), | ||||
|           queryParameters: {'pub': pubName}, | ||||
|           options: Options(method: packId == null ? 'POST' : 'PATCH'), | ||||
|         ); | ||||
|         if (!context.mounted) return; | ||||
|         context.pop(SnStickerPack.fromJson(resp.data)); | ||||
|   | ||||
| @@ -488,6 +488,7 @@ class _RealmMemberListSheet extends HookConsumerWidget { | ||||
|     Future<void> invitePerson() async { | ||||
|       final result = await showModalBottomSheet( | ||||
|         isScrollControlled: true, | ||||
|         useRootNavigator: true, | ||||
|         context: context, | ||||
|         builder: (context) => const AccountPickerSheet(), | ||||
|       ); | ||||
|   | ||||
| @@ -67,6 +67,9 @@ Future<void> subscribePushNotification( | ||||
|   Dio apiClient, { | ||||
|   bool detailedErrors = false, | ||||
| }) async { | ||||
|   if (Platform.isLinux){ | ||||
|     return; | ||||
|   } | ||||
|   await FirebaseMessaging.instance.requestPermission( | ||||
|     alert: true, | ||||
|     badge: true, | ||||
|   | ||||
| @@ -305,7 +305,7 @@ class _UpdateSheetState extends State<_UpdateSheet> { | ||||
|     UpdateModel model = UpdateModel( | ||||
|       downloadUrl, | ||||
|       "solian-update-${widget.release.tagName}.apk", | ||||
|       "ic_launcher", | ||||
|       "launcher_icon", | ||||
|       'https://apps.apple.com/us/app/solian/id6499032345', | ||||
|     ); | ||||
|     AzhonAppUpdate.update(model); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import 'dart:async'; | ||||
|  | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| @@ -44,9 +45,8 @@ class AccountPickerSheet extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     return Container( | ||||
|       constraints: BoxConstraints( | ||||
|         maxHeight: MediaQuery.of(context).size.height * 0.4, | ||||
|       ), | ||||
|       padding: MediaQuery.of(context).viewInsets, | ||||
|       height: MediaQuery.of(context).size.height * 0.6, | ||||
|       child: Column( | ||||
|         children: [ | ||||
|           Padding( | ||||
| @@ -54,8 +54,8 @@ class AccountPickerSheet extends HookConsumerWidget { | ||||
|             child: TextField( | ||||
|               controller: searchController, | ||||
|               onChanged: onSearchChanged, | ||||
|               decoration: const InputDecoration( | ||||
|                 hintText: 'Search accounts...', | ||||
|               decoration: InputDecoration( | ||||
|                 hintText: 'searchAccounts'.tr(), | ||||
|                 contentPadding: EdgeInsets.symmetric( | ||||
|                   horizontal: 18, | ||||
|                   vertical: 16, | ||||
|   | ||||
							
								
								
									
										86
									
								
								lib/widgets/keyboard_navigation.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								lib/widgets/keyboard_navigation.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
|  | ||||
| enum VimMode { normal, insert } | ||||
|  | ||||
| class KeyboardNavigation extends StatefulWidget { | ||||
|   const KeyboardNavigation({super.key, required this.child}); | ||||
|  | ||||
|   final Widget child; | ||||
|  | ||||
|   @override | ||||
|   State<KeyboardNavigation> createState() => _KeyboardNavigationState(); | ||||
| } | ||||
|  | ||||
| class _KeyboardNavigationState extends State<KeyboardNavigation> { | ||||
|   VimMode _mode = VimMode.normal; | ||||
|   final FocusScopeNode _focusScopeNode = FocusScopeNode(); | ||||
|  | ||||
|   @override | ||||
|   void dispose() { | ||||
|     _focusScopeNode.dispose(); | ||||
|     super.dispose(); | ||||
|   } | ||||
|  | ||||
|   KeyEventResult _handleKeyEvent(FocusNode node, KeyEvent event) { | ||||
|     if (event is! KeyDownEvent && event is! KeyRepeatEvent) { | ||||
|       return KeyEventResult.ignored; | ||||
|     } | ||||
|  | ||||
|     if (_mode == VimMode.normal) { | ||||
|       if (event.logicalKey == LogicalKeyboardKey.keyJ) { | ||||
|         node.focusInDirection(TraversalDirection.down); | ||||
|         return KeyEventResult.handled; | ||||
|       } else if (event.logicalKey == LogicalKeyboardKey.keyK) { | ||||
|         node.focusInDirection(TraversalDirection.up); | ||||
|         return KeyEventResult.handled; | ||||
|       } else if (event.logicalKey == LogicalKeyboardKey.keyH) { | ||||
|         final focusNode = FocusManager.instance.primaryFocus; | ||||
|         if (focusNode != null) { | ||||
|           final scrollable = Scrollable.of(focusNode.context!); | ||||
|           if (scrollable.position.axis == Axis.horizontal) { | ||||
|             scrollable.position.moveTo(scrollable.position.pixels - 50); | ||||
|             return KeyEventResult.handled; | ||||
|           } | ||||
|         } | ||||
|         node.focusInDirection(TraversalDirection.left); | ||||
|         return KeyEventResult.handled; | ||||
|       } else if (event.logicalKey == LogicalKeyboardKey.keyL) { | ||||
|         final focusNode = FocusManager.instance.primaryFocus; | ||||
|         if (focusNode != null) { | ||||
|           final scrollable = Scrollable.of(focusNode.context!); | ||||
|           if (scrollable.position.axis == Axis.horizontal) { | ||||
|             scrollable.position.moveTo(scrollable.position.pixels + 50); | ||||
|             return KeyEventResult.handled; | ||||
|           } | ||||
|         } | ||||
|         node.focusInDirection(TraversalDirection.right); | ||||
|         return KeyEventResult.handled; | ||||
|       } else if (event.logicalKey == LogicalKeyboardKey.keyI) { | ||||
|         setState(() { | ||||
|           _mode = VimMode.insert; | ||||
|         }); | ||||
|         return KeyEventResult.handled; | ||||
|       } | ||||
|     } else if (_mode == VimMode.insert) { | ||||
|       if (event.logicalKey == LogicalKeyboardKey.escape) { | ||||
|         setState(() { | ||||
|           _mode = VimMode.normal; | ||||
|         }); | ||||
|         // Unfocus the current widget to prevent typing | ||||
|         node.unfocus(); | ||||
|         return KeyEventResult.handled; | ||||
|       } | ||||
|     } | ||||
|     return KeyEventResult.ignored; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Focus( | ||||
|       focusNode: _focusScopeNode, | ||||
|       onKeyEvent: _handleKeyEvent, | ||||
|       child: widget.child, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev | ||||
| # 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: 3.1.0+121 | ||||
| version: 3.1.0+122 | ||||
|  | ||||
| environment: | ||||
|   sdk: ^3.7.2 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user