✨ Channel detail
This commit is contained in:
@ -12,6 +12,7 @@ import 'package:solian/models/pagination.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
import 'package:solian/providers/chat.dart';
|
||||
import 'package:solian/providers/content/channel.dart';
|
||||
import 'package:solian/router.dart';
|
||||
import 'package:solian/services.dart';
|
||||
import 'package:solian/theme.dart';
|
||||
import 'package:solian/widgets/chat/chat_message.dart';
|
||||
@ -33,6 +34,7 @@ class ChannelChatScreen extends StatefulWidget {
|
||||
|
||||
class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
||||
bool _isBusy = false;
|
||||
String? _overrideAlias;
|
||||
|
||||
Channel? _channel;
|
||||
StreamSubscription<NetworkPackage>? _subscription;
|
||||
@ -40,13 +42,20 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
||||
final PagingController<int, Message> _pagingController =
|
||||
PagingController(firstPageKey: 0);
|
||||
|
||||
getChannel() async {
|
||||
getChannel({String? overrideAlias}) async {
|
||||
final ChannelProvider provider = Get.find();
|
||||
|
||||
setState(() => _isBusy = true);
|
||||
|
||||
if (overrideAlias != null) {
|
||||
_overrideAlias = overrideAlias;
|
||||
}
|
||||
|
||||
try {
|
||||
final resp = await provider.getChannel(widget.alias, realm: widget.realm);
|
||||
final resp = await provider.getChannel(
|
||||
_overrideAlias ?? widget.alias,
|
||||
realm: widget.realm,
|
||||
);
|
||||
setState(() => _channel = Channel.fromJson(resp.body));
|
||||
} catch (e) {
|
||||
context.showErrorDialog(e);
|
||||
@ -184,8 +193,23 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
||||
centerTitle: false,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings),
|
||||
onPressed: () {},
|
||||
icon: const Icon(Icons.more_vert),
|
||||
onPressed: () {
|
||||
AppRouter.instance
|
||||
.pushNamed(
|
||||
'channelDetail',
|
||||
pathParameters: {'alias': widget.alias},
|
||||
queryParameters: {'realm': widget.realm},
|
||||
extra: _channel,
|
||||
)
|
||||
.then((value) {
|
||||
if (value == false) AppRouter.instance.pop();
|
||||
if (value != null) {
|
||||
final resp = Channel.fromJson(value as Map<String, dynamic>);
|
||||
getChannel(overrideAlias: resp.alias);
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
||||
|
142
lib/screens/channel/channel_detail.dart
Normal file
142
lib/screens/channel/channel_detail.dart
Normal file
@ -0,0 +1,142 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:solian/models/channel.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
import 'package:solian/router.dart';
|
||||
import 'package:solian/screens/channel/channel_organize.dart';
|
||||
import 'package:solian/widgets/channel/channel_deletion.dart';
|
||||
|
||||
class ChannelDetailScreen extends StatefulWidget {
|
||||
final String realm;
|
||||
final Channel channel;
|
||||
|
||||
const ChannelDetailScreen({
|
||||
super.key,
|
||||
required this.channel,
|
||||
required this.realm,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ChannelDetailScreen> createState() => _ChannelDetailScreenState();
|
||||
}
|
||||
|
||||
class _ChannelDetailScreenState extends State<ChannelDetailScreen> {
|
||||
bool _isOwned = false;
|
||||
|
||||
void checkOwner() async {
|
||||
final AuthProvider auth = Get.find();
|
||||
final prof = await auth.getProfile();
|
||||
setState(() {
|
||||
_isOwned = prof.body['id'] == widget.channel.account.externalId;
|
||||
});
|
||||
}
|
||||
|
||||
void promptLeaveChannel() async {
|
||||
final did = await showDialog(
|
||||
context: context,
|
||||
builder: (context) => ChannelDeletion(
|
||||
channel: widget.channel,
|
||||
realm: widget.realm,
|
||||
isOwned: _isOwned,
|
||||
),
|
||||
);
|
||||
if (did == true && AppRouter.instance.canPop()) {
|
||||
AppRouter.instance.pop(false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
checkOwner();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ownerActions = [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.edit),
|
||||
title: Text('channelAdjust'.tr),
|
||||
onTap: () async {
|
||||
AppRouter.instance
|
||||
.pushNamed(
|
||||
'channelOrganizing',
|
||||
extra: ChannelOrganizeArguments(edit: widget.channel),
|
||||
queryParameters:
|
||||
widget.realm != 'global' ? {'realm': widget.realm} : {},
|
||||
)
|
||||
.then((resp) {
|
||||
if (resp != null) {
|
||||
AppRouter.instance.pop(resp);
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 28,
|
||||
backgroundColor: Colors.teal,
|
||||
child: FaIcon(
|
||||
widget.channel.icon,
|
||||
color: Colors.white,
|
||||
size: 18,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(widget.channel.name,
|
||||
style: Theme.of(context).textTheme.bodyLarge),
|
||||
Text(widget.channel.description,
|
||||
style: Theme.of(context).textTheme.bodySmall),
|
||||
Text(
|
||||
'#${widget.channel.id.toString().padLeft(8, '0')} · ${widget.channel.alias}',
|
||||
style: const TextStyle(fontSize: 11),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(thickness: 0.3),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.settings),
|
||||
title: Text('channelSettings'.tr),
|
||||
onTap: () {},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.supervisor_account),
|
||||
title: Text('channelMembers'.tr),
|
||||
onTap: () {},
|
||||
),
|
||||
...(_isOwned ? ownerActions : List.empty()),
|
||||
const Divider(thickness: 0.3),
|
||||
ListTile(
|
||||
leading: _isOwned
|
||||
? const Icon(Icons.delete)
|
||||
: const Icon(Icons.exit_to_app),
|
||||
title: Text(_isOwned ? 'delete'.tr : 'leave'.tr),
|
||||
onTap: () => promptLeaveChannel(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -227,7 +227,7 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> {
|
||||
).paddingSymmetric(horizontal: 16, vertical: 12),
|
||||
),
|
||||
const Divider(thickness: 0.3),
|
||||
if (_channelType == 1)
|
||||
if (_channelType == 1 && widget.edit == null)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.supervisor_account)
|
||||
.paddingSymmetric(horizontal: 8),
|
||||
@ -250,6 +250,8 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> {
|
||||
isExpanded: true,
|
||||
items: channelTypes.entries
|
||||
.map((item) => DropdownMenuItem<int>(
|
||||
enabled: widget.edit == null ||
|
||||
item.key == widget.edit?.type,
|
||||
value: item.key,
|
||||
child: Text(
|
||||
item.value,
|
||||
|
Reference in New Issue
Block a user