♻️ Refactored friend module

This commit is contained in:
LittleSheep 2024-07-24 01:17:41 +08:00
parent 39c8597428
commit 8366bda846
18 changed files with 250 additions and 272 deletions

View File

@ -11,11 +11,11 @@ import 'package:solian/platform.dart';
import 'package:solian/providers/websocket.dart'; import 'package:solian/providers/websocket.dart';
import 'package:solian/providers/auth.dart'; import 'package:solian/providers/auth.dart';
import 'package:solian/providers/content/attachment.dart'; import 'package:solian/providers/content/attachment.dart';
import 'package:solian/providers/content/call.dart'; import 'package:solian/providers/call.dart';
import 'package:solian/providers/content/channel.dart'; import 'package:solian/providers/content/channel.dart';
import 'package:solian/providers/content/posts.dart'; import 'package:solian/providers/content/posts.dart';
import 'package:solian/providers/content/realm.dart'; import 'package:solian/providers/content/realm.dart';
import 'package:solian/providers/friend.dart'; import 'package:solian/providers/relation.dart';
import 'package:solian/providers/account_status.dart'; import 'package:solian/providers/account_status.dart';
import 'package:solian/router.dart'; import 'package:solian/router.dart';
import 'package:solian/shells/system_shell.dart'; import 'package:solian/shells/system_shell.dart';
@ -96,7 +96,7 @@ class SolianApp extends StatelessWidget {
void _initializeProviders(BuildContext context) async { void _initializeProviders(BuildContext context) async {
Get.lazyPut(() => AuthProvider()); Get.lazyPut(() => AuthProvider());
Get.lazyPut(() => FriendProvider()); Get.lazyPut(() => RelationshipProvider());
Get.lazyPut(() => PostProvider()); Get.lazyPut(() => PostProvider());
Get.lazyPut(() => AttachmentProvider()); Get.lazyPut(() => AttachmentProvider());
Get.lazyPut(() => WebSocketProvider()); Get.lazyPut(() => WebSocketProvider());

View File

@ -1,38 +1,35 @@
import 'package:solian/models/account.dart'; import 'package:solian/models/account.dart';
class Friendship { class Relationship {
int id; int id;
DateTime createdAt; DateTime createdAt;
DateTime updatedAt; DateTime updatedAt;
DateTime? deletedAt; DateTime? deletedAt;
int accountId; int accountId;
int relatedId; int relatedId;
int? blockedBy;
Account account; Account account;
Account related; Account related;
int status; int status;
Friendship({ Relationship({
required this.id, required this.id,
required this.createdAt, required this.createdAt,
required this.updatedAt, required this.updatedAt,
required this.deletedAt, required this.deletedAt,
required this.accountId, required this.accountId,
required this.relatedId, required this.relatedId,
required this.blockedBy,
required this.account, required this.account,
required this.related, required this.related,
required this.status, required this.status,
}); });
factory Friendship.fromJson(Map<String, dynamic> json) => Friendship( factory Relationship.fromJson(Map<String, dynamic> json) => Relationship(
id: json['id'], id: json['id'],
createdAt: DateTime.parse(json['created_at']), createdAt: DateTime.parse(json['created_at']),
updatedAt: DateTime.parse(json['updated_at']), updatedAt: DateTime.parse(json['updated_at']),
deletedAt: json['deleted_at'], deletedAt: json['deleted_at'],
accountId: json['account_id'], accountId: json['account_id'],
relatedId: json['related_id'], relatedId: json['related_id'],
blockedBy: json['blocked_by'],
account: Account.fromJson(json['account']), account: Account.fromJson(json['account']),
related: Account.fromJson(json['related']), related: Account.fromJson(json['related']),
status: json['status'], status: json['status'],
@ -45,7 +42,6 @@ class Friendship {
'deleted_at': deletedAt, 'deleted_at': deletedAt,
'account_id': accountId, 'account_id': accountId,
'related_id': relatedId, 'related_id': relatedId,
'blocked_by': blockedBy,
'account': account.toJson(), 'account': account.toJson(),
'related': related.toJson(), 'related': related.toJson(),
'status': status, 'status': status,

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/models/channel.dart'; import 'package:solian/models/channel.dart';
import 'package:solian/providers/auth.dart'; import 'package:solian/providers/auth.dart';
import 'package:solian/widgets/account/friend_select.dart'; import 'package:solian/widgets/account/relative_select.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
class ChannelProvider extends GetxController { class ChannelProvider extends GetxController {
@ -123,7 +123,7 @@ class ChannelProvider extends GetxController {
final related = await showModalBottomSheet( final related = await showModalBottomSheet(
useRootNavigator: true, useRootNavigator: true,
context: context, context: context,
builder: (context) => FriendSelect( builder: (context) => RelativeSelector(
title: 'channelOrganizeDirectHint'.tr, title: 'channelOrganizeDirectHint'.tr,
), ),
); );

View File

@ -1,43 +0,0 @@
import 'package:get/get.dart';
import 'package:solian/models/friendship.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart';
class FriendProvider extends GetConnect {
@override
void onInit() {
final AuthProvider auth = Get.find();
httpClient.baseUrl = ServiceFinder.buildUrl('auth', null);
httpClient.addAuthenticator(auth.requestAuthenticator);
}
Future<Response> listFriendship() => get('/users/me/friends');
Future<Response> listFriendshipWithStatus(int status) =>
get('/users/me/friends?status=$status');
Future<Response> createFriendship(String username) async {
final resp = await post('/users/me/friends?related=$username', {});
if (resp.statusCode != 200) {
throw Exception(resp.bodyString);
}
return resp;
}
Future<Response> updateFriendship(Friendship relationship, int status) async {
final AuthProvider auth = Get.find();
final prof = await auth.getProfile();
final otherside = relationship.getOtherside(prof.body['id']);
final resp = await put('/users/me/friends/${otherside.id}', {
'status': status,
});
if (resp.statusCode != 200) {
throw Exception(resp.bodyString);
}
return resp;
}
}

View File

@ -0,0 +1,57 @@
import 'package:get/get.dart';
import 'package:solian/models/relations.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart';
class RelationshipProvider extends GetConnect {
@override
void onInit() {
final AuthProvider auth = Get.find();
httpClient.baseUrl = ServiceFinder.buildUrl('auth', null);
httpClient.addAuthenticator(auth.requestAuthenticator);
}
Future<Response> listRelation() => get('/users/me/relations');
Future<Response> listRelationWithStatus(int status) =>
get('/users/me/relations?status=$status');
Future<Response> makeFriend(String username) async {
final resp = await post('/users/me/relations?related=$username', {});
if (resp.statusCode != 200) {
throw Exception(resp.bodyString);
}
return resp;
}
Future<Response> handleRelation(
Relationship relationship, bool doAccept) async {
final AuthProvider auth = Get.find();
final client = auth.configureClient('auth');
final resp = await client.post(
'/users/me/relations/${relationship.relatedId}/${doAccept ? 'accept' : 'decline'}',
{},
);
if (resp.statusCode != 200) {
throw Exception(resp.bodyString);
}
return resp;
}
Future<Response> editRelation(Relationship relationship, int status) async {
final AuthProvider auth = Get.find();
final client = auth.configureClient('auth');
final resp =
await client.patch('/users/me/relations/${relationship.relatedId}', {
'status': status,
});
if (resp.statusCode != 200) {
throw Exception(resp.bodyString);
}
return resp;
}
}

View File

@ -191,10 +191,7 @@ abstract class AppRouter {
GoRoute( GoRoute(
path: '/account/friend', path: '/account/friend',
name: 'accountFriend', name: 'accountFriend',
builder: (context, state) => TitleShell( builder: (context, state) => const FriendScreen(),
state: state,
child: const FriendScreen(),
),
), ),
GoRoute( GoRoute(
path: '/account/personalize', path: '/account/personalize',

View File

@ -2,10 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/exts.dart'; import 'package:solian/exts.dart';
import 'package:solian/models/friendship.dart'; import 'package:solian/models/relations.dart';
import 'package:solian/providers/auth.dart'; import 'package:solian/providers/relation.dart';
import 'package:solian/providers/friend.dart'; import 'package:solian/widgets/account/relative_list.dart';
import 'package:solian/widgets/account/friend_list.dart';
class FriendScreen extends StatefulWidget { class FriendScreen extends StatefulWidget {
const FriendScreen({super.key}); const FriendScreen({super.key});
@ -14,71 +13,38 @@ class FriendScreen extends StatefulWidget {
State<FriendScreen> createState() => _FriendScreenState(); State<FriendScreen> createState() => _FriendScreenState();
} }
class _FriendScreenState extends State<FriendScreen> { class _FriendScreenState extends State<FriendScreen>
with SingleTickerProviderStateMixin {
late final TabController _tabController;
bool _isBusy = false; bool _isBusy = false;
int? _accountId;
List<Friendship> _friendships = List.empty(); List<Relationship> _relations = List.empty();
List<Friendship> filterWithStatus(int status) { List<Relationship> filterByStatus(int status) {
return _friendships.where((x) => x.status == status).toList(); return _relations.where((x) => x.status == status).toList();
} }
Future<void> getFriendship() async { Future<void> loadRelations() async {
setState(() => _isBusy = true); setState(() => _isBusy = true);
final FriendProvider provider = Get.find(); final RelationshipProvider provider = Get.find();
final resp = await provider.listFriendship(); final resp = await provider.listRelation();
setState(() { setState(() {
_friendships = resp.body _relations = resp.body
.map((e) => Friendship.fromJson(e)) .map((e) => Relationship.fromJson(e))
.toList() .toList()
.cast<Friendship>(); .cast<Relationship>();
_isBusy = false; _isBusy = false;
}); });
} }
void showScopedListPopup(String title, int status) {
showModalBottomSheet(
useRootNavigator: true,
isScrollControlled: true,
context: context,
builder: (context) {
return SizedBox(
height: MediaQuery.of(context).size.height * 0.85,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.headlineSmall,
).paddingOnly(left: 24, right: 24, top: 32, bottom: 16),
Expanded(
child: CustomScrollView(
slivers: [
SliverFriendList(
accountId: _accountId!,
items: filterWithStatus(status),
onUpdate: () {
getFriendship();
},
),
],
),
),
],
),
);
},
);
}
void promptAddFriend() async { void promptAddFriend() async {
final FriendProvider provider = Get.find(); final RelationshipProvider provider = Get.find();
final controller = TextEditingController(); final controller = TextEditingController();
final input = await showDialog( final input = await showDialog<String?>(
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
@ -125,7 +91,7 @@ class _FriendScreenState extends State<FriendScreen> {
try { try {
setState(() => _isBusy = true); setState(() => _isBusy = true);
await provider.createFriendship(input); await provider.makeFriend(input);
} catch (e) { } catch (e) {
context.showErrorDialog(e); context.showErrorDialog(e);
} finally { } finally {
@ -135,12 +101,14 @@ class _FriendScreenState extends State<FriendScreen> {
@override @override
void initState() { void initState() {
Get.find<AuthProvider>().getProfile().then((value) {
_accountId = value.body['id'];
});
super.initState(); super.initState();
_tabController = TabController(length: 3, vsync: this);
Future.delayed(Duration.zero, () => getFriendship()); loadRelations().then((_) {
if (filterByStatus(0).isEmpty) {
_tabController.animateTo(1);
}
});
} }
@override @override
@ -148,64 +116,71 @@ class _FriendScreenState extends State<FriendScreen> {
return Material( return Material(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
child: Scaffold( child: Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text('accountFriend'.tr),
bottom: TabBar(
controller: _tabController,
tabs: const [
Tab(icon: Icon(Icons.call_received)),
Tab(icon: Icon(Icons.people)),
Tab(icon: Icon(Icons.call_made)),
],
),
),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add), child: const Icon(Icons.add),
onPressed: () => promptAddFriend(), onPressed: () => promptAddFriend(),
), ),
body: RefreshIndicator( body: TabBarView(
onRefresh: () => getFriendship(), controller: _tabController,
child: CustomScrollView( children: [
slivers: [ RefreshIndicator(
if (_isBusy) onRefresh: () => loadRelations(),
SliverToBoxAdapter( child: CustomScrollView(
child: const LinearProgressIndicator().animate().scaleX(), slivers: [
), if (_isBusy)
SliverToBoxAdapter( SliverToBoxAdapter(
child: ListTile( child: const LinearProgressIndicator().animate().scaleX(),
tileColor: Theme.of(context).colorScheme.surfaceContainerLow, ),
contentPadding: const EdgeInsets.symmetric(horizontal: 20), SilverRelativeList(
leading: const Icon(Icons.person_add), items: filterByStatus(0),
trailing: const Icon(Icons.chevron_right), onUpdate: () => loadRelations(),
title: Text(
'${'accountFriendPending'.tr} (${filterWithStatus(0).length})',
), ),
onTap: () => ],
showScopedListPopup('accountFriendPending'.tr, 0),
),
), ),
SliverToBoxAdapter( ),
child: ListTile( RefreshIndicator(
tileColor: Theme.of(context).colorScheme.surfaceContainerLow, onRefresh: () => loadRelations(),
contentPadding: const EdgeInsets.symmetric(horizontal: 20), child: CustomScrollView(
leading: const Icon(Icons.block), slivers: [
trailing: const Icon(Icons.chevron_right), if (_isBusy)
title: Text( SliverToBoxAdapter(
'${'accountFriendBlocked'.tr} (${filterWithStatus(2).length})', child: const LinearProgressIndicator().animate().scaleX(),
),
SilverRelativeList(
items: filterByStatus(1),
onUpdate: () => loadRelations(),
), ),
onTap: () => ],
showScopedListPopup('accountFriendBlocked'.tr, 2),
),
), ),
if (_accountId != null) ),
SliverFriendList( RefreshIndicator(
accountId: _accountId!, onRefresh: () => loadRelations(),
items: filterWithStatus(1), child: CustomScrollView(
onUpdate: () { slivers: [
getFriendship(); if (_isBusy)
}, SliverToBoxAdapter(
), child: const LinearProgressIndicator().animate().scaleX(),
const SliverToBoxAdapter( ),
child: Divider(thickness: 0.3, height: 0.3), SilverRelativeList(
items: filterByStatus(3),
onUpdate: () => loadRelations(),
),
],
), ),
SliverToBoxAdapter( ),
child: Text( ],
'accountFriendListHint'.tr,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodySmall,
).paddingOnly(top: 16, bottom: 32),
),
],
),
), ),
), ),
); );

View File

@ -3,7 +3,7 @@ import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/providers/content/call.dart'; import 'package:solian/providers/call.dart';
import 'package:solian/theme.dart'; import 'package:solian/theme.dart';
import 'package:solian/widgets/app_bar_leading.dart'; import 'package:solian/widgets/app_bar_leading.dart';
import 'package:solian/widgets/chat/call/call_controls.dart'; import 'package:solian/widgets/chat/call/call_controls.dart';

View File

@ -11,7 +11,7 @@ import 'package:solian/models/channel.dart';
import 'package:solian/models/event.dart'; import 'package:solian/models/event.dart';
import 'package:solian/models/packet.dart'; import 'package:solian/models/packet.dart';
import 'package:solian/providers/auth.dart'; import 'package:solian/providers/auth.dart';
import 'package:solian/providers/content/call.dart'; import 'package:solian/providers/call.dart';
import 'package:solian/providers/content/channel.dart'; import 'package:solian/providers/content/channel.dart';
import 'package:solian/providers/websocket.dart'; import 'package:solian/providers/websocket.dart';
import 'package:solian/router.dart'; import 'package:solian/router.dart';

View File

@ -1,87 +0,0 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/models/friendship.dart';
import 'package:solian/providers/friend.dart';
import 'package:solian/widgets/account/account_avatar.dart';
import 'package:solian/widgets/account/account_profile_popup.dart';
class SliverFriendList extends StatelessWidget {
final int accountId;
final List<Friendship> items;
final Function onUpdate;
const SliverFriendList({
super.key,
required this.accountId,
required this.items,
required this.onUpdate,
});
DismissDirection getDismissDirection(Friendship relation) {
if (relation.status == 2) return DismissDirection.endToStart;
if (relation.status == 1) return DismissDirection.startToEnd;
if (relation.status == 0 && relation.relatedId != accountId) {
return DismissDirection.startToEnd;
}
return DismissDirection.horizontal;
}
Widget buildItem(context, index) {
final element = items[index];
final otherside = element.getOtherside(accountId);
final randomId = DateTime.now().microsecondsSinceEpoch >> 10;
return Dismissible(
key: Key(randomId.toString()),
background: Container(
color: Colors.red,
padding: const EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.centerLeft,
child: const Icon(Icons.close, color: Colors.white),
),
secondaryBackground: Container(
color: Colors.green,
padding: const EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.centerRight,
child: const Icon(Icons.check, color: Colors.white),
),
direction: getDismissDirection(element),
child: ListTile(
title: Text(otherside.nick),
subtitle: Text(otherside.name),
leading: GestureDetector(
child: AccountAvatar(content: otherside.avatar),
onTap: () {
showModalBottomSheet(
useRootNavigator: true,
isScrollControlled: true,
backgroundColor: Theme.of(context).colorScheme.surface,
context: context,
builder: (context) => AccountProfilePopup(
account: otherside,
),
);
},
),
),
onDismissed: (direction) {
final FriendProvider provider = Get.find();
if (direction == DismissDirection.startToEnd) {
provider.updateFriendship(element, 2).then((_) => onUpdate());
}
if (direction == DismissDirection.endToStart) {
provider.updateFriendship(element, 1).then((_) => onUpdate());
}
},
);
}
@override
Widget build(BuildContext context) {
return SliverList.builder(
itemCount: items.length,
itemBuilder: (context, idx) => buildItem(context, idx),
);
}
}

View File

@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/models/relations.dart';
import 'package:solian/providers/relation.dart';
import 'package:solian/widgets/account/account_avatar.dart';
import 'package:solian/widgets/account/account_profile_popup.dart';
class SilverRelativeList extends StatelessWidget {
final List<Relationship> items;
final Function onUpdate;
final bool isHandleable;
const SilverRelativeList({
super.key,
required this.items,
required this.onUpdate,
this.isHandleable = true,
});
Widget buildItem(context, index) {
final element = items[index];
return ListTile(
title: Text(element.related.nick),
subtitle: Text(element.related.name),
leading: GestureDetector(
child: AccountAvatar(content: element.related.avatar),
onTap: () {
showModalBottomSheet(
useRootNavigator: true,
isScrollControlled: true,
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
context: context,
builder: (context) =>
AccountProfilePopup(
account: element.related,
),
);
},
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
if(element.status != 1 && element.status != 3)
IconButton(
icon: const Icon(Icons.check),
onPressed: () {
final RelationshipProvider provider = Get.find();
if (element.status == 0) {
provider.handleRelation(element, true).then((_) => onUpdate());
} else {
provider.editRelation(element, 1).then((_) => onUpdate());
}
},
),
if(element.status != 2 && element.status != 3)
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
final RelationshipProvider provider = Get.find();
if (element.status == 0) {
provider.handleRelation(element, false).then((_) => onUpdate());
} else {
provider.editRelation(element, 2).then((_) => onUpdate());
}
},
),
],
),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
);
}
@override
Widget build(BuildContext context) {
return SliverList.builder(
itemCount: items.length,
itemBuilder: (context, idx) => buildItem(context, idx),
);
}
}

View File

@ -1,39 +1,39 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/models/account.dart'; import 'package:solian/models/account.dart';
import 'package:solian/models/friendship.dart'; import 'package:solian/models/relations.dart';
import 'package:solian/providers/auth.dart'; import 'package:solian/providers/auth.dart';
import 'package:solian/providers/friend.dart'; import 'package:solian/providers/relation.dart';
import 'package:solian/widgets/account/account_avatar.dart'; import 'package:solian/widgets/account/account_avatar.dart';
class FriendSelect extends StatefulWidget { class RelativeSelector extends StatefulWidget {
final String title; final String title;
final Widget? Function(Account item)? trailingBuilder; final Widget? Function(Account item)? trailingBuilder;
const FriendSelect({super.key, required this.title, this.trailingBuilder}); const RelativeSelector({super.key, required this.title, this.trailingBuilder});
@override @override
State<FriendSelect> createState() => _FriendSelectState(); State<RelativeSelector> createState() => _RelativeSelectorState();
} }
class _FriendSelectState extends State<FriendSelect> { class _RelativeSelectorState extends State<RelativeSelector> {
int _accountId = 0; int _accountId = 0;
final List<Friendship> _friends = List.empty(growable: true); final List<Relationship> _friends = List.empty(growable: true);
getFriends() async { getFriends() async {
final AuthProvider auth = Get.find(); final AuthProvider auth = Get.find();
final prof = await auth.getProfile(); final prof = await auth.getProfile();
_accountId = prof.body['id']; _accountId = prof.body['id'];
final FriendProvider provider = Get.find(); final RelationshipProvider provider = Get.find();
final resp = await provider.listFriendshipWithStatus(1); final resp = await provider.listRelationWithStatus(1);
setState(() { setState(() {
_friends.addAll(resp.body _friends.addAll(resp.body
.map((e) => Friendship.fromJson(e)) .map((e) => Relationship.fromJson(e))
.toList() .toList()
.cast<Friendship>()); .cast<Relationship>());
}); });
} }

View File

@ -7,7 +7,7 @@ import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart'; import 'package:solian/services.dart';
import 'package:solian/widgets/account/account_avatar.dart'; import 'package:solian/widgets/account/account_avatar.dart';
import 'package:solian/widgets/account/account_profile_popup.dart'; import 'package:solian/widgets/account/account_profile_popup.dart';
import 'package:solian/widgets/account/friend_select.dart'; import 'package:solian/widgets/account/relative_select.dart';
class ChannelMemberListPopup extends StatefulWidget { class ChannelMemberListPopup extends StatefulWidget {
final Channel channel; final Channel channel;
@ -62,7 +62,7 @@ class _ChannelMemberListPopupState extends State<ChannelMemberListPopup> {
final input = await showModalBottomSheet( final input = await showModalBottomSheet(
context: context, context: context,
builder: (context) { builder: (context) {
return FriendSelect(title: 'channelMembersAdd'.tr); return RelativeSelector(title: 'channelMembersAdd'.tr);
}, },
); );
if (input == null) return; if (input == null) return;

View File

@ -6,7 +6,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:livekit_client/livekit_client.dart'; import 'package:livekit_client/livekit_client.dart';
import 'package:solian/exts.dart'; import 'package:solian/exts.dart';
import 'package:solian/providers/content/call.dart'; import 'package:solian/providers/call.dart';
class ControlsWidget extends StatefulWidget { class ControlsWidget extends StatefulWidget {
final Room room; final Room room;

View File

@ -6,7 +6,7 @@ import 'package:solian/exts.dart';
import 'package:solian/models/call.dart'; import 'package:solian/models/call.dart';
import 'package:solian/models/channel.dart'; import 'package:solian/models/channel.dart';
import 'package:solian/providers/auth.dart'; import 'package:solian/providers/auth.dart';
import 'package:solian/providers/content/call.dart'; import 'package:solian/providers/call.dart';
class ChatCallPrejoinPopup extends StatefulWidget { class ChatCallPrejoinPopup extends StatefulWidget {
final Call ongoingCall; final Call ongoingCall;

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/providers/content/call.dart'; import 'package:solian/providers/call.dart';
class ChatCallCurrentIndicator extends StatelessWidget { class ChatCallCurrentIndicator extends StatelessWidget {
const ChatCallCurrentIndicator({super.key}); const ChatCallCurrentIndicator({super.key});

View File

@ -7,7 +7,7 @@ import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart'; import 'package:solian/services.dart';
import 'package:solian/widgets/account/account_avatar.dart'; import 'package:solian/widgets/account/account_avatar.dart';
import 'package:solian/widgets/account/account_profile_popup.dart'; import 'package:solian/widgets/account/account_profile_popup.dart';
import 'package:solian/widgets/account/friend_select.dart'; import 'package:solian/widgets/account/relative_select.dart';
class RealmMemberListPopup extends StatefulWidget { class RealmMemberListPopup extends StatefulWidget {
final Realm realm; final Realm realm;
@ -59,7 +59,7 @@ class _RealmMemberListPopupState extends State<RealmMemberListPopup> {
final input = await showModalBottomSheet( final input = await showModalBottomSheet(
context: context, context: context,
builder: (context) { builder: (context) {
return FriendSelect(title: 'channelMembersAdd'.tr); return RelativeSelector(title: 'channelMembersAdd'.tr);
}, },
); );
if (input == null) return; if (input == null) return;