✨ Better chat screen
This commit is contained in:
parent
bb67edd227
commit
e221016c8d
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:solian/models/channel.dart';
|
||||
@ -80,82 +79,135 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => getChannels(),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
title: AppBarTitle('chat'.tr),
|
||||
centerTitle: false,
|
||||
floating: true,
|
||||
titleSpacing: SolianTheme.titleSpacing(context),
|
||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
||||
actions: [
|
||||
const BackgroundStateWidget(),
|
||||
const NotificationButton(),
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.add_circle),
|
||||
itemBuilder: (BuildContext context) => [
|
||||
PopupMenuItem(
|
||||
child: ListTile(
|
||||
title: Text('channelOrganizeCommon'.tr),
|
||||
leading: const Icon(Icons.tag),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
onTap: () {
|
||||
AppRouter.instance
|
||||
.pushNamed('channelOrganizing')
|
||||
.then(
|
||||
(value) {
|
||||
if (value != null) getChannels();
|
||||
final prefixSlivers = [
|
||||
Obx(() {
|
||||
if (call.current.value != null) {
|
||||
return const SliverToBoxAdapter(
|
||||
child: ChatCallCurrentIndicator(),
|
||||
);
|
||||
} else {
|
||||
return const SliverToBoxAdapter();
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
||||
return DefaultTabController(
|
||||
length: 2,
|
||||
child: NestedScrollView(
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverOverlapAbsorber(
|
||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
|
||||
context),
|
||||
sliver: SliverAppBar(
|
||||
title: AppBarTitle('chat'.tr),
|
||||
centerTitle: true,
|
||||
floating: true,
|
||||
titleSpacing: SolianTheme.titleSpacing(context),
|
||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
||||
actions: [
|
||||
const BackgroundStateWidget(),
|
||||
const NotificationButton(),
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.add_circle),
|
||||
itemBuilder: (BuildContext context) => [
|
||||
PopupMenuItem(
|
||||
child: ListTile(
|
||||
title: Text('channelOrganizeCommon'.tr),
|
||||
leading: const Icon(Icons.tag),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
onTap: () {
|
||||
AppRouter.instance
|
||||
.pushNamed('channelOrganizing')
|
||||
.then(
|
||||
(value) {
|
||||
if (value != null) getChannels();
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: ListTile(
|
||||
title: Text('channelOrganizeDirect'.tr),
|
||||
leading: const FaIcon(
|
||||
FontAwesomeIcons.userGroup,
|
||||
size: 16,
|
||||
),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
onTap: () {
|
||||
final ChannelProvider provider = Get.find();
|
||||
provider
|
||||
.createDirectChannel(context, 'global')
|
||||
.then((resp) {
|
||||
if (resp != null) {
|
||||
getChannels();
|
||||
}
|
||||
});
|
||||
},
|
||||
PopupMenuItem(
|
||||
child: ListTile(
|
||||
title: Text('channelOrganizeDirect'.tr),
|
||||
leading: const FaIcon(
|
||||
FontAwesomeIcons.userGroup,
|
||||
size: 16,
|
||||
),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
onTap: () {
|
||||
final ChannelProvider provider = Get.find();
|
||||
provider
|
||||
.createDirectChannel(context, 'global')
|
||||
.then((resp) {
|
||||
if (resp != null) {
|
||||
getChannels();
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
||||
),
|
||||
],
|
||||
bottom: TabBar(
|
||||
tabs: [
|
||||
Tab(
|
||||
icon: const Icon(Icons.tag),
|
||||
text: 'channels'.tr,
|
||||
),
|
||||
Tab(
|
||||
icon: const Icon(Icons.chat),
|
||||
text: 'channelCategoryDirect'.tr,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
||||
),
|
||||
];
|
||||
},
|
||||
body: Builder(builder: (context) {
|
||||
if (_isBusy) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return TabBarView(
|
||||
children: [
|
||||
RefreshIndicator(
|
||||
onRefresh: () => getChannels(),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
...prefixSlivers,
|
||||
ChannelListWidget(
|
||||
channels:
|
||||
_channels.where((x) => x.type == 0).toList(),
|
||||
selfId: _accountId ?? 0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
RefreshIndicator(
|
||||
onRefresh: () => getChannels(),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
...prefixSlivers,
|
||||
ChannelListWidget(
|
||||
channels:
|
||||
_channels.where((x) => x.type == 1).toList(),
|
||||
selfId: _accountId ?? 0,
|
||||
noCategory: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Obx(() {
|
||||
if (call.current.value != null) {
|
||||
return const SliverToBoxAdapter(
|
||||
child: ChatCallCurrentIndicator(),
|
||||
);
|
||||
} else {
|
||||
return const SliverToBoxAdapter();
|
||||
}
|
||||
}),
|
||||
if (_isBusy)
|
||||
SliverToBoxAdapter(
|
||||
child: const LinearProgressIndicator().animate().scaleX(),
|
||||
),
|
||||
ChannelListWidget(channels: _channels, selfId: _accountId ?? 0),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -127,6 +127,7 @@ class SolianMessages extends Translations {
|
||||
'realmDeletionConfirm': 'Confirm realm deletion',
|
||||
'realmDeletionConfirmCaption':
|
||||
'Are you sure to delete realm @realm? This action cannot be undone!',
|
||||
'channels': 'Channels',
|
||||
'channelNew': 'Create a new channel',
|
||||
'channelNewInRealmHint': 'Create channel in realm @realm',
|
||||
'channelOrganizing': 'Organize a channel',
|
||||
@ -328,6 +329,7 @@ class SolianMessages extends Translations {
|
||||
'realmLeaveConfirmCaption': '你确认要离开领域 @realm 吗?你在该领域发表的内容不会被删除。',
|
||||
'realmDeletionConfirm': '确认删除领域',
|
||||
'realmDeletionConfirmCaption': '你确定要删除领域 @realm 嘛?该操作不可撤销。',
|
||||
'channels': '频道',
|
||||
'channelNew': '创建新频道',
|
||||
'channelNewInRealmHint': '在领域 @realm 里创建新频道',
|
||||
'channelOrganizing': '组织频道',
|
||||
|
@ -23,13 +23,11 @@ class ChannelListWidget extends StatefulWidget {
|
||||
|
||||
class _ChannelListWidgetState extends State<ChannelListWidget> {
|
||||
final List<Channel> _globalChannels = List.empty(growable: true);
|
||||
final List<Channel> _directMessages = List.empty(growable: true);
|
||||
final Map<String, List<Channel>> _inRealms = {};
|
||||
|
||||
void mapChannels() {
|
||||
_inRealms.clear();
|
||||
_globalChannels.clear();
|
||||
_directMessages.clear();
|
||||
|
||||
if (widget.noCategory) {
|
||||
_globalChannels.addAll(widget.channels);
|
||||
@ -42,8 +40,6 @@ class _ChannelListWidgetState extends State<ChannelListWidget> {
|
||||
_inRealms[channel.realm!.alias] = List.empty(growable: true);
|
||||
}
|
||||
_inRealms[channel.realm!.alias]!.add(channel);
|
||||
} else if (channel.type == 1) {
|
||||
_directMessages.add(channel);
|
||||
} else {
|
||||
_globalChannels.add(channel);
|
||||
}
|
||||
@ -56,6 +52,12 @@ class _ChannelListWidgetState extends State<ChannelListWidget> {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
mapChannels();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Widget buildItem(Channel element) {
|
||||
if (element.type == 1) {
|
||||
final otherside = element.members!
|
||||
@ -125,13 +127,6 @@ class _ChannelListWidgetState extends State<ChannelListWidget> {
|
||||
return SliverList.list(
|
||||
children: [
|
||||
..._globalChannels.map((e) => buildItem(e)),
|
||||
if (_directMessages.isNotEmpty)
|
||||
ExpansionTile(
|
||||
tilePadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('channelCategoryDirect'.tr),
|
||||
subtitle: Text('channelCategoryDirectHint'.tr),
|
||||
children: _directMessages.map((e) => buildItem(e)).toList(),
|
||||
),
|
||||
..._inRealms.entries.map((element) {
|
||||
return ExpansionTile(
|
||||
tilePadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
|
Loading…
Reference in New Issue
Block a user