fix audio

This commit is contained in:
OkaykOrhmn 2024-09-25 12:40:51 +03:30
parent 2b1be1989a
commit 74b7f9dd3d
11 changed files with 184 additions and 113 deletions

View File

@ -15,7 +15,7 @@ class MessageData {
final RadarAttachment? radar;
final File? audioFile;
final int? audioDuration;
final double? duration;
final int? duration;
MessageData({
required this.id,
@ -60,4 +60,32 @@ class MessageData {
'news': news?.toJson(),
'radar': radar?.toJson(),
};
MessageData copyWith({
int? id,
String? text,
String? audio,
bool? writedByAdmin,
bool? readed,
String? createdAt,
NewsAttachment? news,
RadarAttachment? radar,
File? audioFile,
int? audioDuration,
int? duration,
}) {
return MessageData(
id: id ?? this.id,
text: text ?? this.text,
audio: audio ?? this.audio,
writedByAdmin: writedByAdmin ?? this.writedByAdmin,
readed: readed ?? this.readed,
news: news ?? this.news,
radar: radar ?? this.radar,
createdAt: createdAt ?? this.createdAt,
audioFile: audioFile ?? this.audioFile,
audioDuration: audioDuration ?? this.audioDuration,
duration: duration ?? this.duration,
);
}
}

View File

@ -154,7 +154,7 @@ class _AiState extends State<Ai> {
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Text(
"به هوشان, هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.",
"به هوشان؛ هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.",
textAlign: TextAlign.center,
),
)

View File

@ -157,7 +157,7 @@ class _AiChatPageState extends State<AiChatPage> {
height: 12,
),
const DidvanText(
'دوست دارید هوشان، چه چیزهایی را درباره شما بداند تا بتواند پاسخ‌های بهتری ارائه دهد؟ \nدستورات و اطلاعات ارائه شما، بر روی تمامی پیام‌هایی که از این به بعد ارسال می‌کنید، اعمال خواهد شد.'),
'دوست دارید هوشان چه چیزهایی را درباره شما بداند تا بتواند پاسخ‌های بهتری ارائه دهد؟ '),
const SizedBox(
height: 12,
),
@ -254,7 +254,7 @@ class _AiChatPageState extends State<AiChatPage> {
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Text(
"به هوشان, هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.",
"به هوشان؛ هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.",
textAlign: TextAlign.center,
),
)

View File

@ -38,7 +38,6 @@ class _AudioWaveState extends State<AudioWave> {
@override
void initState() {
super.initState();
print(widget.file);
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (widget.totalDuration == null) {
await VoiceService.getDuration(src: widget.file).then((duration) {
@ -116,64 +115,60 @@ class _AudioWaveState extends State<AudioWave> {
if (!snapshot.hasData) {
return const SizedBox();
}
return totalDuration == null ||
if ((totalDuration == null ||
(totalDuration != null &&
VoiceService.audioPlayer.playing &&
VoiceService.audioPlayer.duration!.inSeconds !=
totalDuration!.inSeconds &&
VoiceService.src == widget.file)
? Padding(
padding: EdgeInsets.symmetric(
vertical: widget.loadingPaddingSize),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
5,
(index) => SpinKitWave(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.4),
size: 32,
itemCount: 10,
))),
)
: Padding(
padding: const EdgeInsets.fromLTRB(24, 12, 12, 0),
child: ProgressBar(
thumbColor: Theme.of(context).colorScheme.title,
progressBarColor: DesignConfig.isDark
? Theme.of(context).colorScheme.title
: Theme.of(context).colorScheme.primary,
baseBarColor:
Theme.of(context).colorScheme.border,
bufferedBarColor:
Theme.of(context).colorScheme.splash,
total: totalDuration!,
progress: VoiceService.src == widget.file
? snapshot.data ?? Duration.zero
: Duration.zero,
thumbRadius: 6,
barHeight: 3,
// timeLabelTextStyle: TextStyle(
// fontSize: showTimer ? null : 0,
// height: showTimer ? 3 : 0,
// color:
// Theme.of(context).colorScheme.text,
// fontFamily:
// DesignConfig.fontFamily.replaceAll(
// '-FA',
// '',
// ),
// ),
onSeek: (value) {
if (VoiceService.src == widget.file) {
VoiceService.audioPlayer.seek(Duration(
milliseconds: value.inMilliseconds));
}
},
),
);
(VoiceService.audioPlayer.duration != null &&
VoiceService
.audioPlayer.duration!.inSeconds !=
totalDuration!.inSeconds))) &&
VoiceService.src == widget.file &&
VoiceService.audioPlayer.playing) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: widget.loadingPaddingSize),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
5,
(index) => SpinKitWave(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.4),
size: 32,
itemCount: 10,
))),
);
}
return Padding(
padding: EdgeInsets.fromLTRB(
24, 12, 12, totalDuration != null ? 0 : 12),
child: ProgressBar(
thumbColor: Theme.of(context).colorScheme.title,
progressBarColor: DesignConfig.isDark
? Theme.of(context).colorScheme.title
: Theme.of(context).colorScheme.primary,
baseBarColor: Theme.of(context).colorScheme.border,
bufferedBarColor: Theme.of(context).colorScheme.splash,
total: totalDuration ?? Duration.zero,
progress: VoiceService.src == widget.file
? snapshot.data ?? Duration.zero
: Duration.zero,
thumbRadius: 6,
barHeight: 3,
timeLabelTextStyle: TextStyle(
fontSize: totalDuration != null ? null : 0,
// height: totalDuration != null ? 3 : 0,
color: Theme.of(context).colorScheme.text,
fontFamily: DesignConfig.fontFamily),
onSeek: (value) {
if (VoiceService.src == widget.file) {
VoiceService.audioPlayer.seek(
Duration(milliseconds: value.inMilliseconds));
}
},
),
);
},
),
)

