replace conversations page with conversations popup

This commit is contained in:
zoe 2022-10-01 13:00:00 +02:00
parent 7933caa158
commit 756deea82c
2 changed files with 235 additions and 7 deletions

View File

@ -0,0 +1,208 @@
import 'package:flutter/material.dart';
import 'package:localization/localization.dart';
import 'package:loris/business_logic/chat/chat.dart';
import 'package:loris/dialogues/full_post_view.dart';
import 'package:loris/dialogues/profile_view.dart';
import 'package:loris/partials/loadingbox.dart';
import 'package:loris/partials/post.dart';
import 'package:loris/partials/post_text_renderer.dart';
import 'package:loris/themes/themes.dart' as themes;
import 'package:loris/global.dart' as global;
class Chat extends StatefulWidget {
const Chat({super.key});
@override
State<Chat> createState() => _ChatState();
}
class _ChatState extends State<Chat> {
List<ConversationModel> conversations = [];
// map that stores max ids for each identity
Map<String, String?> maxIds = {};
final scrollController = ScrollController();
bool loading = false;
// loads more conversations and properly stores all ids
Future<void> updateConversations() async {
if (loading) return;
loading = true;
final models = await getAllConversationModels(maxIds);
if (!mounted) return;
setState(() {
conversations.addAll(models.models);
maxIds = models.maxIds;
});
loading = false;
}
@override
void initState() {
updateConversations();
scrollController.addListener(() {
if (scrollController.position.maxScrollExtent - scrollController.offset <
MediaQuery.of(context).size.height) {
updateConversations();
}
});
super.initState();
}
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SimpleDialog(
contentPadding: const EdgeInsets.all(0),
children: [
Container(
constraints: global.getConstraints(context),
width: global.getWidth(context),
height: MediaQuery.of(context).size.height * 2 / 3,
child: Column(
children: [
Expanded(
child: ListView.separated(
controller: scrollController,
shrinkWrap: true,
itemBuilder: ((context, index) {
if (index >= conversations.length) {
return const LoadingBox();
}
return ConversationButton(
model: conversations[index],
onTap: () {
showDialog(
barrierColor: Colors.transparent,
context: context,
builder: (context) {
final con = conversations[index];
if (con.lastStatus != null) {
return FullPostView(
originPostModel: con.lastStatus!);
}
return ProfileView(model: con.accounts.first);
});
},
);
}),
separatorBuilder: (context, index) => const Divider(
height: themes.defaultSeperatorHeight,
color: Colors.transparent,
),
itemCount: conversations.length + 1),
),
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Theme.of(context).colorScheme.primary,
width: 2))),
),
],
),
),
],
);
}
}
class ConversationButton extends StatelessWidget {
const ConversationButton({
super.key,
required this.model,
required this.onTap,
});
final ConversationModel model;
final void Function() onTap;
@override
Widget build(BuildContext context) {
final List<Widget> people = [];
for (var p in model.accounts) {
people.add(DisplayName(account: p));
}
return Align(
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(themes.defaultRadius),
color: Theme.of(context).colorScheme.surface,
),
margin: const EdgeInsets.fromLTRB(themes.defaultSeperatorHeight * 2, 0,
themes.defaultSeperatorHeight * 2, 0),
width: global.getWidth(context),
constraints: global.getConstraints(context),
child: Material(
borderOnForeground: true,
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(themes.defaultRadius),
side: BorderSide(
color: Theme.of(context).colorScheme.secondary, width: 2),
),
child: InkWell(
borderRadius: const BorderRadius.all(themes.defaultRadius),
onTap: onTap,
child: Padding(
padding: themes.defaultInsideMargins,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: people +
[
Divider(
color: Theme.of(context).hintColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton.icon(
onPressed: onTap,
icon: const Icon(Icons.open_in_full),
label: Text("show".i18n())),
if (model.unread) const UnreadIndicator(),
],
),
Wrap(
alignment: WrapAlignment.spaceBetween,
children: [
SelectableText(model.getAccountsString()),
SelectableText(
"${"you-are".i18n()} ${model.identity}"),
],
),
if (model.lastStatus != null)
PostTextRenderer(
input: model.lastStatus!.content,
identityName: model.identity,
),
],
),
),
),
),
),
);
}
}
class UnreadIndicator extends StatefulWidget {
const UnreadIndicator({super.key});
@override
State<UnreadIndicator> createState() => _UnreadIndicatorState();
}
class _UnreadIndicatorState extends State<UnreadIndicator> {
@override
Widget build(BuildContext context) {
return Row(
children: [
const Icon(Icons.mark_unread_chat_alt),
SelectableText("unread".i18n())
],
);
}
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:localization/localization.dart';
import 'package:loris/dialogues/conversations.dart';
import 'package:loris/dialogues/followreqs.dart';
import '../../global.dart' as global;
@ -15,6 +16,7 @@ class AccountSettings extends StatelessWidget {
}
children.add(const NewAccountButton());
children.add(const FollowreqButton());
children.add(const ConversationButton());
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: children,
@ -82,12 +84,30 @@ class FollowreqButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TextButton.icon(
onPressed: (() => showDialog(
barrierColor: Colors.transparent,
context: context,
builder: (context) => const FollowReqScreen(),
)),
icon: const Icon(Icons.check),
label: Text("follow-requests".i18n()));
onPressed: (() => showDialog(
barrierColor: Colors.transparent,
context: context,
builder: (context) => const FollowReqScreen(),
)),
icon: const Icon(Icons.check),
label: Text(
"follow-requests".i18n(),
),
);
}
}
class ConversationButton extends StatelessWidget {
const ConversationButton({super.key});
@override
Widget build(BuildContext context) {
return TextButton.icon(
onPressed: () => showDialog(
context: context,
builder: (context) => Chat(),
),
icon: const Icon(Icons.chat),
label: Text("chat".i18n()));
}
}