automatically update contact screen when delete/add friend

main
htylight 2023-08-12 18:31:37 +08:00
parent 5da249e4fc
commit 277edd7f0e
11 changed files with 52 additions and 53 deletions

View File

@ -25,11 +25,14 @@ class Contact extends ChangeNotifier {
List<String> friendGroups = []; List<String> friendGroups = [];
String defaultGroup = ''; String defaultGroup = '';
Map<String, GroupChatSetting> groupChats = {}; Map<String, GroupChatSetting> groupChats = {};
int friendCount = 0;
void init(Map json) { void init(Map json) {
defaultGroup = json['defaultGroup']; defaultGroup = json['defaultGroup'];
friendCount = 0;
json['friends'].forEach((key, value) { json['friends'].forEach((key, value) {
friendCount += 1;
friends[key] = FriendSetting.fromJson(value); friends[key] = FriendSetting.fromJson(value);
}); });
// json['groupChats'].forEach((key, value) { // json['groupChats'].forEach((key, value) {
@ -53,7 +56,8 @@ class Contact extends ChangeNotifier {
} }
void addFriend(String friendId, Map friendSetting) { void addFriend(String friendId, Map friendSetting) {
friends.addAll({friendId: FriendSetting.fromJson(friendSetting)}); friends[friendId] = FriendSetting.fromJson(friendSetting);
friendCount += 1;
notifyListeners(); notifyListeners();
} }
@ -67,6 +71,7 @@ class Contact extends ChangeNotifier {
void removeFriend(String friendId) { void removeFriend(String friendId) {
friends.remove(friendId); friends.remove(friendId);
friendCount -= 1;
notifyListeners(); notifyListeners();
} }
} }

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get_it_mixin/get_it_mixin.dart';
import 'package:together_mobile/models/contact_model.dart'; import 'package:together_mobile/models/contact_model.dart';
import 'package:together_mobile/models/init_get_it.dart';
import 'friend_tile.dart'; import 'friend_tile.dart';
class FriendGroup extends StatelessWidget { class FriendGroup extends StatelessWidget with GetItMixin {
const FriendGroup({ FriendGroup({
super.key, super.key,
required this.groupName, required this.groupName,
}); });
@ -15,26 +15,21 @@ class FriendGroup extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final friends = watchOnly((Contact contact) => contact.friends);
return ExpansionTile( return ExpansionTile(
title: Text(groupName), title: Text(groupName),
trailing: Text( trailing: Text(
getIt get<Contact>().filterGroupFriends(groupName).length.toString(),
.get<Contact>()
.filterGroupFriends(groupName)
.length
.toString(),
), ),
children: List.generate( children: List.generate(
getIt.get<Contact>().filterGroupFriends(groupName).length, get<Contact>().filterGroupFriends(groupName).length,
(index) => FriendTile( (index) => FriendTile(
key: ValueKey( key: ValueKey(
getIt.get<Contact>().friends.keys.toList()[index], friends.keys.toList()[index],
), ),
friendId: getIt friendId:
.get<Contact>() get<Contact>().filterGroupFriends(groupName).keys.toList()[index],
.filterGroupFriends(groupName)
.keys
.toList()[index],
), ),
), ),
); );

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:together_mobile/models/apply_list_model.dart'; import 'package:together_mobile/models/apply_list_model.dart';
import 'package:together_mobile/models/init_get_it.dart'; import 'package:together_mobile/models/init_get_it.dart';
@ -53,6 +54,14 @@ class _ApplyListScreenState extends State<ApplyListScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
leading: IconButton(
onPressed: () {
// Have to replace the default back button,
// because default back button use the old state
context.goNamed('Contact');
},
icon: const Icon(Icons.arrow_back),
),
centerTitle: true, centerTitle: true,
title: const Text('申请列表'), title: const Text('申请列表'),
), ),

View File

@ -1,5 +1,4 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:cherry_toast/cherry_toast.dart'; import 'package:cherry_toast/cherry_toast.dart';
@ -215,16 +214,6 @@ class _ApplyBottomSheetState extends State<ApplyBottomSheet> {
context.pop(); context.pop();
if (res['code'] == 10600) { if (res['code'] == 10600) {
// ignore: use_build_context_synchronously
CherryToast.success(
title: const Text(
'添加好友成功',
style: TextStyle(
color: kContentColorLight,
),
),
).show(context);
final accountProfile = {}; final accountProfile = {};
accountProfile.addAll(getIt.get<UserAccount>().toMap()); accountProfile.addAll(getIt.get<UserAccount>().toMap());
accountProfile.addAll(getIt.get<UserProfile>().toMap()); accountProfile.addAll(getIt.get<UserProfile>().toMap());
@ -243,6 +232,15 @@ class _ApplyBottomSheetState extends State<ApplyBottomSheet> {
widget.apply.applicant!, widget.apply.applicant!,
widget.accountProfile, widget.accountProfile,
); );
// ignore: use_build_context_synchronously
CherryToast.success(
title: const Text(
'添加好友成功',
style: TextStyle(
color: kContentColorLight,
),
),
).show(context);
widget.refreshCallback(); widget.refreshCallback();
} else { } else {
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously

View File

@ -30,16 +30,14 @@ class _ContactScreenState extends State<ContactScreen> with GetItStateMixin {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Map<String, FriendSetting> friends = watchOnly( // Seems like `watchOnly` cannot watch collecion type.
(Contact contact) => contact.friends, int friendCount = watchOnly(
); (Contact contact) => contact.friendCount,
List<String> friendGroups = watchOnly(
(Contact contact) => contact.friendGroups,
); );
int applyCount = watchOnly( int applyCount = watchOnly(
(ApplyList applyList) => applyList.count, (ApplyList applyList) => applyList.count,
); );
int friendCount = friends.length;
// Create a localkey, use to generate the custom scroll view, // Create a localkey, use to generate the custom scroll view,
// or there will be a error: "Duplicate GlobalKey detected in widget tree." // or there will be a error: "Duplicate GlobalKey detected in widget tree."
@ -169,12 +167,14 @@ class _ContactScreenState extends State<ContactScreen> with GetItStateMixin {
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {
if (_shows['friendGroups']!) { if (_shows['friendGroups']!) {
String groupName = get<Contact>().friendGroups[index];
return FriendGroup( return FriendGroup(
key: ValueKey(friendGroups[index]), key: ValueKey(groupName),
groupName: friendGroups[index], groupName: groupName,
); );
} else if (_shows['allFriends']!) { } else if (_shows['allFriends']!) {
String friendId = friends.keys.toList()[index]; String friendId =
get<Contact>().friends.keys.toList()[index];
// print(friends); // print(friends);
return FriendTile( return FriendTile(
key: ValueKey( key: ValueKey(
@ -187,7 +187,7 @@ class _ContactScreenState extends State<ContactScreen> with GetItStateMixin {
} }
}, },
childCount: _shows['friendGroups']! childCount: _shows['friendGroups']!
? friendGroups.length ? get<Contact>().friendGroups.length
: _shows['allFriends']! : _shows['allFriends']!
? friendCount ? friendCount
: get<Contact>().groupChats.length, : get<Contact>().groupChats.length,

View File

@ -4,8 +4,6 @@ import 'package:go_router/go_router.dart';
import 'package:cherry_toast/cherry_toast.dart'; import 'package:cherry_toast/cherry_toast.dart';
import 'package:together_mobile/common/constants.dart'; import 'package:together_mobile/common/constants.dart';
import 'package:together_mobile/models/contact_model.dart';
import 'package:together_mobile/models/init_get_it.dart';
class EditGroupBottomSheet extends StatefulWidget { class EditGroupBottomSheet extends StatefulWidget {
const EditGroupBottomSheet({ const EditGroupBottomSheet({

View File

@ -128,7 +128,7 @@ class _FriendGroupScreenState extends State<FriendGroupScreen> {
getIt.get<Contact>().friendGroups.length - _deletedOriginGroups.length; getIt.get<Contact>().friendGroups.length - _deletedOriginGroups.length;
setState(() { setState(() {
_deletedOriginGroups.addAll(List.filled(sub - 1, '')); _deletedOriginGroups.addAll(List.filled(sub, ''));
}); });
Map<String, dynamic> res = await manageGroups( Map<String, dynamic> res = await manageGroups(

View File

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:cherry_toast/cherry_toast.dart'; import 'package:cherry_toast/cherry_toast.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -10,8 +8,6 @@ import 'package:together_mobile/models/contact_model.dart';
import 'package:together_mobile/models/init_get_it.dart'; import 'package:together_mobile/models/init_get_it.dart';
import 'package:together_mobile/models/user_model.dart'; import 'package:together_mobile/models/user_model.dart';
import 'package:together_mobile/request/search_new.dart'; import 'package:together_mobile/request/search_new.dart';
import 'package:together_mobile/request/user_profile.dart';
import 'package:together_mobile/utils/app_dir.dart';
class SearchNewScreen extends StatefulWidget { class SearchNewScreen extends StatefulWidget {
const SearchNewScreen({super.key}); const SearchNewScreen({super.key});

View File

@ -73,13 +73,15 @@ class RowFloatingButtons extends StatelessWidget {
), ),
), ),
FloatingActionButton( FloatingActionButton(
onPressed: () { onPressed: () async {
try { try {
Hive.box<MessageT>('message_$contactId'); Hive.box<MessageT>('message_$contactId');
} catch (e) { } catch (e) {
Hive.openBox<MessageT>('message_$contactId'); // have to await it
await Hive.openBox<MessageT>('message_$contactId');
} }
// ignore: use_build_context_synchronously
context.goNamed( context.goNamed(
'Message', 'Message',
queryParameters: {'contactId': contactId}, queryParameters: {'contactId': contactId},

View File

@ -1,17 +1,15 @@
import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:cherry_toast/cherry_toast.dart'; import 'package:cherry_toast/cherry_toast.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:image_editor_plus/image_editor_plus.dart'; import 'package:image_editor_plus/image_editor_plus.dart';
import 'package:image_editor_plus/utils.dart'; import 'package:image_editor_plus/utils.dart';
import 'package:together_mobile/common/constants.dart'; import 'package:together_mobile/common/constants.dart';
import 'package:together_mobile/request/server.dart'; import 'package:together_mobile/request/server.dart';
import 'package:together_mobile/utils/app_dir.dart';
import 'package:together_mobile/models/init_get_it.dart'; import 'package:together_mobile/models/init_get_it.dart';
import 'package:together_mobile/models/user_model.dart'; import 'package:together_mobile/models/user_model.dart';
import 'package:together_mobile/request/user_profile.dart'; import 'package:together_mobile/request/user_profile.dart';

View File

@ -1,12 +1,10 @@
import 'dart:io'; import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:together_mobile/common/constants.dart'; import 'package:together_mobile/common/constants.dart';
import 'package:together_mobile/models/init_get_it.dart'; import 'package:together_mobile/models/init_get_it.dart';
import 'package:together_mobile/models/user_model.dart'; import 'package:together_mobile/models/user_model.dart';
import 'package:together_mobile/request/server.dart'; import 'package:together_mobile/request/server.dart';
import 'components/profile_card.dart'; import 'components/profile_card.dart';