View File

@ -6,6 +6,7 @@ import 'package:didvan/models/message_data/news_attachment.dart';
import 'package:didvan/models/message_data/radar_attachment.dart';
import 'package:didvan/providers/core.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/media/voice.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:flutter/foundation.dart';
@ -25,7 +26,9 @@ class DirectState extends CoreProvier {
NewsAttachment? replyNews;
RadarAttachment? replyRadar;
File? recordedFile;
Uint8List? recordedFileBytes;
int? audioDuration;
String? path;
bool isRecording = false;
@ -74,21 +77,18 @@ class DirectState extends CoreProvier {
}
Future<void> stopRecording({required bool sendImidiately}) async {
final path = await _recorder.stop();
path = await _recorder.stop();
isRecording = false;
if (path == null) {
notifyListeners();
return;
}
if (kIsWeb) {
// final uri = Uri.file(path);
// recordedFile = File.fromUri(uri);
final Uri audioUri = Uri.parse(path);
final Uri audioUri = Uri.parse(path!);
final http.Response audioResponse = await http.get(audioUri);
final bytes = audioResponse.bodyBytes;
recordedFile = File.fromRawPath(bytes);
recordedFileBytes = audioResponse.bodyBytes;
} else {
recordedFile = File(path);
recordedFile = File(path!);
}
if (sendImidiately) {
await sendMessage();
@ -121,7 +121,8 @@ class DirectState extends CoreProvier {
}
Future<void> sendMessage() async {
if ((text == null || text!.isEmpty) && recordedFile == null) return;
if ((text == null || text!.isEmpty) &&
(recordedFile == null && recordedFileBytes == null)) return;
MediaService.audioPlayer.stop();
final body = {};
@ -138,17 +139,31 @@ class DirectState extends CoreProvier {
body.addAll({'newsId': replyNews!.id});
}
if (replyNews != null) {
body.addAll({'newsId': replyNews!.id});
}
if (path != null) {
final duration = await VoiceService.getDuration(src: path!);
if (duration != null) {
body.addAll({'duration': duration.inSeconds.toString()});
}
}
final uploadFile = recordedFile;
final uploadFileBytes = recordedFileBytes;
text = null;
recordedFile = null;
recordedFileBytes = null;
replyRadar = null;
replyNews = null;
path = null;
notifyListeners();
final service =
RequestService(RequestHelper.sendDirectMessage(typeId), body: body);
if (uploadFile == null) {
if (uploadFile == null && uploadFileBytes == null) {
await service.post();
if (service.isSuccess) {
@ -171,7 +186,7 @@ class DirectState extends CoreProvier {
createdAt:
DateTime.now().subtract(const Duration(minutes: 210)).toString(),
text: text,
audio: null,
audio: path,
audioFile: uploadFile,
radar: replyRadar,
news: replyNews,
@ -185,20 +200,33 @@ class DirectState extends CoreProvier {
_addToDailyGrouped(messages[i]);
}
await service.multipart(
file: Platform.isIOS
? File(uploadFile.path.replaceAll('file://', ''))
: uploadFile,
method: 'POST',
fieldName: 'audio',
fileName: 'voice-message',
mediaExtension: 'm4a',
mediaFormat: 'audio',
);
if (kIsWeb) {
await service.multipartBytes(
file: uploadFileBytes!,
method: 'POST',
fieldName: 'audio',
fileName: 'voice-message',
mediaExtension: 'm4a',
mediaFormat: 'audio',
);
} else {
await service.multipart(
file: Platform.isIOS
? File(uploadFile!.path.replaceAll('file://', ''))
: uploadFile,
method: 'POST',
fieldName: 'audio',
fileName: 'voice-message',
mediaExtension: 'm4a',
mediaFormat: 'audio',
);
}
if (service.isSuccess) {
final message = service.result['message'];
messages[0].id = MessageData.fromJson(message).id;
final m = MessageData.fromJson(message);
messages[0] = m;
update();
}
}
}

View File

@ -2,16 +2,13 @@ import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/message_data/message_data.dart';
import 'package:didvan/services/media/voice.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/views/ai/widgets/audio_wave.dart';
import 'package:didvan/views/direct/direct_state.dart';
import 'package:didvan/views/direct/widgets/audio_widget.dart';
import 'package:didvan/views/widgets/didvan/divider.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:provider/provider.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
@ -89,6 +86,9 @@ class Message extends StatelessWidget {
if (message.audio != null || message.audioFile != null)
AudioWave(
file: message.audio ?? message.audioFile!.path,
totalDuration: message.duration != null
? Duration(seconds: message.duration!)
: null,
),
if (message.radar != null || message.news != null)
const DidvanDivider(),

View File

@ -1,9 +1,9 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/views/ai/widgets/audio_wave.dart';
import 'package:didvan/views/ai/widgets/message_bar_btn.dart';
import 'package:didvan/views/direct/direct_state.dart';
import 'package:didvan/views/direct/widgets/audio_widget.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
@ -64,7 +64,9 @@ class MessageBox extends StatelessWidget {
builder: (context, state, child) {
if (state.isRecording) {
return const _Recording();
} else if (!state.isRecording && state.recordedFile != null) {
} else if (!state.isRecording &&
(state.recordedFile != null ||
state.recordedFileBytes != null)) {
return const _RecordChecking();
}
return const _Typing();
@ -223,9 +225,8 @@ class _RecordChecking extends StatelessWidget {
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: AudioWidget(
audioFile: state.recordedFile!,
id: 0,
child: AudioWave(
file: state.path!,
// deleteClidk: () => state.deleteRecordedFile,
),
),

View File

@ -154,7 +154,7 @@ class _BookmarksState extends State<Bookmarks> {
: Column(
children: [
DidvanText(
'در قسمت رصدخانه من، تمامی محتواهایی که در قسمت‌های مختلف سوپراپلیکیشن دیدوان، بوکمارک (نشان‌دار) کرده‌اید، به تفکیک نمایش داده می‌شوند. هم‌چنین امکان درج یادداشت شخصی بصورت ضمیمه برای هر محتوا وجود دارد.',
'در قسمت رصدخانه من، تمامی مطالبی که در قسمت‌های مختلف سوپراپلیکیشن دیدوان، بوکمارک (نشان‌دار) کرده‌اید، به تفکیک نمایش داده می‌شوند. هم‌چنین امکان درج یادداشت شخصی بصورت ضمیمه برای هر محتوا وجود دارد.',
fontSize: 14,
color: Theme.of(context).colorScheme.title,
textAlign: TextAlign.justify,

View File

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

View File

@ -1,7 +1,8 @@
// ignore_for_file: library_private_types_in_public_api, deprecated_member_use
import 'package:didvan/constants/assets.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
@ -18,25 +19,33 @@ class _WebViewState extends State<WebView> {
bool loading = true;
int progress = 0;
final Set<Factory<VerticalDragGestureRecognizer>> gestureRecognizers = {
Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer())
};
void _onProgress(int progress) {
setState(() {
this.progress = progress;
});
}
void _onPageFinished(String url) async {
await Future.delayed(const Duration(seconds: 2));
setState(() {
if (progress == 100) loading = false;
});
}
@override
void initState() {
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
// Update loading bar.
setState(() {
this.progress = progress;
});
},
onProgress: _onProgress,
onPageStarted: (String url) {},
onPageFinished: (String url) async {
await Future.delayed(const Duration(seconds: 2));
setState(() {
if (progress == 100) loading = false;
});
},
onPageFinished: _onPageFinished,
onHttpError: (HttpResponseError error) {},
onWebResourceError: (WebResourceError error) {
// navigatorKey.currentState!.pop();
@ -65,11 +74,12 @@ class _WebViewState extends State<WebView> {
}
},
child: Scaffold(
appBar: AppBar(
title: const DidvanText(
'بازگشت به دیدوان',
),
),
// appBar: AppBar(
// title: const DidvanText(
// 'بازگشت به دیدوان',
// ),
// leading: const BackButton(),
// ),
body: loading
? Center(
child: Image.asset(
@ -78,7 +88,16 @@ class _WebViewState extends State<WebView> {
height: 60,
),
)
: WebViewWidget(controller: controller),
: LayoutBuilder(builder: (context, constraints) {
return SizedBox(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
child: WebViewWidget(
controller: controller,
gestureRecognizers: gestureRecognizers,
),
);
}),
));
}
}

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.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 3.3.0+3300
version: 3.3.1+3300
environment:
sdk: ">=2.19.0 <3.0.0"