"Updated Podfile.lock, Info.plist, and various Dart files in lib directory, including ai_chat_args.dart, media.dart, action_sheet.dart, ai.dart, ai_chat_page.dart, and ai_message_bar.dart, with changes to code structure,

This commit is contained in:
Amir Hossein Mousavi 2024-10-03 12:13:16 +03:30
parent 9c7ff79cb9
commit 4aebc144fa
10 changed files with 244 additions and 121 deletions

View File

@ -77,6 +77,10 @@ PODS:
- Flutter - Flutter
- flutter_secure_storage (6.0.0): - flutter_secure_storage (6.0.0):
- Flutter - Flutter
- flutter_sound (9.6.0):
- Flutter
- flutter_sound_core (= 9.6.0)
- flutter_sound_core (9.6.0)
- flutter_vibrate (0.0.1): - flutter_vibrate (0.0.1):
- Flutter - Flutter
- GoogleDataTransport (9.4.1): - GoogleDataTransport (9.4.1):
@ -164,6 +168,7 @@ DEPENDENCIES:
- flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`) - flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- flutter_sound (from `.symlinks/plugins/flutter_sound/ios`)
- flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`) - flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`)
- home_widget (from `.symlinks/plugins/home_widget/ios`) - home_widget (from `.symlinks/plugins/home_widget/ios`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`) - image_cropper (from `.symlinks/plugins/image_cropper/ios`)
@ -189,6 +194,7 @@ SPEC REPOS:
- FirebaseCoreInternal - FirebaseCoreInternal
- FirebaseInstallations - FirebaseInstallations
- FirebaseMessaging - FirebaseMessaging
- flutter_sound_core
- GoogleDataTransport - GoogleDataTransport
- GoogleUtilities - GoogleUtilities
- IosAwnCore - IosAwnCore
@ -217,6 +223,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_local_notifications/ios" :path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_secure_storage: flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios" :path: ".symlinks/plugins/flutter_secure_storage/ios"
flutter_sound:
:path: ".symlinks/plugins/flutter_sound/ios"
flutter_vibrate: flutter_vibrate:
:path: ".symlinks/plugins/flutter_vibrate/ios" :path: ".symlinks/plugins/flutter_vibrate/ios"
home_widget: home_widget:
@ -265,6 +273,8 @@ SPEC CHECKSUMS:
flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
flutter_sound: dde9a913063b65a27ba8fdc2039036b99b136c79
flutter_sound_core: 0c6eb9d5268adc70ff159b3d65fd3d98a82d3a27
flutter_vibrate: 9f4c2ab57008965f78969472367c329dd77eb801 flutter_vibrate: 9f4c2ab57008965f78969472367c329dd77eb801
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15

View File

@ -59,7 +59,7 @@
<key>NSAppleMusicUsageDescription</key> <key>NSAppleMusicUsageDescription</key>
<string>This app requires access to Apple Music to [explain specific reason].</string> <string>This app requires access to Apple Music to [explain specific reason].</string>
<key>NSMicrophoneUsageDescription</key> <key>NSMicrophoneUsageDescription</key>
<string>... explain why the app uses the microphone here ...</string> <string> To send voice text this app requires Mic's permission.</string>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
@ -71,9 +71,9 @@
</array> </array>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<true/> <true />
</dict> </dict>
</dict> </dict>
</plist> </plist>

View File

@ -5,6 +5,7 @@ class AiChatArgs {
final BotsModel bot; final BotsModel bot;
final ChatsModel? chat; final ChatsModel? chat;
final Prompts? prompts; final Prompts? prompts;
final bool? attach;
AiChatArgs({required this.bot, this.chat, this.prompts}); AiChatArgs({required this.bot, this.chat, this.prompts, this.attach});
} }

View File

@ -163,7 +163,7 @@ class MediaService {
print("Cannot get download folder path $err"); print("Cannot get download folder path $err");
} }
} }
String path = "${dir?.path}$basename"; String path = "${dir?.path}${Platform.isIOS ? '/' : ''}$basename";
File file = File(path); File file = File(path);

