mirror of
https://gitlab.com/comunic/comunicmobile
synced 2025-02-18 06:32:39 +00:00
201 lines
5.4 KiB
Dart
201 lines
5.4 KiB
Dart
/// Chat file tile
|
|
///
|
|
/// @author Pierre Hubert
|
|
import 'dart:io';
|
|
|
|
import 'package:cached_network_image/cached_network_image.dart';
|
|
import 'package:comunic/helpers/conversation_files_helper.dart';
|
|
import 'package:comunic/models/conversation_message.dart';
|
|
import 'package:comunic/ui/widgets/async_screen_widget.dart';
|
|
import 'package:comunic/ui/widgets/audio_player_widget.dart';
|
|
import 'package:comunic/ui/widgets/network_image_widget.dart';
|
|
import 'package:comunic/utils/intl_utils.dart';
|
|
import 'package:comunic/utils/log_utils.dart';
|
|
import 'package:comunic/utils/ui_utils.dart';
|
|
import 'package:dio/dio.dart';
|
|
import 'package:filesize/filesize.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
const _AreaSize = 150.0;
|
|
|
|
class ConversationFileWidget extends StatefulWidget {
|
|
final int messageID;
|
|
final ConversationMessageFile file;
|
|
|
|
const ConversationFileWidget({
|
|
Key key,
|
|
@required this.messageID,
|
|
@required this.file,
|
|
}) : assert(messageID != null),
|
|
assert(file != null),
|
|
super(key: key);
|
|
|
|
@override
|
|
_ConversationFileWidgetState createState() => _ConversationFileWidgetState();
|
|
}
|
|
|
|
class _ConversationFileWidgetState extends State<ConversationFileWidget> {
|
|
final _refreshKey = GlobalKey<AsyncScreenWidgetState>();
|
|
|
|
File _targetFile;
|
|
|
|
bool _isDownloaded;
|
|
|
|
bool _downloading = false;
|
|
var _downloadProgress = 0.0;
|
|
CancelToken _cancelDownloadToken;
|
|
|
|
ConversationMessageFile get file => widget.file;
|
|
|
|
Future<void> _refresh() async {
|
|
_targetFile = await ConversationFilesHelper.getPathForChatFile(
|
|
widget.messageID, file);
|
|
|
|
_isDownloaded = await _targetFile.exists();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
width: _AreaSize,
|
|
height: _AreaSize,
|
|
child: AsyncScreenWidget(
|
|
key: _refreshKey,
|
|
onReload: _refresh,
|
|
onBuild: _buildContent,
|
|
errorMessage: tr("Error!"),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildContent() => _isDownloaded || !file.downloadable
|
|
? _buildFileWidget()
|
|
: _buildDownloadWidget();
|
|
|
|
Widget _buildDownloadWidget() => Stack(
|
|
children: <Widget>[
|
|
// Thumbnail, if possible
|
|
!file.hasThumbnail
|
|
? Container()
|
|
: CachedNetworkImage(
|
|
imageUrl: file.thumbnail,
|
|
width: _AreaSize,
|
|
height: _AreaSize,
|
|
fit: BoxFit.fill,
|
|
),
|
|
|
|
Container(
|
|
width: _AreaSize,
|
|
color: Color(0x66000000),
|
|
child: DefaultTextStyle(
|
|
style: TextStyle(color: Colors.white),
|
|
child: Column(
|
|
children: <Widget>[
|
|
Spacer(),
|
|
Icon(file.icon, color: Colors.white),
|
|
Spacer(),
|
|
_buildDownloadArea(),
|
|
Spacer(),
|
|
Text(filesize(file.size)),
|
|
Spacer(),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
|
|
Widget _buildDownloadArea() => _downloading
|
|
? _buildDownloadingWidget()
|
|
: Material(
|
|
borderRadius: BorderRadius.all(Radius.circular(2.0)),
|
|
color: Colors.green,
|
|
child: IconButton(
|
|
icon: Icon(Icons.file_download),
|
|
onPressed: _downloadFile,
|
|
color: Colors.white,
|
|
),
|
|
);
|
|
|
|
Widget _buildDownloadingWidget() => Container(
|
|
width: 36,
|
|
height: 36,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
CircularProgressIndicator(value: _downloadProgress),
|
|
Center(
|
|
child: InkWell(
|
|
onTap: () => _cancelDownloadToken.cancel(),
|
|
child: Icon(Icons.cancel, color: Colors.white),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
|
|
Future<void> _downloadFile() async {
|
|
try {
|
|
setState(() {
|
|
_cancelDownloadToken = CancelToken();
|
|
_downloading = true;
|
|
_downloadProgress = 0.0;
|
|
});
|
|
|
|
await ConversationFilesHelper.download(
|
|
msgID: widget.messageID,
|
|
fileInfo: file,
|
|
onProgress: (p) => setState(() => _downloadProgress = p),
|
|
cancelToken: _cancelDownloadToken,
|
|
);
|
|
|
|
await _refreshKey.currentState.refresh();
|
|
} catch (e, s) {
|
|
logError(e, s);
|
|
showSimpleSnack(context, tr("Failed to download file!"));
|
|
}
|
|
|
|
setState(() {
|
|
_downloading = false;
|
|
});
|
|
}
|
|
|
|
Widget _buildFileWidget() {
|
|
switch (file.fileType) {
|
|
// Images
|
|
case ConversationMessageFileType.IMAGE:
|
|
return Center(
|
|
child: NetworkImageWidget(
|
|
url: file.url,
|
|
thumbnailURL: file.thumbnail,
|
|
allowFullScreen: true,
|
|
),
|
|
);
|
|
|
|
// Audio player
|
|
case ConversationMessageFileType.AUDIO:
|
|
return AudioPlayerWidget(_targetFile);
|
|
|
|
// The file is not downloadable, we open it in the browser
|
|
default:
|
|
return Center(
|
|
child: MaterialButton(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Spacer(flex: 2),
|
|
Icon(file.icon, color: Colors.white),
|
|
Spacer(),
|
|
Text(file.name, textAlign: TextAlign.center),
|
|
Spacer(flex: 2),
|
|
],
|
|
),
|
|
onPressed: () => launch(file.url),
|
|
),
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
}
|