mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-22 12:59:21 +00:00
Can copy message to clipboard
This commit is contained in:
parent
8705aa1b0d
commit
217111e3fd
@ -1,3 +1,4 @@
|
||||
import 'package:clipboard/clipboard.dart';
|
||||
import 'package:comunic/models/conversation.dart';
|
||||
import 'package:comunic/models/conversation_message.dart';
|
||||
import 'package:comunic/models/user.dart';
|
||||
@ -13,7 +14,12 @@ import 'package:flutter/material.dart';
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
enum _MenuChoices { DELETE, REQUEST_UPDATE_CONTENT }
|
||||
enum _MenuChoices {
|
||||
COPY_URL,
|
||||
COPY_MESSAGE,
|
||||
DELETE,
|
||||
REQUEST_UPDATE_CONTENT
|
||||
}
|
||||
|
||||
typedef OnRequestMessageUpdate = void Function(ConversationMessage);
|
||||
typedef OnRequestMessageDelete = void Function(ConversationMessage);
|
||||
@ -60,6 +66,18 @@ class ConversationMessageTile extends StatelessWidget {
|
||||
width: 35.0,
|
||||
),
|
||||
itemBuilder: (c) => [
|
||||
|
||||
PopupMenuItem(
|
||||
enabled: (message.message?.content ?? "") != "",
|
||||
value: _MenuChoices.COPY_MESSAGE,
|
||||
child: Text(tr("Copy message")),
|
||||
),
|
||||
|
||||
PopupMenuItem(
|
||||
enabled: message.file != null,
|
||||
value: _MenuChoices.COPY_URL,
|
||||
child: Text(tr("Copy URL")),
|
||||
),
|
||||
// Update message content
|
||||
PopupMenuItem(
|
||||
enabled: message.isOwner,
|
||||
@ -249,6 +267,14 @@ class ConversationMessageTile extends StatelessWidget {
|
||||
/// Process menu choice
|
||||
void _menuOptionSelected(_MenuChoices value) {
|
||||
switch (value) {
|
||||
case _MenuChoices.COPY_MESSAGE:
|
||||
FlutterClipboard.copy(message.message.content);
|
||||
break;
|
||||
|
||||
case _MenuChoices.COPY_URL:
|
||||
FlutterClipboard.copy(message.file.url);
|
||||
break;
|
||||
|
||||
case _MenuChoices.REQUEST_UPDATE_CONTENT:
|
||||
onRequestMessageUpdate(message);
|
||||
break;
|
||||
|
@ -1,135 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:comunic/utils/date_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Audio player widget
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class AudioPlayerWidget extends StatefulWidget {
|
||||
final File file;
|
||||
|
||||
const AudioPlayerWidget(this.file);
|
||||
|
||||
@override
|
||||
_AudioPlayerWidgetState createState() => _AudioPlayerWidgetState();
|
||||
}
|
||||
|
||||
class _AudioPlayerWidgetState extends State<AudioPlayerWidget> {
|
||||
AudioPlayer _player;
|
||||
|
||||
Duration _mediaDuration;
|
||||
Duration _mediaPosition;
|
||||
|
||||
double get _max => _mediaDuration?.inMilliseconds?.toDouble() ?? 0.0;
|
||||
|
||||
double get _value => _mediaPosition?.inMilliseconds?.toDouble() ?? 0.0;
|
||||
|
||||
bool get _playing =>
|
||||
_player != null && _player.state == AudioPlayerState.PLAYING;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
|
||||
if (_player != null) _player.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
textStyle: TextStyle(color: Colors.white),
|
||||
color: Colors.transparent,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Spacer(),
|
||||
Icon(Icons.audiotrack, color: Colors.white),
|
||||
Spacer(),
|
||||
Slider(
|
||||
value: _value,
|
||||
onChanged: (newValue) =>
|
||||
_player.seek(Duration(milliseconds: newValue.toInt())),
|
||||
max: _max,
|
||||
activeColor: Colors.white,
|
||||
min: 0,
|
||||
),
|
||||
Spacer(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Spacer(),
|
||||
Text(formatDuration(_mediaPosition ?? Duration())),
|
||||
Spacer(),
|
||||
_AudioButton(
|
||||
icon: Icons.play_arrow, onTap: _play, visible: !_playing),
|
||||
_AudioButton(icon: Icons.pause, onTap: _pause, visible: _playing),
|
||||
_AudioButton(icon: Icons.stop, onTap: _stop, visible: _playing),
|
||||
Spacer(),
|
||||
_playing ? Container() : Text(formatDuration(_mediaDuration ?? Duration())),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _play() async {
|
||||
if (_player == null) {
|
||||
_player = AudioPlayer();
|
||||
|
||||
_player.onDurationChanged.listen((newDuration) {
|
||||
setState(() => _mediaDuration = newDuration);
|
||||
});
|
||||
|
||||
_player.onAudioPositionChanged.listen((newDuration) {
|
||||
setState(() => _mediaPosition = newDuration);
|
||||
});
|
||||
|
||||
_player.onPlayerStateChanged.listen((event) => setState(() {}));
|
||||
|
||||
_player.onSeekComplete.listen((event) => setState(() {}));
|
||||
}
|
||||
|
||||
if (_player.state != AudioPlayerState.PAUSED)
|
||||
_player.play(widget.file.absolute.path, isLocal: true);
|
||||
else
|
||||
_player.resume();
|
||||
}
|
||||
|
||||
void _pause() async {
|
||||
_player.pause();
|
||||
}
|
||||
|
||||
void _stop() {
|
||||
_player.stop();
|
||||
_player.seek(Duration());
|
||||
}
|
||||
}
|
||||
|
||||
class _AudioButton extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final void Function() onTap;
|
||||
final bool visible;
|
||||
|
||||
const _AudioButton({
|
||||
Key key,
|
||||
@required this.icon,
|
||||
@required this.onTap,
|
||||
@required this.visible,
|
||||
}) : assert(icon != null),
|
||||
assert(onTap != null),
|
||||
assert(visible != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!visible) return Container();
|
||||
|
||||
return IconButton(icon: Icon(icon, color: Colors.white), onPressed: onTap);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
/// @author Pierre Hubert
|
||||
import 'package:comunic/models/conversation_message.dart';
|
||||
import 'package:comunic/ui/widgets/network_image_widget.dart';
|
||||
import 'package:filesize/filesize.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
@ -60,6 +61,11 @@ class _ConversationFileWidgetState extends State<ConversationFileWidget> {
|
||||
Icon(file.icon, color: Colors.white),
|
||||
Spacer(),
|
||||
Text(file.name, textAlign: TextAlign.center),
|
||||
Spacer(),
|
||||
Text(
|
||||
filesize(file.size),
|
||||
style: TextStyle(fontSize: 10),
|
||||
),
|
||||
Spacer(flex: 2),
|
||||
],
|
||||
),
|
||||
|
@ -50,6 +50,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.1"
|
||||
clipboard:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: clipboard
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2+8"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -97,6 +97,9 @@ dependencies:
|
||||
# Format file size
|
||||
filesize: ^1.0.4
|
||||
|
||||
# Copy content to clipboard
|
||||
clipboard: ^0.1.2+8
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
Loading…
Reference in New Issue
Block a user