Compare commits
	
		
			18 Commits
		
	
	
		
			594ac39e3d
			...
			3.1.0+113
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a7454edec0 | |||
| cbf1952eb7 | |||
| 6d06f0a1b4 | |||
| f2d2a9efd8 | |||
| d44c8217b0 | |||
| 446c33d8b0 | |||
| 996462f1fd | |||
| 778f6bb79f | |||
| 8747f948b9 | |||
| 9546d6e4b8 | |||
| f8d1940af6 | |||
| b2b0891d24 | |||
| 274168d4bc | |||
| 2c98b348d5 | |||
| afc7887ddd | |||
| 99ff78a3d5 | |||
| 2ad85addf6 | |||
| 552b4b2572 | 
| @@ -41,7 +41,16 @@ | ||||
|                 <action android:name="android.intent.action.MAIN" /> | ||||
|                 <category android:name="android.intent.category.LAUNCHER" /> | ||||
|             </intent-filter> | ||||
|              | ||||
|  | ||||
|             <!-- Deeplinking --> | ||||
|             <intent-filter android:autoVerify="true"> | ||||
|                 <action android:name="android.intent.action.VIEW" /> | ||||
|                 <category android:name="android.intent.category.DEFAULT" /> | ||||
|                 <category android:name="android.intent.category.BROWSABLE" /> | ||||
|                 <data android:scheme="http" android:host="solian.app" /> | ||||
|                 <data android:scheme="https" /> | ||||
|             </intent-filter> | ||||
|  | ||||
|             <!-- Share Intent Filters --> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.SEND" /> | ||||
|   | ||||
| @@ -590,6 +590,7 @@ | ||||
|   "yes": "Yes", | ||||
|   "navigateToChat": "Navigate to Chat", | ||||
|   "wouldYouLikeToNavigateToChat": "Would You like to navigate to the chat?", | ||||
|   "abuseReports": "Abuse Reports", | ||||
|   "abuseReport": "Report", | ||||
|   "abuseReportTitle": "Report Content", | ||||
|   "abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.", | ||||
|   | ||||
| @@ -45,10 +45,10 @@ PODS: | ||||
|   - Firebase/Messaging (11.15.0): | ||||
|     - Firebase/CoreOnly | ||||
|     - FirebaseMessaging (~> 11.15.0) | ||||
|   - firebase_core (3.15.0): | ||||
|   - firebase_core (3.15.1): | ||||
|     - Firebase/CoreOnly (= 11.15.0) | ||||
|     - Flutter | ||||
|   - firebase_messaging (15.2.8): | ||||
|   - firebase_messaging (15.2.9): | ||||
|     - Firebase/Messaging (= 11.15.0) | ||||
|     - firebase_core | ||||
|     - Flutter | ||||
| @@ -130,7 +130,7 @@ PODS: | ||||
|     - Flutter | ||||
|   - irondash_engine_context (0.0.1): | ||||
|     - Flutter | ||||
|   - Kingfisher (8.3.3) | ||||
|   - Kingfisher (8.4.0) | ||||
|   - livekit_client (2.4.9): | ||||
|     - Flutter | ||||
|     - flutter_webrtc | ||||
| @@ -178,18 +178,18 @@ PODS: | ||||
|   - sqflite_darwin (0.0.4): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|   - sqlite3 (3.50.1): | ||||
|     - sqlite3/common (= 3.50.1) | ||||
|   - sqlite3/common (3.50.1) | ||||
|   - sqlite3/dbstatvtab (3.50.1): | ||||
|   - sqlite3 (3.50.2): | ||||
|     - sqlite3/common (= 3.50.2) | ||||
|   - sqlite3/common (3.50.2) | ||||
|   - sqlite3/dbstatvtab (3.50.2): | ||||
|     - sqlite3/common | ||||
|   - sqlite3/fts5 (3.50.1): | ||||
|   - sqlite3/fts5 (3.50.2): | ||||
|     - sqlite3/common | ||||
|   - sqlite3/math (3.50.1): | ||||
|   - sqlite3/math (3.50.2): | ||||
|     - sqlite3/common | ||||
|   - sqlite3/perf-threadsafe (3.50.1): | ||||
|   - sqlite3/perf-threadsafe (3.50.2): | ||||
|     - sqlite3/common | ||||
|   - sqlite3/rtree (3.50.1): | ||||
|   - sqlite3/rtree (3.50.2): | ||||
|     - sqlite3/common | ||||
|   - sqlite3_flutter_libs (0.0.1): | ||||
|     - Flutter | ||||
| @@ -362,8 +362,8 @@ SPEC CHECKSUMS: | ||||
|   DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 | ||||
|   file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be | ||||
|   Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e | ||||
|   firebase_core: c727a02c560a53f1f1e56e18f16515eb5753c492 | ||||
|   firebase_messaging: 4158969b04b667f5435731ec9d6e453bb58b0c4c | ||||
|   firebase_core: ece862f94b2bc72ee0edbeec7ab5c7cb09fe1ab5 | ||||
|   firebase_messaging: e1a5fae495603115be1d0183bc849da748734e2b | ||||
|   FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e | ||||
|   FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 | ||||
|   FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 | ||||
| @@ -382,9 +382,9 @@ SPEC CHECKSUMS: | ||||
|   GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 | ||||
|   image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a | ||||
|   irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486 | ||||
|   Kingfisher: ff82cb91d9266ddb56cbb2f72d32c26f00d3e5be | ||||
|   Kingfisher: b14cc47bbfa7a3c150dd12962ee9c86338545629 | ||||
|   livekit_client: 3f79d79233a5bd13d5b541732624ef959d7c538e | ||||
|   local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 | ||||
|   local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19 | ||||
|   media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854 | ||||
|   media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474 | ||||
|   nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 | ||||
| @@ -403,7 +403,7 @@ SPEC CHECKSUMS: | ||||
|   shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 | ||||
|   sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418 | ||||
|   sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 | ||||
|   sqlite3: 1d85290c3321153511f6e900ede7a1608718bbd5 | ||||
|   sqlite3: 3e82a2daae39ba3b41ae6ee84a130494585460fc | ||||
|   sqlite3_flutter_libs: e7fc8c9ea2200ff3271f08f127842131746b70e2 | ||||
|   super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4 | ||||
|   SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| 	archiveVersion = 1; | ||||
| 	classes = { | ||||
| 	}; | ||||
| 	objectVersion = 54; | ||||
| 	objectVersion = 77; | ||||
| 	objects = { | ||||
|  | ||||
| /* Begin PBXBuildFile section */ | ||||
| @@ -525,10 +525,14 @@ | ||||
| 			inputFileListPaths = ( | ||||
| 				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", | ||||
| 			); | ||||
| 			inputPaths = ( | ||||
| 			); | ||||
| 			name = "[CP] Copy Pods Resources"; | ||||
| 			outputFileListPaths = ( | ||||
| 				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", | ||||
| 			); | ||||
| 			outputPaths = ( | ||||
| 			); | ||||
| 			runOnlyForDeploymentPostprocessing = 0; | ||||
| 			shellPath = /bin/sh; | ||||
| 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; | ||||
| @@ -586,10 +590,14 @@ | ||||
| 			inputFileListPaths = ( | ||||
| 				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", | ||||
| 			); | ||||
| 			inputPaths = ( | ||||
| 			); | ||||
| 			name = "[CP] Embed Pods Frameworks"; | ||||
| 			outputFileListPaths = ( | ||||
| 				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", | ||||
| 			); | ||||
| 			outputPaths = ( | ||||
| 			); | ||||
| 			runOnlyForDeploymentPostprocessing = 0; | ||||
| 			shellPath = /bin/sh; | ||||
| 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; | ||||
| @@ -772,6 +780,7 @@ | ||||
| 				ENABLE_BITCODE = NO; | ||||
| 				INFOPLIST_FILE = Runner/Info.plist; | ||||
| 				INFOPLIST_KEY_CFBundleDisplayName = Solian; | ||||
| 				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 13.0; | ||||
| 				LD_RUNPATH_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| @@ -1202,6 +1211,7 @@ | ||||
| 				ENABLE_BITCODE = NO; | ||||
| 				INFOPLIST_FILE = Runner/Info.plist; | ||||
| 				INFOPLIST_KEY_CFBundleDisplayName = Solian; | ||||
| 				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 13.0; | ||||
| 				LD_RUNPATH_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| @@ -1229,6 +1239,7 @@ | ||||
| 				ENABLE_BITCODE = NO; | ||||
| 				INFOPLIST_FILE = Runner/Info.plist; | ||||
| 				INFOPLIST_KEY_CFBundleDisplayName = Solian; | ||||
| 				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 13.0; | ||||
| 				LD_RUNPATH_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
|   | ||||
| @@ -27,6 +27,7 @@ import UIKit | ||||
|         UNUserNotificationCenter.current().setNotificationCategories([replyableMessageCategory]) | ||||
|          | ||||
|         GeneratedPluginRegistrant.register(with: self) | ||||
|          | ||||
|         return super.application(application, didFinishLaunchingWithOptions: launchOptions) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> | ||||
|     <device id="retina6_12" orientation="portrait" appearance="light"/> | ||||
|     <dependencies> | ||||
|         <deployment identifier="iOS"/> | ||||
|         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> | ||||
|         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/> | ||||
|         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | ||||
|     </dependencies> | ||||
|     <scenes> | ||||
|         <!--Flutter View Controller--> | ||||
| @@ -14,13 +16,14 @@ | ||||
|                         <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> | ||||
|                     </layoutGuides> | ||||
|                     <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> | ||||
|                         <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> | ||||
|                         <rect key="frame" x="0.0" y="0.0" width="393" height="852"/> | ||||
|                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | ||||
|                         <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> | ||||
|                         <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||||
|                     </view> | ||||
|                 </viewController> | ||||
|                 <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> | ||||
|             </objects> | ||||
|             <point key="canvasLocation" x="-26" y="-76"/> | ||||
|         </scene> | ||||
|     </scenes> | ||||
| </document> | ||||
|   | ||||
| @@ -2,16 +2,10 @@ | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| 	<key>CLIENT_ID</key> | ||||
| 	<string>961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com</string> | ||||
| 	<key>REVERSED_CLIENT_ID</key> | ||||
| 	<string>com.googleusercontent.apps.961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig</string> | ||||
| 	<key>PLIST_VERSION</key> | ||||
| 	<string>1</string> | ||||
| 	<key>AppGroupId</key> | ||||
| 	<string>$(CUSTOM_GROUP_ID)</string> | ||||
| 	<key>BUNDLE_ID</key> | ||||
| 	<string>dev.solsynth.solian</string> | ||||
| 	<key>ITSAppUsesNonExemptEncryption</key> | ||||
| 	<false/> | ||||
| 	<key>CADisableMinimumFrameDurationOnPhone</key> | ||||
| 	<true/> | ||||
| 	<key>CFBundleDevelopmentRegion</key> | ||||
| @@ -32,31 +26,46 @@ | ||||
| 	<string>$(FLUTTER_BUILD_NAME)</string> | ||||
| 	<key>CFBundleSignature</key> | ||||
| 	<string>????</string> | ||||
| 	<key>CFBundleURLTypes</key> | ||||
| 	<array> | ||||
| 		<dict> | ||||
| 			<key>CFBundleTypeRole</key> | ||||
| 			<string>Editor</string> | ||||
| 			<key>CFBundleURLSchemes</key> | ||||
| 			<array> | ||||
| 				<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||||
| 			</array> | ||||
| 		</dict> | ||||
| 	</array> | ||||
| 	<key>CFBundleVersion</key> | ||||
| 	<string>$(FLUTTER_BUILD_NUMBER)</string> | ||||
|     <key>CFBundleURLTypes</key> | ||||
|     <array> | ||||
|         <dict> | ||||
|             <key>CFBundleTypeRole</key> | ||||
|             <string>Editor</string> | ||||
|             <key>CFBundleURLSchemes</key> | ||||
|             <array> | ||||
|                 <string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||||
|             </array> | ||||
|         </dict> | ||||
|     </array> | ||||
| 	<key>CLIENT_ID</key> | ||||
| 	<string>961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com</string> | ||||
| 	<key>ITSAppUsesNonExemptEncryption</key> | ||||
| 	<false/> | ||||
| 	<key>LSRequiresIPhoneOS</key> | ||||
| 	<true/> | ||||
| 	<key>NSCalendarsUsageDescription</key> | ||||
| 	<string>Grant access to Calander help us to shows Solar Calander with your own events.</string> | ||||
| 	<key>NSCameraUsageDescription</key> | ||||
| 	<string>Grant access to Camera will allow Solian take photo or video for your post.</string> | ||||
| 	<key>NSFaceIDUsageDescription</key> | ||||
| 	<string>Allow the Solar Network verify your ownership of the logged in account and continue your action quickly.</string> | ||||
| 	<key>NSMicrophoneUsageDescription</key> | ||||
| 	<string>Grant access to Microphone will allow Solian record audio for your post.</string> | ||||
| 	<key>NSPhotoLibraryAddUsageDescription</key> | ||||
| 	<string>Grant access to Photo Library will allow Solian download photo to album for you.</string> | ||||
| 	<key>NSPhotoLibraryUsageDescription</key> | ||||
| 	<string>Grant access to Photo Library will allow Solian upload photo or video for your post.</string> | ||||
| 	<key>NSUserActivityTypes</key> | ||||
| 	<array> | ||||
| 		<string>INStartCallIntent</string> | ||||
| 		<string>INSendMessageIntent</string> | ||||
| 	</array> | ||||
| 	<key>PLIST_VERSION</key> | ||||
| 	<string>1</string> | ||||
| 	<key>REVERSED_CLIENT_ID</key> | ||||
| 	<string>com.googleusercontent.apps.961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig</string> | ||||
| 	<key>UIApplicationSupportsIndirectInputEvents</key> | ||||
| 	<true/> | ||||
| 	<key>UIBackgroundModes</key> | ||||
| @@ -74,25 +83,16 @@ | ||||
| 	<false/> | ||||
| 	<key>UISupportedInterfaceOrientations</key> | ||||
| 	<array> | ||||
| 		<string>UIInterfaceOrientationPortrait</string> | ||||
| 		<string>UIInterfaceOrientationLandscapeLeft</string> | ||||
| 		<string>UIInterfaceOrientationLandscapeRight</string> | ||||
| 		<string>UIInterfaceOrientationPortrait</string> | ||||
| 	</array> | ||||
| 	<key>UISupportedInterfaceOrientations~ipad</key> | ||||
| 	<array> | ||||
| 		<string>UIInterfaceOrientationPortrait</string> | ||||
| 		<string>UIInterfaceOrientationPortraitUpsideDown</string> | ||||
| 		<string>UIInterfaceOrientationLandscapeLeft</string> | ||||
| 		<string>UIInterfaceOrientationLandscapeRight</string> | ||||
| 	</array> | ||||
| 	<key>NSFaceIDUsageDescription</key> | ||||
| 	<string>Allow the Solar Network verify your ownership of the logged in account and continue your action quickly.</string> | ||||
| 	<key>AppGroupId</key> | ||||
| 	<string>$(CUSTOM_GROUP_ID)</string> | ||||
| 	<key>NSUserActivityTypes</key> | ||||
| 	<array> | ||||
| 		<string>INStartCallIntent</string> | ||||
| 		<string>INSendMessageIntent</string> | ||||
| 		<string>UIInterfaceOrientationPortrait</string> | ||||
| 		<string>UIInterfaceOrientationPortraitUpsideDown</string> | ||||
| 	</array> | ||||
| </dict> | ||||
| </plist> | ||||
|   | ||||
							
								
								
									
										23
									
								
								lib/models/abuse_report.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/models/abuse_report.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | ||||
|  | ||||
| part 'abuse_report.freezed.dart'; | ||||
| part 'abuse_report.g.dart'; | ||||
|  | ||||
| @freezed | ||||
| sealed class SnAbuseReport with _$SnAbuseReport { | ||||
|   const factory SnAbuseReport({ | ||||
|     required String id, | ||||
|     required String resourceIdentifier, | ||||
|     required int type, | ||||
|     required String reason, | ||||
|     required DateTime? resolvedAt, | ||||
|     required String? resolution, | ||||
|     required String accountId, | ||||
|     required DateTime createdAt, | ||||
|     required DateTime updatedAt, | ||||
|     required DateTime? deletedAt, | ||||
|   }) = _SnAbuseReport; | ||||
|  | ||||
|   factory SnAbuseReport.fromJson(Map<String, dynamic> json) => | ||||
|       _$SnAbuseReportFromJson(json); | ||||
| } | ||||
							
								
								
									
										175
									
								
								lib/models/abuse_report.freezed.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								lib/models/abuse_report.freezed.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| // dart format width=80 | ||||
| // coverage:ignore-file | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
| // ignore_for_file: type=lint | ||||
| // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark | ||||
|  | ||||
| part of 'abuse_report.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // FreezedGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| // dart format off | ||||
| T _$identity<T>(T value) => value; | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$SnAbuseReport { | ||||
|  | ||||
|  String get id; String get resourceIdentifier; int get type; String get reason; DateTime? get resolvedAt; String? get resolution; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; | ||||
| /// Create a copy of SnAbuseReport | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| $SnAbuseReportCopyWith<SnAbuseReport> get copyWith => _$SnAbuseReportCopyWithImpl<SnAbuseReport>(this as SnAbuseReport, _$identity); | ||||
|  | ||||
|   /// Serializes this SnAbuseReport to a JSON map. | ||||
|   Map<String, dynamic> toJson(); | ||||
|  | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAbuseReport&&(identical(other.id, id) || other.id == id)&&(identical(other.resourceIdentifier, resourceIdentifier) || other.resourceIdentifier == resourceIdentifier)&&(identical(other.type, type) || other.type == type)&&(identical(other.reason, reason) || other.reason == reason)&&(identical(other.resolvedAt, resolvedAt) || other.resolvedAt == resolvedAt)&&(identical(other.resolution, resolution) || other.resolution == resolution)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,resourceIdentifier,type,reason,resolvedAt,resolution,accountId,createdAt,updatedAt,deletedAt); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'SnAbuseReport(id: $id, resourceIdentifier: $resourceIdentifier, type: $type, reason: $reason, resolvedAt: $resolvedAt, resolution: $resolution, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class $SnAbuseReportCopyWith<$Res>  { | ||||
|   factory $SnAbuseReportCopyWith(SnAbuseReport value, $Res Function(SnAbuseReport) _then) = _$SnAbuseReportCopyWithImpl; | ||||
| @useResult | ||||
| $Res call({ | ||||
|  String id, String resourceIdentifier, int type, String reason, DateTime? resolvedAt, String? resolution, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class _$SnAbuseReportCopyWithImpl<$Res> | ||||
|     implements $SnAbuseReportCopyWith<$Res> { | ||||
|   _$SnAbuseReportCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final SnAbuseReport _self; | ||||
|   final $Res Function(SnAbuseReport) _then; | ||||
|  | ||||
| /// Create a copy of SnAbuseReport | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? resourceIdentifier = null,Object? type = null,Object? reason = null,Object? resolvedAt = freezed,Object? resolution = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
|   return _then(_self.copyWith( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,resourceIdentifier: null == resourceIdentifier ? _self.resourceIdentifier : resourceIdentifier // ignore: cast_nullable_to_non_nullable | ||||
| as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable | ||||
| as int,reason: null == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable | ||||
| as String,resolvedAt: freezed == resolvedAt ? _self.resolvedAt : resolvedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?,resolution: freezed == resolution ? _self.resolution : resolution // ignore: cast_nullable_to_non_nullable | ||||
| as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable | ||||
| as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?, | ||||
|   )); | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
|  | ||||
| class _SnAbuseReport implements SnAbuseReport { | ||||
|   const _SnAbuseReport({required this.id, required this.resourceIdentifier, required this.type, required this.reason, required this.resolvedAt, required this.resolution, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}); | ||||
|   factory _SnAbuseReport.fromJson(Map<String, dynamic> json) => _$SnAbuseReportFromJson(json); | ||||
|  | ||||
| @override final  String id; | ||||
| @override final  String resourceIdentifier; | ||||
| @override final  int type; | ||||
| @override final  String reason; | ||||
| @override final  DateTime? resolvedAt; | ||||
| @override final  String? resolution; | ||||
| @override final  String accountId; | ||||
| @override final  DateTime createdAt; | ||||
| @override final  DateTime updatedAt; | ||||
| @override final  DateTime? deletedAt; | ||||
|  | ||||
| /// Create a copy of SnAbuseReport | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @pragma('vm:prefer-inline') | ||||
| _$SnAbuseReportCopyWith<_SnAbuseReport> get copyWith => __$SnAbuseReportCopyWithImpl<_SnAbuseReport>(this, _$identity); | ||||
|  | ||||
| @override | ||||
| Map<String, dynamic> toJson() { | ||||
|   return _$SnAbuseReportToJson(this, ); | ||||
| } | ||||
|  | ||||
| @override | ||||
| bool operator ==(Object other) { | ||||
|   return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAbuseReport&&(identical(other.id, id) || other.id == id)&&(identical(other.resourceIdentifier, resourceIdentifier) || other.resourceIdentifier == resourceIdentifier)&&(identical(other.type, type) || other.type == type)&&(identical(other.reason, reason) || other.reason == reason)&&(identical(other.resolvedAt, resolvedAt) || other.resolvedAt == resolvedAt)&&(identical(other.resolution, resolution) || other.resolution == resolution)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); | ||||
| } | ||||
|  | ||||
| @JsonKey(includeFromJson: false, includeToJson: false) | ||||
| @override | ||||
| int get hashCode => Object.hash(runtimeType,id,resourceIdentifier,type,reason,resolvedAt,resolution,accountId,createdAt,updatedAt,deletedAt); | ||||
|  | ||||
| @override | ||||
| String toString() { | ||||
|   return 'SnAbuseReport(id: $id, resourceIdentifier: $resourceIdentifier, type: $type, reason: $reason, resolvedAt: $resolvedAt, resolution: $resolution, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract mixin class _$SnAbuseReportCopyWith<$Res> implements $SnAbuseReportCopyWith<$Res> { | ||||
|   factory _$SnAbuseReportCopyWith(_SnAbuseReport value, $Res Function(_SnAbuseReport) _then) = __$SnAbuseReportCopyWithImpl; | ||||
| @override @useResult | ||||
| $Res call({ | ||||
|  String id, String resourceIdentifier, int type, String reason, DateTime? resolvedAt, String? resolution, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| /// @nodoc | ||||
| class __$SnAbuseReportCopyWithImpl<$Res> | ||||
|     implements _$SnAbuseReportCopyWith<$Res> { | ||||
|   __$SnAbuseReportCopyWithImpl(this._self, this._then); | ||||
|  | ||||
|   final _SnAbuseReport _self; | ||||
|   final $Res Function(_SnAbuseReport) _then; | ||||
|  | ||||
| /// Create a copy of SnAbuseReport | ||||
| /// with the given fields replaced by the non-null parameter values. | ||||
| @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? resourceIdentifier = null,Object? type = null,Object? reason = null,Object? resolvedAt = freezed,Object? resolution = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { | ||||
|   return _then(_SnAbuseReport( | ||||
| id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable | ||||
| as String,resourceIdentifier: null == resourceIdentifier ? _self.resourceIdentifier : resourceIdentifier // ignore: cast_nullable_to_non_nullable | ||||
| as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable | ||||
| as int,reason: null == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable | ||||
| as String,resolvedAt: freezed == resolvedAt ? _self.resolvedAt : resolvedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?,resolution: freezed == resolution ? _self.resolution : resolution // ignore: cast_nullable_to_non_nullable | ||||
| as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable | ||||
| as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable | ||||
| as DateTime?, | ||||
|   )); | ||||
| } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| // dart format on | ||||
							
								
								
									
										41
									
								
								lib/models/abuse_report.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								lib/models/abuse_report.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
|  | ||||
| part of 'abuse_report.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // JsonSerializableGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| _SnAbuseReport _$SnAbuseReportFromJson(Map<String, dynamic> json) => | ||||
|     _SnAbuseReport( | ||||
|       id: json['id'] as String, | ||||
|       resourceIdentifier: json['resource_identifier'] as String, | ||||
|       type: (json['type'] as num).toInt(), | ||||
|       reason: json['reason'] as String, | ||||
|       resolvedAt: | ||||
|           json['resolved_at'] == null | ||||
|               ? null | ||||
|               : DateTime.parse(json['resolved_at'] as String), | ||||
|       resolution: json['resolution'] as String?, | ||||
|       accountId: json['account_id'] as String, | ||||
|       createdAt: DateTime.parse(json['created_at'] as String), | ||||
|       updatedAt: DateTime.parse(json['updated_at'] as String), | ||||
|       deletedAt: | ||||
|           json['deleted_at'] == null | ||||
|               ? null | ||||
|               : DateTime.parse(json['deleted_at'] as String), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$SnAbuseReportToJson(_SnAbuseReport instance) => | ||||
|     <String, dynamic>{ | ||||
|       'id': instance.id, | ||||
|       'resource_identifier': instance.resourceIdentifier, | ||||
|       'type': instance.type, | ||||
|       'reason': instance.reason, | ||||
|       'resolved_at': instance.resolvedAt?.toIso8601String(), | ||||
|       'resolution': instance.resolution, | ||||
|       'account_id': instance.accountId, | ||||
|       'created_at': instance.createdAt.toIso8601String(), | ||||
|       'updated_at': instance.updatedAt.toIso8601String(), | ||||
|       'deleted_at': instance.deletedAt?.toIso8601String(), | ||||
|     }; | ||||
							
								
								
									
										38
									
								
								lib/models/abuse_report_type.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								lib/models/abuse_report_type.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| enum AbuseReportType { | ||||
|   copyright(0), | ||||
|   harassment(1), | ||||
|   impersonation(2), | ||||
|   offensiveContent(3), | ||||
|   spam(4), | ||||
|   privacyViolation(5), | ||||
|   illegalContent(6), | ||||
|   other(7); | ||||
|  | ||||
|   const AbuseReportType(this.value); | ||||
|   final int value; | ||||
|  | ||||
|   static AbuseReportType fromValue(int value) { | ||||
|     return values.firstWhere((e) => e.value == value); | ||||
|   } | ||||
|  | ||||
|   String get displayName { | ||||
|     switch (this) { | ||||
|       case AbuseReportType.copyright: | ||||
|         return 'Copyright'; | ||||
|       case AbuseReportType.harassment: | ||||
|         return 'Harassment'; | ||||
|       case AbuseReportType.impersonation: | ||||
|         return 'Impersonation'; | ||||
|       case AbuseReportType.offensiveContent: | ||||
|         return 'Offensive Content'; | ||||
|       case AbuseReportType.spam: | ||||
|         return 'Spam'; | ||||
|       case AbuseReportType.privacyViolation: | ||||
|         return 'Privacy Violation'; | ||||
|       case AbuseReportType.illegalContent: | ||||
|         return 'Illegal Content'; | ||||
|       case AbuseReportType.other: | ||||
|         return 'Other'; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -65,12 +65,13 @@ final apiClientProvider = Provider<Dio>((ref) { | ||||
|   final serverUrl = ref.watch(serverUrlProvider); | ||||
|   final dio = Dio( | ||||
|     BaseOptions( | ||||
|       baseUrl: serverUrl, | ||||
|       baseUrl: '$serverUrl/api', | ||||
|       connectTimeout: const Duration(seconds: 10), | ||||
|       receiveTimeout: const Duration(seconds: 10), | ||||
|       headers: { | ||||
|         'Accept': 'application/json', | ||||
|         'Content-Type': 'application/json', | ||||
|         'X-Client': 'Solian', | ||||
|       }, | ||||
|     ), | ||||
|   ); | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import 'package:island/screens/posts/post_search.dart'; | ||||
| import 'package:island/widgets/app_wrapper.dart'; | ||||
| import 'package:island/screens/tabs.dart'; | ||||
| import 'package:island/screens/explore.dart'; | ||||
| import 'package:island/screens/article_detail_screen.dart'; | ||||
| import 'package:island/screens/discovery/article_detail.dart'; | ||||
| import 'package:island/screens/account.dart'; | ||||
| import 'package:island/screens/notification.dart'; | ||||
| import 'package:island/screens/wallet.dart'; | ||||
| @@ -41,6 +41,8 @@ import 'package:island/screens/realm/realms.dart'; | ||||
| import 'package:island/screens/realm/realm_detail.dart'; | ||||
| import 'package:island/screens/account/event_calendar.dart'; | ||||
| import 'package:island/screens/discovery/realms.dart'; | ||||
| import 'package:island/screens/reports/report_detail.dart'; | ||||
| import 'package:island/screens/reports/report_list.dart'; | ||||
|  | ||||
| // Shell route keys for nested navigation | ||||
| final rootNavigatorKey = GlobalKey<NavigatorState>(); | ||||
| @@ -258,6 +260,19 @@ final routerProvider = Provider<GoRouter>((ref) { | ||||
|             builder: (context, state) => const AboutScreen(), | ||||
|           ), | ||||
|  | ||||
|           GoRoute( | ||||
|             path: '/safety/reports/me', | ||||
|             builder: (context, state) => const AbuseReportListScreen(), | ||||
|           ), | ||||
|  | ||||
|           GoRoute( | ||||
|             path: '/safety/reports/me/:id', | ||||
|             builder: (context, state) { | ||||
|               final id = state.pathParameters['id']!; | ||||
|               return AbuseReportDetailScreen(reportId: id); | ||||
|             }, | ||||
|           ), | ||||
|  | ||||
|           // Main tabs with TabsScreen shell | ||||
|           ShellRoute( | ||||
|             navigatorKey: _tabsShellKey, | ||||
| @@ -399,7 +414,7 @@ final routerProvider = Provider<GoRouter>((ref) { | ||||
|                     builder: (context, state) => const LevelingScreen(), | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     path: '/account/settings', | ||||
|                     path: '/account/me/settings', | ||||
|                     builder: (context, state) => const AccountSettingsScreen(), | ||||
|                   ), | ||||
|                 ], | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import 'package:island/pods/network.dart'; | ||||
| import 'package:island/services/notify.dart'; | ||||
| import 'package:island/services/udid.native.dart'; | ||||
| import 'package:island/widgets/alert.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:package_info_plus/package_info_plus.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| @@ -90,7 +91,7 @@ class _AboutScreenState extends ConsumerState<AboutScreen> { | ||||
|   Widget build(BuildContext context) { | ||||
|     final theme = Theme.of(context); | ||||
|  | ||||
|     return Scaffold( | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar(title: Text('about'.tr()), elevation: 0), | ||||
|       body: | ||||
|           _isLoading | ||||
|   | ||||
| @@ -222,9 +222,17 @@ class AccountScreen extends HookConsumerWidget { | ||||
|               contentPadding: EdgeInsets.symmetric(horizontal: 24), | ||||
|               title: Text('relationships').tr(), | ||||
|               onTap: () { | ||||
|                 context.push('/account/relationship'); | ||||
|                 context.push('/account/relationships'); | ||||
|               }, | ||||
|             ), | ||||
|             ListTile( | ||||
|               minTileHeight: 48, | ||||
|               title: Text('abuseReports').tr(), | ||||
|               contentPadding: const EdgeInsets.only(left: 24, right: 17), | ||||
|               leading: const Icon(Symbols.gavel), | ||||
|               trailing: const Icon(Symbols.chevron_right), | ||||
|               onTap: () => context.push('/safety/reports/me'), | ||||
|             ), | ||||
|             const Divider(height: 1).padding(vertical: 8), | ||||
|             ListTile( | ||||
|               minTileHeight: 48, | ||||
| @@ -328,7 +336,7 @@ class _UnauthorizedAccountScreen extends StatelessWidget { | ||||
|                   child: Card( | ||||
|                     child: InkWell( | ||||
|                       onTap: () { | ||||
|                         context.push('/auth/create'); | ||||
|                         context.push('/auth/create-account'); | ||||
|                       }, | ||||
|                       child: Padding( | ||||
|                         padding: const EdgeInsets.all(16), | ||||
|   | ||||
| @@ -22,6 +22,7 @@ import 'package:island/widgets/account/status.dart'; | ||||
| import 'package:island/widgets/alert.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/content/cloud_files.dart'; | ||||
| import 'package:island/widgets/safety/abuse_report_helper.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:palette_generator/palette_generator.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| @@ -143,6 +144,23 @@ class AccountProfileScreen extends HookConsumerWidget { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     Future<void> blockAction() async { | ||||
|       showLoadingModal(context); | ||||
|       try { | ||||
|         final client = ref.watch(apiClientProvider); | ||||
|         if (accountRelationship.value == null) { | ||||
|           await client.post('/relationships/${account.value!.id}/block'); | ||||
|         } else { | ||||
|           await client.delete('/relationships/${account.value!.id}/block'); | ||||
|         } | ||||
|         ref.invalidate(accountRelationshipProvider(name)); | ||||
|       } catch (err) { | ||||
|         showErrorAlert(err); | ||||
|       } finally { | ||||
|         if (context.mounted) hideLoadingModal(context); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     Future<void> directMessageAction() async { | ||||
|       if (!account.hasValue) return; | ||||
|       if (accountChat.value != null) { | ||||
| @@ -396,49 +414,108 @@ class AccountProfileScreen extends HookConsumerWidget { | ||||
|                     child: Row( | ||||
|                       spacing: 8, | ||||
|                       children: [ | ||||
|                         Expanded( | ||||
|                           child: FilledButton.icon( | ||||
|                             style: ButtonStyle( | ||||
|                               backgroundColor: WidgetStatePropertyAll( | ||||
|                                 accountRelationship.value == null | ||||
|                                     ? null | ||||
|                                     : Theme.of(context).colorScheme.secondary, | ||||
|                               ), | ||||
|                               foregroundColor: WidgetStatePropertyAll( | ||||
|                                 accountRelationship.value == null | ||||
|                                     ? null | ||||
|                                     : Theme.of(context).colorScheme.onSecondary, | ||||
|                               ), | ||||
|                             ), | ||||
|                             onPressed: relationshipAction, | ||||
|                             label: | ||||
|                                 Text( | ||||
|                         if (accountRelationship.value == null || | ||||
|                             accountRelationship.value!.status > -100) | ||||
|                           Expanded( | ||||
|                             child: FilledButton.icon( | ||||
|                               style: ButtonStyle( | ||||
|                                 backgroundColor: WidgetStatePropertyAll( | ||||
|                                   accountRelationship.value == null | ||||
|                                       ? 'addFriendShort' | ||||
|                                       : 'added', | ||||
|                                 ).tr(), | ||||
|                             icon: | ||||
|                                 accountRelationship.value == null | ||||
|                                     ? const Icon(Symbols.person_add) | ||||
|                                     : const Icon(Symbols.person_check), | ||||
|                                       ? null | ||||
|                                       : Theme.of(context).colorScheme.secondary, | ||||
|                                 ), | ||||
|                                 foregroundColor: WidgetStatePropertyAll( | ||||
|                                   accountRelationship.value == null | ||||
|                                       ? null | ||||
|                                       : Theme.of( | ||||
|                                         context, | ||||
|                                       ).colorScheme.onSecondary, | ||||
|                                 ), | ||||
|                               ), | ||||
|                               onPressed: relationshipAction, | ||||
|                               label: | ||||
|                                   Text( | ||||
|                                     accountRelationship.value == null | ||||
|                                         ? 'addFriendShort' | ||||
|                                         : 'added', | ||||
|                                   ).tr(), | ||||
|                               icon: | ||||
|                                   accountRelationship.value == null | ||||
|                                       ? const Icon(Symbols.person_add) | ||||
|                                       : const Icon(Symbols.person_check), | ||||
|                             ), | ||||
|                           ), | ||||
|                         ), | ||||
|                         Expanded( | ||||
|                           child: FilledButton.icon( | ||||
|                             onPressed: directMessageAction, | ||||
|                             icon: const Icon(Symbols.message), | ||||
|                             label: | ||||
|                                 Text( | ||||
|                                   accountChat.value == null | ||||
|                                       ? 'createDirectMessage' | ||||
|                                       : 'gotoDirectMessage', | ||||
|                                   maxLines: 1, | ||||
|                                 ).tr(), | ||||
|                         if (accountRelationship.value == null || | ||||
|                             accountRelationship.value!.status <= -100) | ||||
|                           Expanded( | ||||
|                             child: FilledButton.icon( | ||||
|                               style: ButtonStyle( | ||||
|                                 backgroundColor: WidgetStatePropertyAll( | ||||
|                                   accountRelationship.value == null | ||||
|                                       ? null | ||||
|                                       : Theme.of(context).colorScheme.secondary, | ||||
|                                 ), | ||||
|                                 foregroundColor: WidgetStatePropertyAll( | ||||
|                                   accountRelationship.value == null | ||||
|                                       ? null | ||||
|                                       : Theme.of( | ||||
|                                         context, | ||||
|                                       ).colorScheme.onSecondary, | ||||
|                                 ), | ||||
|                               ), | ||||
|                               onPressed: blockAction, | ||||
|                               label: | ||||
|                                   Text( | ||||
|                                     accountRelationship.value == null | ||||
|                                         ? 'blockUser' | ||||
|                                         : 'unblockUser', | ||||
|                                   ).tr(), | ||||
|                               icon: | ||||
|                                   accountRelationship.value == null | ||||
|                                       ? const Icon(Symbols.block) | ||||
|                                       : const Icon(Symbols.person_cancel), | ||||
|                             ), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ).padding(horizontal: 16), | ||||
|                   ), | ||||
|                 SliverToBoxAdapter( | ||||
|                   child: Row( | ||||
|                     spacing: 8, | ||||
|                     children: [ | ||||
|                       Expanded( | ||||
|                         child: FilledButton.icon( | ||||
|                           onPressed: directMessageAction, | ||||
|                           icon: const Icon(Symbols.message), | ||||
|                           label: | ||||
|                               Text( | ||||
|                                 accountChat.value == null | ||||
|                                     ? 'createDirectMessage' | ||||
|                                     : 'gotoDirectMessage', | ||||
|                                 maxLines: 1, | ||||
|                               ).tr(), | ||||
|                         ), | ||||
|                       ), | ||||
|                       IconButton.filled( | ||||
|                         onPressed: () { | ||||
|                           showAbuseReportSheet( | ||||
|                             context, | ||||
|                             resourceIdentifier: 'account/${data.id}', | ||||
|                           ); | ||||
|                         }, | ||||
|                         icon: Icon( | ||||
|                           Symbols.flag, | ||||
|                           color: Theme.of(context).colorScheme.onError, | ||||
|                         ), | ||||
|                         style: ButtonStyle( | ||||
|                           backgroundColor: WidgetStatePropertyAll( | ||||
|                             Theme.of(context).colorScheme.error, | ||||
|                           ), | ||||
|                         ), | ||||
|                       ), | ||||
|                     ], | ||||
|                   ).padding(horizontal: 16, top: 4), | ||||
|                 ), | ||||
|                 SliverToBoxAdapter( | ||||
|                   child: const Divider(height: 1).padding(top: 12), | ||||
|                 ), | ||||
|   | ||||
| @@ -395,7 +395,7 @@ class _AccountAppbarForcegroundColorProviderElement | ||||
|   String get uname => (origin as AccountAppbarForcegroundColorProvider).uname; | ||||
| } | ||||
|  | ||||
| String _$accountDirectChatHash() => r'60d0015fc2a3c8fc2190bb41d6818cf3027d9d0a'; | ||||
| String _$accountDirectChatHash() => r'3d28c8ba8079159f724fe3cd47bbe00db55cedcc'; | ||||
|  | ||||
| /// See also [accountDirectChat]. | ||||
| @ProviderFor(accountDirectChat) | ||||
| @@ -517,7 +517,7 @@ class _AccountDirectChatProviderElement | ||||
| } | ||||
|  | ||||
| String _$accountRelationshipHash() => | ||||
|     r'cb7d0d3f8cd4f23ad9d2d529872c540dac483d4f'; | ||||
|     r'0be2420e1f6a65b8dcead9617191471924aaf232'; | ||||
|  | ||||
| /// See also [accountRelationship]. | ||||
| @ProviderFor(accountRelationship) | ||||
|   | ||||
| @@ -28,7 +28,7 @@ class StickersScreen extends HookConsumerWidget { | ||||
|         actions: [ | ||||
|           IconButton( | ||||
|             onPressed: () { | ||||
|               context.push('/creators/stickers/new?pubName=pubName').then(( | ||||
|               context.push('/creators/stickers/new?pubName=$pubName').then(( | ||||
|                 value, | ||||
|               ) { | ||||
|                 if (value != null) { | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/webfeed.dart'; | ||||
| import 'package:island/widgets/alert.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| @@ -183,7 +184,7 @@ class WebFeedEditScreen extends HookConsumerWidget { | ||||
|       } | ||||
|     }, [pubName, feedId, ref, context]); | ||||
|  | ||||
|     return Scaffold( | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar( | ||||
|         title: Text(hasFeedId ? 'Edit Web Feed' : 'New Web Feed'), | ||||
|         actions: [ | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/web_article_card.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; | ||||
| @@ -124,7 +125,7 @@ class ArticlesScreen extends ConsumerWidget { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     return Scaffold( | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar(title: Text(title ?? 'Articles')), | ||||
|       body: Center( | ||||
|         child: ConstrainedBox( | ||||
|   | ||||
| @@ -338,7 +338,7 @@ class _ActivityListView extends HookConsumerWidget { | ||||
|                             bottom: 16, | ||||
|                           ) | ||||
|                           : null, | ||||
|                   onRefresh: (_) { | ||||
|                   onRefresh: () { | ||||
|                     activitiesNotifier.forceRefresh(); | ||||
|                   }, | ||||
|                   onUpdate: (post) { | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/post.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/post/post_item.dart'; | ||||
| import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; | ||||
|  | ||||
| @@ -107,7 +108,7 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar( | ||||
|         title: TextField( | ||||
|           controller: _searchController, | ||||
|   | ||||
| @@ -187,7 +187,7 @@ class PublisherProfileScreen extends HookConsumerWidget { | ||||
|                         ), | ||||
|                         onTap: () { | ||||
|                           Navigator.pop(context, true); | ||||
|                           context.push('/account/${data.name}'); | ||||
|                           context.push('/account/${data.account?.name}'); | ||||
|                         }, | ||||
|                       ), | ||||
|                       Expanded( | ||||
|   | ||||
| @@ -77,6 +77,7 @@ class RealmDetailScreen extends HookConsumerWidget { | ||||
|     ); | ||||
|  | ||||
|     return AppScaffold( | ||||
|       noBackground: false, | ||||
|       body: realmState.when( | ||||
|         loading: () => const Center(child: CircularProgressIndicator()), | ||||
|         error: (error, _) => Center(child: Text('Error: $error')), | ||||
|   | ||||
							
								
								
									
										105
									
								
								lib/screens/reports/report_detail.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								lib/screens/reports/report_detail.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/abuse_report.dart'; | ||||
| import 'package:island/models/abuse_report_type.dart'; | ||||
| import 'package:island/services/abuse_report_service.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| class AbuseReportDetailScreen extends ConsumerStatefulWidget { | ||||
|   final String reportId; | ||||
|  | ||||
|   const AbuseReportDetailScreen({super.key, required this.reportId}); | ||||
|  | ||||
|   @override | ||||
|   ConsumerState<AbuseReportDetailScreen> createState() => | ||||
|       _AbuseReportDetailScreenState(); | ||||
| } | ||||
|  | ||||
| class _AbuseReportDetailScreenState | ||||
|     extends ConsumerState<AbuseReportDetailScreen> { | ||||
|   Future<SnAbuseReport>? _reportFuture; | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     _reportFuture = ref | ||||
|         .read(abuseReportServiceProvider) | ||||
|         .getReport(widget.reportId); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar(title: const Text('Abuse Report Details')), | ||||
|       body: FutureBuilder<SnAbuseReport>( | ||||
|         future: _reportFuture, | ||||
|         builder: (context, snapshot) { | ||||
|           if (snapshot.connectionState == ConnectionState.waiting) { | ||||
|             return const Center(child: CircularProgressIndicator()); | ||||
|           } else if (snapshot.hasError) { | ||||
|             return Center(child: Text('Error: ${snapshot.error}')); | ||||
|           } else if (snapshot.hasData) { | ||||
|             final report = snapshot.data!; | ||||
|             return Padding( | ||||
|               padding: const EdgeInsets.all(16.0), | ||||
|               child: Column( | ||||
|                 crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                 children: [ | ||||
|                   _buildDetailRow(context, 'Report ID', report.id), | ||||
|                   _buildDetailRow( | ||||
|                     context, | ||||
|                     'Resource Identifier', | ||||
|                     report.resourceIdentifier, | ||||
|                   ), | ||||
|                   _buildDetailRow( | ||||
|                     context, | ||||
|                     'Type', | ||||
|                     AbuseReportType.fromValue(report.type).displayName, | ||||
|                   ), | ||||
|                   _buildDetailRow(context, 'Reason', report.reason), | ||||
|                   _buildDetailRow( | ||||
|                     context, | ||||
|                     'Resolved At', | ||||
|                     report.resolvedAt?.toString() ?? 'N/A', | ||||
|                   ), | ||||
|                   _buildDetailRow( | ||||
|                     context, | ||||
|                     'Resolution', | ||||
|                     report.resolution ?? 'N/A', | ||||
|                   ), | ||||
|                   _buildDetailRow(context, 'Account ID', report.accountId), | ||||
|                   _buildDetailRow( | ||||
|                     context, | ||||
|                     'Created At', | ||||
|                     report.createdAt.toString(), | ||||
|                   ), | ||||
|                   _buildDetailRow( | ||||
|                     context, | ||||
|                     'Updated At', | ||||
|                     report.updatedAt.toString(), | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ); | ||||
|           } else { | ||||
|             return const Center(child: Text('No data')); | ||||
|           } | ||||
|         }, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildDetailRow(BuildContext context, String label, String value) { | ||||
|     return Padding( | ||||
|       padding: const EdgeInsets.symmetric(vertical: 8.0), | ||||
|       child: Column( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           Text(label, style: Theme.of(context).textTheme.titleMedium).bold(), | ||||
|           Text(value, style: Theme.of(context).textTheme.bodyLarge), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										153
									
								
								lib/screens/reports/report_list.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								lib/screens/reports/report_list.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:go_router/go_router.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/abuse_report.dart'; | ||||
| import 'package:island/models/abuse_report_type.dart'; | ||||
| import 'package:island/services/abuse_report_service.dart'; | ||||
| import 'package:island/services/time.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/safety/abuse_report_helper.dart'; | ||||
|  | ||||
| class AbuseReportListScreen extends ConsumerStatefulWidget { | ||||
|   const AbuseReportListScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   ConsumerState<AbuseReportListScreen> createState() => | ||||
|       _AbuseReportListScreenState(); | ||||
| } | ||||
|  | ||||
| class _AbuseReportListScreenState extends ConsumerState<AbuseReportListScreen> { | ||||
|   Future<List<SnAbuseReport>>? _reportsFuture; | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     _reportsFuture = ref.read(abuseReportServiceProvider).getReports(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar(title: Text('abuseReports').tr()), | ||||
|       floatingActionButton: FloatingActionButton( | ||||
|         child: const Icon(Icons.add), | ||||
|         onPressed: () { | ||||
|           showAbuseReportSheet(context, resourceIdentifier: 'unidentified'); | ||||
|         }, | ||||
|       ), | ||||
|       body: FutureBuilder<List<SnAbuseReport>>( | ||||
|         future: _reportsFuture, | ||||
|         builder: (context, snapshot) { | ||||
|           if (snapshot.connectionState == ConnectionState.waiting) { | ||||
|             return const Center(child: CircularProgressIndicator()); | ||||
|           } else if (snapshot.hasError) { | ||||
|             return Center(child: Text('Error: ${snapshot.error}')); | ||||
|           } else if (snapshot.hasData) { | ||||
|             final reports = snapshot.data!; | ||||
|             return ListView.builder( | ||||
|               padding: EdgeInsets.zero, | ||||
|               itemCount: reports.length, | ||||
|               itemBuilder: (context, index) { | ||||
|                 final report = reports[index]; | ||||
|                 return Card( | ||||
|                   elevation: 2, | ||||
|                   margin: const EdgeInsets.symmetric( | ||||
|                     horizontal: 16, | ||||
|                     vertical: 8, | ||||
|                   ), | ||||
|                   child: InkWell( | ||||
|                     onTap: () { | ||||
|                       context.push('/safety/reports/me/${report.id}'); | ||||
|                     }, | ||||
|                     child: Padding( | ||||
|                       padding: const EdgeInsets.all(16.0), | ||||
|                       child: Column( | ||||
|                         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                         children: [ | ||||
|                           Text( | ||||
|                             report.reason, | ||||
|                             style: Theme.of(context).textTheme.titleMedium, | ||||
|                           ), | ||||
|                           const SizedBox(height: 8), | ||||
|                           Row( | ||||
|                             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                             children: [ | ||||
|                               Text( | ||||
|                                 'ID', | ||||
|                                 style: Theme.of(context).textTheme.bodySmall, | ||||
|                               ), | ||||
|                               Text( | ||||
|                                 report.id, | ||||
|                                 style: Theme.of(context).textTheme.bodyMedium, | ||||
|                               ), | ||||
|                             ], | ||||
|                           ), | ||||
|                           const SizedBox(height: 4), | ||||
|                           Row( | ||||
|                             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                             children: [ | ||||
|                               Text( | ||||
|                                 'Type', | ||||
|                                 style: Theme.of(context).textTheme.bodySmall, | ||||
|                               ), | ||||
|                               Text( | ||||
|                                 AbuseReportType.fromValue( | ||||
|                                   report.type, | ||||
|                                 ).displayName, | ||||
|                                 style: Theme.of(context).textTheme.bodyMedium, | ||||
|                               ), | ||||
|                             ], | ||||
|                           ), | ||||
|                           const SizedBox(height: 4), | ||||
|                           Row( | ||||
|                             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                             children: [ | ||||
|                               Text( | ||||
|                                 'Created at', | ||||
|                                 style: Theme.of(context).textTheme.bodySmall, | ||||
|                               ), | ||||
|                               Text( | ||||
|                                 '${report.createdAt.formatRelative(context)} · ${report.createdAt.formatSystem()}', | ||||
|                                 style: Theme.of(context).textTheme.bodyMedium, | ||||
|                               ), | ||||
|                             ], | ||||
|                           ), | ||||
|                           const SizedBox(height: 4), | ||||
|                           Row( | ||||
|                             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                             children: [ | ||||
|                               Text( | ||||
|                                 'Status', | ||||
|                                 style: Theme.of(context).textTheme.bodySmall, | ||||
|                               ), | ||||
|                               Text( | ||||
|                                 report.resolvedAt != null | ||||
|                                     ? 'Resolved' | ||||
|                                     : 'Unresolved', | ||||
|                                 style: Theme.of( | ||||
|                                   context, | ||||
|                                 ).textTheme.bodyMedium?.copyWith( | ||||
|                                   color: | ||||
|                                       report.resolvedAt != null | ||||
|                                           ? Colors.green | ||||
|                                           : Colors.orange, | ||||
|                                 ), | ||||
|                               ), | ||||
|                             ], | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ); | ||||
|               }, | ||||
|             ); | ||||
|           } else { | ||||
|             return const Center(child: Text('No data')); | ||||
|           } | ||||
|         }, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										25
									
								
								lib/services/abuse_report_service.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/services/abuse_report_service.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/abuse_report.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
|  | ||||
| final abuseReportServiceProvider = Provider<AbuseReportService>((ref) { | ||||
|   return AbuseReportService(ref); | ||||
| }); | ||||
|  | ||||
| class AbuseReportService { | ||||
|   final Ref ref; | ||||
|   AbuseReportService(this.ref); | ||||
|  | ||||
|   Future<SnAbuseReport> getReport(String id) async { | ||||
|     final response = | ||||
|         await ref.read(apiClientProvider).get('/safety/reports/me/$id'); | ||||
|     return SnAbuseReport.fromJson(response.data); | ||||
|   } | ||||
|  | ||||
|   Future<List<SnAbuseReport>> getReports() async { | ||||
|     final response = await ref.read(apiClientProvider).get('/safety/reports/me'); | ||||
|     return (response.data as List) | ||||
|         .map((json) => SnAbuseReport.fromJson(json)) | ||||
|         .toList(); | ||||
|   } | ||||
| } | ||||
| @@ -68,7 +68,6 @@ Future<void> subscribePushNotification( | ||||
|   bool detailedErrors = false, | ||||
| }) async { | ||||
|   await FirebaseMessaging.instance.requestPermission( | ||||
|     provisional: true, | ||||
|     alert: true, | ||||
|     badge: true, | ||||
|     sound: true, | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import 'dart:convert'; | ||||
| import 'package:flutter/widgets.dart'; | ||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | ||||
| import 'package:island/pods/config.dart'; | ||||
| import 'package:island/widgets/tour/techincal_review_intro.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
|  | ||||
| part 'tour.g.dart'; | ||||
| @@ -12,7 +11,7 @@ part 'tour.freezed.dart'; | ||||
| const kAppTourStatusKey = "app_tour_statuses"; | ||||
|  | ||||
| const List<Tour> kAllTours = [ | ||||
|   Tour(id: 'technical_review_intro', isStartup: true), | ||||
|   // Tour(id: 'technical_review_intro', isStartup: true), | ||||
| ]; | ||||
|  | ||||
| @freezed | ||||
| @@ -22,7 +21,7 @@ sealed class Tour with _$Tour { | ||||
|   const factory Tour({required String id, required bool isStartup}) = _Tour; | ||||
|  | ||||
|   Widget get widget => switch (id) { | ||||
|     'technical_review_intro' => const TechicalReviewIntroWidget(), | ||||
|     // 'technical_review_intro' => const TechicalReviewIntroWidget(), | ||||
|     _ => throw UnimplementedError(), | ||||
|   }; | ||||
| } | ||||
|   | ||||
							
								
								
									
										22
									
								
								lib/utils/abuse_report_utils.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lib/utils/abuse_report_utils.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| String getAbuseReportTypeString(int type) { | ||||
|   switch (type) { | ||||
|     case 0: | ||||
|       return 'Copyright'; | ||||
|     case 1: | ||||
|       return 'Harassment'; | ||||
|     case 2: | ||||
|       return 'Impersonation'; | ||||
|     case 3: | ||||
|       return 'Offensive Content'; | ||||
|     case 4: | ||||
|       return 'Spam'; | ||||
|     case 5: | ||||
|       return 'Privacy Violation'; | ||||
|     case 6: | ||||
|       return 'Illegal Content'; | ||||
|     case 7: | ||||
|       return 'Other'; | ||||
|     default: | ||||
|       return 'Unknown'; | ||||
|   } | ||||
| } | ||||
| @@ -44,7 +44,7 @@ class AudioCallButton extends HookConsumerWidget { | ||||
|       try { | ||||
|         await apiClient.post('/chat/realtime/$roomId'); | ||||
|         if (context.mounted) { | ||||
|           context.push('/chat/call/$roomId'); | ||||
|           context.push('/chat/$roomId/call'); | ||||
|         } | ||||
|       } catch (e) { | ||||
|         showErrorAlert(e); | ||||
|   | ||||
| @@ -360,7 +360,7 @@ class CallOverlayBar extends HookConsumerWidget { | ||||
|         ).padding(all: 16), | ||||
|       ), | ||||
|       onTap: () { | ||||
|         context.push('/chat/call/${callNotifier.roomId!}'); | ||||
|         context.push('/chat/${callNotifier.roomId!}/call'); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -29,9 +29,12 @@ class AttachmentPreview extends StatelessWidget { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     var ratio = | ||||
|         (item.isOnCloud ? (item.data.fileMeta?['ratio'] ?? 1) : 1).toDouble(); | ||||
|     if (ratio == 0) ratio = 1.0; | ||||
|  | ||||
|     return AspectRatio( | ||||
|       aspectRatio: | ||||
|           (item.isOnCloud ? (item.data.fileMeta?['ratio'] ?? 1) : 1).toDouble(), | ||||
|       aspectRatio: ratio, | ||||
|       child: ClipRRect( | ||||
|         borderRadius: BorderRadius.circular(8), | ||||
|         child: Stack( | ||||
|   | ||||
| @@ -37,13 +37,10 @@ class CloudFileList extends HookConsumerWidget { | ||||
|  | ||||
|   double calculateAspectRatio() { | ||||
|     double total = 0; | ||||
|     for (var ratio in files.map( | ||||
|       (e) => | ||||
|           e.fileMeta?['ratio'] ?? | ||||
|           ((e.mimeType?.startsWith('image') ?? false) ? 1 : 16 / 9), | ||||
|     )) { | ||||
|     for (var ratio in files.map((e) => e.fileMeta?['ratio'] ?? 1)) { | ||||
|       total += ratio; | ||||
|     } | ||||
|     if (total == 0) return 1; | ||||
|     return total / files.length; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -25,22 +25,21 @@ class CloudFileWidget extends ConsumerWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final serverUrl = ref.watch(serverUrlProvider); | ||||
|     final uri = '$serverUrl/files/${item.id}'; | ||||
|     final uri = '$serverUrl/api/files/${item.id}'; | ||||
|  | ||||
|     var ratio = (item.fileMeta?['ratio'] ?? 1).toDouble(); | ||||
|     if (ratio == 0) ratio = 1.0; | ||||
|     final content = switch (item.mimeType?.split('/').firstOrNull) { | ||||
|       "image" => AspectRatio( | ||||
|         aspectRatio: (item.fileMeta?['ratio'] ?? 1).toDouble(), | ||||
|         aspectRatio: ratio, | ||||
|         child: UniversalImage( | ||||
|           uri: uri, | ||||
|           blurHash: noBlurhash ? null : item.fileMeta?['blur'], | ||||
|         ), | ||||
|       ), | ||||
|       "video" => AspectRatio( | ||||
|         aspectRatio: (item.fileMeta?['ratio'] ?? 16 / 9).toDouble(), | ||||
|         child: UniversalVideo( | ||||
|           uri: uri, | ||||
|           aspectRatio: (item.fileMeta?['ratio'] ?? 16 / 9).toDouble(), | ||||
|         ), | ||||
|         aspectRatio: ratio, | ||||
|         child: UniversalVideo(uri: uri, aspectRatio: ratio), | ||||
|       ), | ||||
|       _ => Text('Unable render for ${item.mimeType}'), | ||||
|     }; | ||||
| @@ -71,7 +70,7 @@ class CloudImageWidget extends ConsumerWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final serverUrl = ref.watch(serverUrlProvider); | ||||
|     final uri = '$serverUrl/files/${file?.id ?? fileId}'; | ||||
|     final uri = '$serverUrl/api/files/${file?.id ?? fileId}'; | ||||
|  | ||||
|     return AspectRatio( | ||||
|       aspectRatio: aspectRatio, | ||||
| @@ -87,7 +86,7 @@ class CloudImageWidget extends ConsumerWidget { | ||||
|     required String serverUrl, | ||||
|     bool original = false, | ||||
|   }) { | ||||
|     final uri = '$serverUrl/files/$fileId?original=$original'; | ||||
|     final uri = '$serverUrl/api/files/$fileId?original=$original'; | ||||
|     return CachedNetworkImageProvider(uri); | ||||
|   } | ||||
| } | ||||
| @@ -110,7 +109,7 @@ class ProfilePictureWidget extends ConsumerWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final serverUrl = ref.watch(serverUrlProvider); | ||||
|     final uri = '$serverUrl/files/${file?.id ?? fileId}'; | ||||
|     final uri = '$serverUrl/api/files/${file?.id ?? fileId}'; | ||||
|  | ||||
|     return ClipRRect( | ||||
|       borderRadius: BorderRadius.all(Radius.circular(radius)), | ||||
| @@ -303,7 +302,7 @@ class SplitAvatarWidget extends ConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     final serverUrl = ref.watch(serverUrlProvider); | ||||
|     final uri = '$serverUrl/files/$fileId'; | ||||
|     final uri = '$serverUrl/api/files/$fileId'; | ||||
|  | ||||
|     return SizedBox( | ||||
|       width: radius, | ||||
|   | ||||
| @@ -70,7 +70,7 @@ class _UniversalVideoState extends ConsumerState<UniversalVideo> { | ||||
|  | ||||
|     return Video( | ||||
|       controller: _videoController!, | ||||
|       aspectRatio: widget.aspectRatio, | ||||
|       aspectRatio: widget.aspectRatio != 1 ? widget.aspectRatio : null, | ||||
|       controls: | ||||
|           !kIsWeb && (Platform.isAndroid || Platform.isIOS) | ||||
|               ? MaterialVideoControls | ||||
|   | ||||
| @@ -384,7 +384,12 @@ class PostItem extends HookConsumerWidget { | ||||
|                         // Show truncation hint if post is truncated | ||||
|                         if (item.isTruncated && !isFullPost && item.type != 1) | ||||
|                           _PostTruncateHint().padding( | ||||
|                             bottom: item.attachments.isNotEmpty ? 8 : null, | ||||
|                             bottom: | ||||
|                                 (item.attachments.isNotEmpty || | ||||
|                                         item.repliedPost != null || | ||||
|                                         item.forwardedPost != null) | ||||
|                                     ? 8 | ||||
|                                     : null, | ||||
|                           ), | ||||
|                         if ((item.repliedPost != null || | ||||
|                                 item.forwardedPost != null) && | ||||
| @@ -571,7 +576,7 @@ class PostItem extends HookConsumerWidget { | ||||
|               callback: () { | ||||
|                 showAbuseReportSheet( | ||||
|                   context, | ||||
|                   resourceIdentifier: 'posts:${item.id}', | ||||
|                   resourceIdentifier: 'post/${item.id}', | ||||
|                 ); | ||||
|               }, | ||||
|             ), | ||||
|   | ||||
| @@ -55,7 +55,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | ||||
|   GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin")) | ||||
|   IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin")) | ||||
|   LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin")) | ||||
|   FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin")) | ||||
|   LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) | ||||
|   MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) | ||||
|   MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) | ||||
|   FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) | ||||
|   | ||||
| @@ -16,10 +16,10 @@ PODS: | ||||
|   - Firebase/Messaging (11.15.0): | ||||
|     - Firebase/CoreOnly | ||||
|     - FirebaseMessaging (~> 11.15.0) | ||||
|   - firebase_core (3.15.0): | ||||
|   - firebase_core (3.15.1): | ||||
|     - Firebase/CoreOnly (~> 11.15.0) | ||||
|     - FlutterMacOS | ||||
|   - firebase_messaging (15.2.8): | ||||
|   - firebase_messaging (15.2.9): | ||||
|     - Firebase/CoreOnly (~> 11.15.0) | ||||
|     - Firebase/Messaging (~> 11.15.0) | ||||
|     - firebase_core | ||||
| @@ -292,8 +292,8 @@ SPEC CHECKSUMS: | ||||
|   file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a | ||||
|   file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31 | ||||
|   Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e | ||||
|   firebase_core: 177f51be1650b15d2d5b9f1abf48792619288070 | ||||
|   firebase_messaging: 8748a5d4bb435993cffa7f5501292f3e914a23d7 | ||||
|   firebase_core: 8dc569d17b3a9fc3ee5ebc21b322411b4a796833 | ||||
|   firebase_messaging: adaf7fc22897a7aa49410d15f8a595bef2dbca2d | ||||
|   FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e | ||||
|   FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 | ||||
|   FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 | ||||
| @@ -310,7 +310,7 @@ SPEC CHECKSUMS: | ||||
|   GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 | ||||
|   irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba | ||||
|   livekit_client: c9d9f41996f5cf22b9ba0e8483e6af4ca5094059 | ||||
|   local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 | ||||
|   local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19 | ||||
|   media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65 | ||||
|   media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758 | ||||
|   nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 | ||||
|   | ||||
							
								
								
									
										48
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								pubspec.lock
									
									
									
									
									
								
							| @@ -13,10 +13,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: _flutterfire_internals | ||||
|       sha256: "50e24b769bd1e725732f0aff18b806b8731c1fbcf4e8018ab98e7c4805a2a52f" | ||||
|       sha256: a5788040810bd84400bc209913fbc40f388cded7cdf95ee2f5d2bff7e38d5241 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.3.57" | ||||
|     version: "1.3.58" | ||||
|   analyzer: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -349,10 +349,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: coverage | ||||
|       sha256: aa07dbe5f2294c827b7edb9a87bba44a9c15a3cc81bc8da2ca19b37322d30080 | ||||
|       sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.14.1" | ||||
|     version: "1.15.0" | ||||
|   croppy: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -629,50 +629,50 @@ packages: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: firebase_core | ||||
|       sha256: "5bba5924139e91d26446fd2601c18a6aa62c1161c768a989bb5e245dcdc20644" | ||||
|       sha256: c6e8a6bf883d8ddd0dec39be90872daca65beaa6f4cff0051ed3b16c56b82e9f | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.15.0" | ||||
|     version: "3.15.1" | ||||
|   firebase_core_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_core_platform_interface | ||||
|       sha256: "5d2ab45779d91af2aa0252dec9fe4ee1caa015d83377de255454dcaa1526a0e0" | ||||
|       sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "5.4.1" | ||||
|     version: "6.0.0" | ||||
|   firebase_core_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_core_web | ||||
|       sha256: eb3afccfc452b2b2075acbe0c4b27de62dd596802b4e5e19869c1e926cbb20b3 | ||||
|       sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.24.0" | ||||
|     version: "2.24.1" | ||||
|   firebase_messaging: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: firebase_messaging | ||||
|       sha256: c6711cf2f455532b84a94022c7aaf85088849763af2f01b775ca79d82d10a01a | ||||
|       sha256: "0f3363f97672eb9f65609fa00ed2f62cc8ec93e7e2d4def99726f9165d3d8a73" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "15.2.8" | ||||
|     version: "15.2.9" | ||||
|   firebase_messaging_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_messaging_platform_interface | ||||
|       sha256: "1c9dacccb1aee1bf17ba519dda5563a16fdd2ec1e79b5f2e421cb4bf75a166f7" | ||||
|       sha256: "7a05ef119a14c5f6a9440d1e0223bcba20c8daf555450e119c4c477bf2c3baa9" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "4.6.8" | ||||
|     version: "4.6.9" | ||||
|   firebase_messaging_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: firebase_messaging_web | ||||
|       sha256: "54317c26fa92f0d90a2017977ac791cb0504eca29fcf397f06adf727d4a7a2d5" | ||||
|       sha256: a4547f76da2a905190f899eb4d0150e1d0fd52206fce469d9f05ae15bb68b2c5 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.10.8" | ||||
|     version: "3.10.9" | ||||
|   fixnum: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1049,18 +1049,18 @@ packages: | ||||
|     dependency: "direct dev" | ||||
|     description: | ||||
|       name: freezed | ||||
|       sha256: "6022db4c7bfa626841b2a10f34dd1e1b68e8f8f9650db6112dcdeeca45ca793c" | ||||
|       sha256: "2d399f823b8849663744d2a9ddcce01c49268fb4170d0442a655bf6a2f47be22" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.0.6" | ||||
|     version: "3.1.0" | ||||
|   freezed_annotation: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: freezed_annotation | ||||
|       sha256: c87ff004c8aa6af2d531668b46a4ea379f7191dc6dfa066acd53d506da6e044b | ||||
|       sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.0.0" | ||||
|     version: "3.1.0" | ||||
|   frontend_server_client: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1385,10 +1385,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: local_auth_darwin | ||||
|       sha256: "630996cd7b7f28f5ab92432c4b35d055dd03a747bc319e5ffbb3c4806a3e50d2" | ||||
|       sha256: "25163ce60a5a6c468cf7a0e3dc8a165f824cabc2aa9e39a5e9fc5c2311b7686f" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.4.3" | ||||
|     version: "1.5.0" | ||||
|   local_auth_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -2174,10 +2174,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: source_helper | ||||
|       sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" | ||||
|       sha256: "4f81479fe5194a622cdd1713fe1ecb683a6e6c85cd8cec8e2e35ee5ab3fdf2a1" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.3.5" | ||||
|     version: "1.3.6" | ||||
|   source_map_stack_trace: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -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.0.0+110 | ||||
| version: 3.1.0+113 | ||||
|  | ||||
| environment: | ||||
|   sdk: ^3.7.2 | ||||
|   | ||||
							
								
								
									
										25
									
								
								web/.well-known/apple-app-site-association
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								web/.well-known/apple-app-site-association
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| { | ||||
|   "applinks": { | ||||
|     "apps": [], | ||||
|     "details": [ | ||||
|       { | ||||
|         "appIDs": [ | ||||
|           "W7HPZ53V6B.dev.solsynth.solian" | ||||
|         ], | ||||
|         "paths": [ | ||||
|           "*" | ||||
|         ], | ||||
|         "components": [ | ||||
|           { | ||||
|             "/": "/*" | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "webcredentials": { | ||||
|     "apps": [ | ||||
|       "W7HPZ53V6B.dev.solsynth.solian" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
							
								
								
									
										12
									
								
								web/.well-known/assetlinks.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/.well-known/assetlinks.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| [ | ||||
|   { | ||||
|     "relation": ["delegate_permission/common.handle_all_urls"], | ||||
|     "target": { | ||||
|       "namespace": "android_app", | ||||
|       "package_name": "dev.solsynth.solian", | ||||
|       "sha256_cert_fingerprints": [ | ||||
|         "57:0C:A4:E6:1F:57:DF:56:70:42:05:4B:43:E2:DD:9E:00:E6:77:C3:D8:3C:5F:D5:A0:05:59:30:5A:85:F9:BC" | ||||
|       ] | ||||
|     } | ||||
|   } | ||||
| ] | ||||
		Reference in New Issue
	
	Block a user