fix audio
This commit is contained in:
parent
2b1be1989a
commit
74b7f9dd3d
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class _AiState extends State<Ai> {
|
|||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Text(
|
||||
"به هوشان, هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.",
|
||||
"به هوشان؛ هوش مصنوعی دیدوان خوش آمدید. \nبرای شروع گفتگو پیام مورد نظر خود را در کادر زیر بنویسید.",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,13 +115,15 @@ 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(
|
||||
(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(
|
||||
|
|
@ -137,39 +138,33 @@ class _AudioWaveState extends State<AudioWave> {
|
|||
size: 32,
|
||||
itemCount: 10,
|
||||
))),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 12, 12, 0),
|
||||
);
|
||||
}
|
||||
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!,
|
||||
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: showTimer ? null : 0,
|
||||
// height: showTimer ? 3 : 0,
|
||||
// color:
|
||||
// Theme.of(context).colorScheme.text,
|
||||
// fontFamily:
|
||||
// DesignConfig.fontFamily.replaceAll(
|
||||
// '-FA',
|
||||
// '',
|
||||
// ),
|
||||
// ),
|
||||
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));
|
||||
VoiceService.audioPlayer.seek(
|
||||
Duration(milliseconds: value.inMilliseconds));
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,9 +200,19 @@ class DirectState extends CoreProvier {
|
|||
_addToDailyGrouped(messages[i]);
|
||||
}
|
||||
|
||||
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://', ''))
|
||||
? File(uploadFile!.path.replaceAll('file://', ''))
|
||||
: uploadFile,
|
||||
method: 'POST',
|
||||
fieldName: 'audio',
|
||||
|
|
@ -195,10 +220,13 @@ class DirectState extends CoreProvier {
|
|||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class _BookmarksState extends State<Bookmarks> {
|
|||
: Column(
|
||||
children: [
|
||||
DidvanText(
|
||||
'در قسمت رصدخانه من، تمامی محتواهایی که در قسمتهای مختلف سوپراپلیکیشن دیدوان، بوکمارک (نشاندار) کردهاید، به تفکیک نمایش داده میشوند. همچنین امکان درج یادداشت شخصی بصورت ضمیمه برای هر محتوا وجود دارد.',
|
||||
'در قسمت رصدخانه من، تمامی مطالبی که در قسمتهای مختلف سوپراپلیکیشن دیدوان، بوکمارک (نشاندار) کردهاید، به تفکیک نمایش داده میشوند. همچنین امکان درج یادداشت شخصی بصورت ضمیمه برای هر محتوا وجود دارد.',
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).colorScheme.title,
|
||||
textAlign: TextAlign.justify,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
);
|
||||
}),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue