mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-02-26 03:10:43 +01:00
chore: Add replies and hold to show
This commit is contained in:
parent
71a2ff5170
commit
010607112d
@ -2668,5 +2668,6 @@
|
|||||||
"whoCanSeeMyStories": "Who can see my stories?",
|
"whoCanSeeMyStories": "Who can see my stories?",
|
||||||
"unsubscribeStories": "Unsubscribe stories",
|
"unsubscribeStories": "Unsubscribe stories",
|
||||||
"thisUserHasNotPostedAnythingYet": "This user has not posted anything in their story yet",
|
"thisUserHasNotPostedAnythingYet": "This user has not posted anything in their story yet",
|
||||||
"yourStory": "Your story"
|
"yourStory": "Your story",
|
||||||
|
"replyHasBeenSent": "Reply has been sent"
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
@ -32,12 +33,60 @@ class StoryPageController extends State<StoryPage> {
|
|||||||
Timer? _progressTimer;
|
Timer? _progressTimer;
|
||||||
bool loadingMode = false;
|
bool loadingMode = false;
|
||||||
|
|
||||||
|
final TextEditingController replyController = TextEditingController();
|
||||||
|
final FocusNode replyFocus = FocusNode();
|
||||||
|
|
||||||
final List<Event> events = [];
|
final List<Event> events = [];
|
||||||
|
|
||||||
Timeline? timeline;
|
Timeline? timeline;
|
||||||
|
|
||||||
Event? get currentEvent => index < events.length ? events[index] : null;
|
Event? get currentEvent => index < events.length ? events[index] : null;
|
||||||
|
|
||||||
|
bool replyLoading = false;
|
||||||
|
|
||||||
|
void replyEmojiAction() async {
|
||||||
|
if (replyLoading) return;
|
||||||
|
hold();
|
||||||
|
await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => EmojiPicker(
|
||||||
|
onEmojiSelected: (c, e) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
replyAction(e.emoji);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
unhold();
|
||||||
|
}
|
||||||
|
|
||||||
|
void replyAction([String? message]) async {
|
||||||
|
message ??= replyController.text;
|
||||||
|
setState(() {
|
||||||
|
replyLoading = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
final client = Matrix.of(context).client;
|
||||||
|
final roomId = await client.startDirectChat(currentEvent!.senderId);
|
||||||
|
await client.getRoomById(roomId)!.sendTextEvent(
|
||||||
|
message,
|
||||||
|
inReplyTo: currentEvent!,
|
||||||
|
);
|
||||||
|
replyController.clear();
|
||||||
|
replyFocus.unfocus();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(L10n.of(context)!.replyHasBeenSent),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().w('Unable to reply to story', e, s);
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
replyLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<User> get currentSeenByUsers {
|
List<User> get currentSeenByUsers {
|
||||||
final timeline = this.timeline;
|
final timeline = this.timeline;
|
||||||
final currentEvent = this.currentEvent;
|
final currentEvent = this.currentEvent;
|
||||||
@ -88,8 +137,6 @@ class StoryPageController extends State<StoryPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final TextEditingController replyController = TextEditingController();
|
|
||||||
|
|
||||||
static const Duration _step = Duration(milliseconds: 50);
|
static const Duration _step = Duration(milliseconds: 50);
|
||||||
static const Duration maxProgress = Duration(seconds: 5);
|
static const Duration maxProgress = Duration(seconds: 5);
|
||||||
|
|
||||||
@ -145,13 +192,19 @@ class StoryPageController extends State<StoryPage> {
|
|||||||
|
|
||||||
DateTime _holdedAt = DateTime.fromMicrosecondsSinceEpoch(0);
|
DateTime _holdedAt = DateTime.fromMicrosecondsSinceEpoch(0);
|
||||||
|
|
||||||
void hold(_) {
|
bool isHold = false;
|
||||||
|
|
||||||
|
void hold([_]) {
|
||||||
_holdedAt = DateTime.now();
|
_holdedAt = DateTime.now();
|
||||||
if (loadingMode) return;
|
if (loadingMode) return;
|
||||||
_progressTimer?.cancel();
|
_progressTimer?.cancel();
|
||||||
|
setState(() {
|
||||||
|
isHold = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void unhold([_]) {
|
void unhold([_]) {
|
||||||
|
isHold = false;
|
||||||
if (DateTime.now().millisecondsSinceEpoch -
|
if (DateTime.now().millisecondsSinceEpoch -
|
||||||
_holdedAt.millisecondsSinceEpoch <
|
_holdedAt.millisecondsSinceEpoch <
|
||||||
200) {
|
200) {
|
||||||
|
@ -26,7 +26,14 @@ class StoryView extends StatelessWidget {
|
|||||||
backgroundColor: Colors.blueGrey,
|
backgroundColor: Colors.blueGrey,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
titleSpacing: 0,
|
titleSpacing: 0,
|
||||||
title: ListTile(
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.close),
|
||||||
|
onPressed: Navigator.of(context).pop,
|
||||||
|
),
|
||||||
|
title: AnimatedOpacity(
|
||||||
|
duration: const Duration(seconds: 1),
|
||||||
|
opacity: controller.isHold ? 0 : 1,
|
||||||
|
child: ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
title: Text(
|
title: Text(
|
||||||
controller.title,
|
controller.title,
|
||||||
@ -61,6 +68,7 @@ class StoryView extends StatelessWidget {
|
|||||||
name: controller.title,
|
name: controller.title,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||||
iconTheme: const IconThemeData(color: Colors.white),
|
iconTheme: const IconThemeData(color: Colors.white),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@ -199,6 +207,9 @@ class StoryView extends StatelessWidget {
|
|||||||
top: 4,
|
top: 4,
|
||||||
left: 4,
|
left: 4,
|
||||||
right: 4,
|
right: 4,
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
duration: const Duration(seconds: 1),
|
||||||
|
opacity: controller.isHold ? 0 : 1,
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -228,6 +239,44 @@ class StoryView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
if (!controller.isOwnStory && currentEvent != null)
|
||||||
|
Positioned(
|
||||||
|
bottom: 16,
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
duration: const Duration(seconds: 1),
|
||||||
|
opacity: controller.isHold ? 0 : 1,
|
||||||
|
child: SafeArea(
|
||||||
|
child: TextField(
|
||||||
|
onTap: controller.hold,
|
||||||
|
onEditingComplete: controller.unhold,
|
||||||
|
focusNode: controller.replyFocus,
|
||||||
|
controller: controller.replyController,
|
||||||
|
minLines: 1,
|
||||||
|
maxLines: 7,
|
||||||
|
onSubmitted: controller.replyAction,
|
||||||
|
textInputAction: TextInputAction.newline,
|
||||||
|
readOnly: controller.replyLoading,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: L10n.of(context)!.reply,
|
||||||
|
prefixIcon: IconButton(
|
||||||
|
onPressed: controller.replyEmojiAction,
|
||||||
|
icon: const Icon(Icons.emoji_emotions_outlined),
|
||||||
|
),
|
||||||
|
suffixIcon: controller.replyLoading
|
||||||
|
? const CircularProgressIndicator.adaptive(
|
||||||
|
strokeWidth: 2)
|
||||||
|
: IconButton(
|
||||||
|
onPressed: controller.replyAction,
|
||||||
|
icon: const Icon(Icons.send_outlined),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
if (controller.isOwnStory &&
|
if (controller.isOwnStory &&
|
||||||
controller.currentSeenByUsers.isNotEmpty)
|
controller.currentSeenByUsers.isNotEmpty)
|
||||||
Positioned(
|
Positioned(
|
||||||
@ -248,7 +297,8 @@ class StoryView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user