View File

@ -382,7 +382,12 @@ class ActionSheetUtils {
), ),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
Text(bot.name.toString()) Expanded(
child: DidvanText(
bot.name.toString(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
))
], ],
), ),
), ),

View File

@ -235,7 +235,18 @@ class _AiState extends State<Ai> {
const SizedBox( const SizedBox(
width: 8, width: 8,
), ),
const MessageBarBtn( MessageBarBtn(
click: () {
Navigator.of(context)
.pushNamed(
Routes.aiChat,
arguments:
AiChatArgs(
bot:
bot,
attach:
true));
},
enable: false, enable: false,
icon: Icons icon: Icons
.attach_file_rounded), .attach_file_rounded),

View File

@ -23,6 +23,7 @@ import 'package:didvan/views/ai/ai_chat_state.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart'; import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/widgets/ai_message_bar.dart'; import 'package:didvan/views/ai/widgets/ai_message_bar.dart';
import 'package:didvan/views/ai/widgets/audio_wave.dart'; import 'package:didvan/views/ai/widgets/audio_wave.dart';
import 'package:didvan/views/widgets/didvan/button.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart'; import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/marquee_text.dart'; import 'package:didvan/views/widgets/marquee_text.dart';
@ -125,96 +126,160 @@ class _AiChatPageState extends State<AiChatPage> {
ActionSheetUtils(context).openDialog( ActionSheetUtils(context).openDialog(
data: ActionSheetData( data: ActionSheetData(
hasConfirmButtonClose: false, hasConfirmButtonClose: false,
onConfirmed: () async { hasConfirmButton: false,
final state = context.read<AiChatState>(); hasDismissButton: false,
await state
.changePlaceHolder(placeholder.text);
Future.delayed(
Duration.zero,
() => ActionSheetUtils(context).pop(),
);
},
content: ValueListenableBuilder<bool>( content: ValueListenableBuilder<bool>(
valueListenable: state.changingPlaceHolder, valueListenable: state.changingPlaceHolder,
builder: (context, value, child) => Column( builder: (context, value, child) =>
children: [ Container(
Stack( constraints: BoxConstraints(
children: [ maxHeight: MediaQuery.sizeOf(context)
Row( .height /
mainAxisAlignment: 3),
MainAxisAlignment.center, child: Column(
children: [ children: [
DidvanText( Expanded(
'شخصی‌سازی دستورات', child: SingleChildScrollView(
style: Theme.of(context) child: Column(
.textTheme children: [
.titleMedium, Stack(
), children: [
], Row(
), mainAxisAlignment:
Positioned( MainAxisAlignment
right: 0, .center,
top: 0, children: [
bottom: 0, DidvanText(
child: Center( 'شخصی‌سازی دستورات',
child: InkWell( style: Theme.of(
onTap: () { context)
ActionSheetUtils(context) .textTheme
.pop(); .titleMedium,
}, ),
child: const Icon( ],
DidvanIcons.close_solid, ),
size: 24, Positioned(
), right: 0,
top: 0,
bottom: 0,
child: Center(
child: InkWell(
onTap: () {
ActionSheetUtils(
context)
.pop();
},
child: const Icon(
DidvanIcons
.close_solid,
size: 24,
),
),
)),
],
), ),
)), const SizedBox(
], height: 12,
), ),
const SizedBox( const DidvanText(
height: 12, 'دوست دارید هوشان چه چیزهایی را درباره شما بداند تا بتواند پاسخ‌های بهتری ارائه دهد؟ '),
), const SizedBox(
const DidvanText( height: 12,
'دوست دارید هوشان چه چیزهایی را درباره شما بداند تا بتواند پاسخ‌های بهتری ارائه دهد؟ '), ),
const SizedBox( value
height: 12, ? Center(
), child: Image.asset(
value Assets
? Center( .loadingAnimation,
child: Image.asset( width: 60,
Assets.loadingAnimation, height: 60,
width: 60, ),
height: 60, )
: TextField(
controller:
placeholder,
style: (Theme.of(
context)
.textTheme
.bodyMedium)!
.copyWith(
fontFamily: DesignConfig
.fontFamily
.padRight(
3)),
minLines: 5,
maxLines: 5,
keyboardType:
TextInputType
.multiline,
decoration:
InputDecoration(
filled: true,
fillColor: Theme.of(
context)
.colorScheme
.secondCTA,
contentPadding:
const EdgeInsets
.fromLTRB(
10,
18,
10,
0),
border: const OutlineInputBorder(
borderRadius:
DesignConfig
.lowBorderRadius),
errorStyle:
const TextStyle(
height:
0.01),
),
),
],
),
),
),
const SizedBox(
height: 12,
),
Row(
children: [
Expanded(
child: DidvanButton(
onPressed: () {
Navigator.of(context).pop();
},
title: 'بازگشت',
style:
ButtonStyleMode.secondary,
), ),
) ),
: TextField( const SizedBox(width: 20),
controller: placeholder, Expanded(
style: (Theme.of(context) child: DidvanButton(
.textTheme style:
.bodyMedium)! ButtonStyleMode.primary,
.copyWith( onPressed: () async {
fontFamily: DesignConfig final state = context
.fontFamily .read<AiChatState>();
.padRight(3)), await state
minLines: 4, .changePlaceHolder(
maxLines: 4, placeholder.text);
keyboardType: Future.delayed(
TextInputType.multiline, Duration.zero,
decoration: InputDecoration( () => ActionSheetUtils(
filled: true, context)
fillColor: Theme.of(context) .pop(),
.colorScheme );
.secondCTA, },
contentPadding: title: 'تایید',
const EdgeInsets.fromLTRB(
10, 10, 10, 0),
border: const OutlineInputBorder(
borderRadius: DesignConfig
.lowBorderRadius),
errorStyle: const TextStyle(
height: 0.01),
), ),
) ),
], ],
),
],
),
), ),
))); )));
}, },
@ -321,6 +386,7 @@ class _AiChatPageState extends State<AiChatPage> {
// : // :
AiMessageBar( AiMessageBar(
bot: widget.args.bot, bot: widget.args.bot,
attch: widget.args.attach,
), ),
], ],
)), )),
@ -394,7 +460,7 @@ class _AiChatPageState extends State<AiChatPage> {
children: [ children: [
Container( Container(
constraints: BoxConstraints( constraints: BoxConstraints(
maxWidth: MediaQuery.sizeOf(context).width / 1.5), maxWidth: MediaQuery.sizeOf(context).width / 1.3),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: DesignConfig.mediumBorderRadius.copyWith( borderRadius: DesignConfig.mediumBorderRadius.copyWith(
bottomLeft: !message.role.toString().contains('user') bottomLeft: !message.role.toString().contains('user')
@ -513,24 +579,43 @@ class _AiChatPageState extends State<AiChatPage> {
value: historyAiChatState value: historyAiChatState
.bots[index], .bots[index],
height: 72, height: 72,
child: Row( child: Container(
children: [ constraints:
ClipOval( const BoxConstraints(
child: CachedNetworkImage( maxWidth: 200),
imageUrl: child: Row(
children: [
ClipOval(
child:
CachedNetworkImage(
imageUrl:
historyAiChatState
.bots[index]
.image
.toString(),
width: 42,
height: 42,
),
),
const SizedBox(width: 12),
Expanded(
child: Directionality(
textDirection:
TextDirection.ltr,
child: DidvanText(
historyAiChatState historyAiChatState
.bots[index] .bots[index]
.image .name
.toString(), .toString(),
width: 42, maxLines: 1,
height: 42, overflow:
TextOverflow
.ellipsis,
),
),
), ),
), ],
const SizedBox(width: 12), ),
DidvanText(
'${historyAiChatState.bots[index].name}X',
),
],
), ),
), ),
) )
@ -542,7 +627,7 @@ class _AiChatPageState extends State<AiChatPage> {
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 8), horizontal: 8),
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: 120), maxWidth: 100),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: borderRadius:
DesignConfig.lowBorderRadius, DesignConfig.lowBorderRadius,
@ -553,11 +638,15 @@ class _AiChatPageState extends State<AiChatPage> {
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: DidvanText( child: Directionality(
'${widget.args.bot.name}', textDirection:
maxLines: 1, TextDirection.ltr,
overflow: child: DidvanText(
TextOverflow.ellipsis, '${widget.args.bot.name}',
maxLines: 1,
overflow:
TextOverflow.ellipsis,
),
), ),
), ),
const Icon( const Icon(

View File

@ -1,6 +1,7 @@
// ignore_for_file: library_private_types_in_public_api, avoid_web_libraries_in_flutter // ignore_for_file: library_private_types_in_public_api, avoid_web_libraries_in_flutter
import 'dart:async'; import 'dart:async';
import 'package:record/record.dart';
import 'package:universal_html/html.dart' as html; import 'package:universal_html/html.dart' as html;
import 'dart:io'; import 'dart:io';
import 'package:audio_session/audio_session.dart'; import 'package:audio_session/audio_session.dart';
@ -39,7 +40,9 @@ typedef _Fn = void Function();
class AiMessageBar extends StatefulWidget { class AiMessageBar extends StatefulWidget {
final BotsModel bot; final BotsModel bot;
const AiMessageBar({Key? key, required this.bot}) : super(key: key); final bool? attch;
const AiMessageBar({Key? key, required this.bot, this.attch})
: super(key: key);
@override @override
_AiMessageBarState createState() => _AiMessageBarState(); _AiMessageBarState createState() => _AiMessageBarState();
@ -55,7 +58,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
bool _mPlayerIsInited = false; bool _mPlayerIsInited = false;
bool _mRecorderIsInited = false; bool _mRecorderIsInited = false;
bool _mplaybackReady = false; bool _mplaybackReady = false;
bool openAttach = false; late bool openAttach = widget.attch ?? false;
Timer? _timer; Timer? _timer;
final theSource = AudioSource.microphone; final theSource = AudioSource.microphone;
@ -91,9 +94,13 @@ class _AiMessageBarState extends State<AiMessageBar> {
Future<void> openTheRecorder() async { Future<void> openTheRecorder() async {
if (!kIsWeb) { if (!kIsWeb) {
var status = await Permission.microphone.request(); var status = await Permission.microphone.status;
await AudioRecorder().hasPermission();
if (status != PermissionStatus.granted) { if (status != PermissionStatus.granted) {
throw RecordingPermissionException('Microphone permission not granted'); if (!Platform.isIOS) {
throw RecordingPermissionException(
'Microphone permission not granted');
}
} }
} }
await _mRecorder!.openRecorder(); await _mRecorder!.openRecorder();
@ -253,7 +260,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
builder: (context, value, child) => Padding( builder: (context, value, child) => Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8), padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
child: SizedBox( child: SizedBox(
width: 46, width: 50,
child: Center( child: Center(
child: DidvanText( child: DidvanText(
DateTimeUtils.normalizeTimeDuration(value)), DateTimeUtils.normalizeTimeDuration(value)),

View File

@ -348,7 +348,7 @@ class _ProfilePageState extends State<ProfilePage> {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
DidvanText( DidvanText(
'نسخه نرم‌افزار: 3.3.4', 'نسخه نرم‌افزار: 3.3.5',
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context).textTheme.bodySmall,
), ),
], ],

View File

@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 3.3.4+3340 version: 3.3.5+3350
environment: environment:
sdk: ">=2.19.0 <3.0.0" sdk: ">=2.19.0 <3.0.0"