fix: какое то уведомление при входе в незнакомые каналы

This commit is contained in:
Jganenokk
2026-07-15 21:00:09 +07:00
parent ac90affc23
commit f7604ebf34
4 changed files with 124 additions and 5 deletions
+6 -2
View File
@@ -266,7 +266,11 @@ class Api {
} }
/// Отправляет запрос и ждёт ответ от сервера. /// Отправляет запрос и ждёт ответ от сервера.
Future<Packet> sendRequest(int opcode, Map<dynamic, dynamic> payload) async { Future<Packet> sendRequest(
int opcode,
Map<dynamic, dynamic> payload, {
bool silent = false,
}) async {
final session = _session; final session = _session;
if (session == null) { if (session == null) {
throw StateError('Нет соединения (${Opcode.name(opcode)})'); throw StateError('Нет соединения (${Opcode.name(opcode)})');
@@ -296,7 +300,7 @@ class Api {
throw ex; throw ex;
} }
final text = _serverErrorText(packet.payload); final text = _serverErrorText(packet.payload);
if (text != null) _errorController.add(text); if (text != null && !silent) _errorController.add(text);
final err = PacketError( final err = PacketError(
messageFromErrorPayload(packet.payload), messageFromErrorPayload(packet.payload),
errorKey: resp.errorKey, errorKey: resp.errorKey,
+27 -3
View File
@@ -399,7 +399,7 @@ class ChatsModule {
'chatId': chatId, 'chatId': chatId,
'messageId': msgIdNum, 'messageId': msgIdNum,
'mark': mark, 'mark': mark,
}); }, silent: true);
} catch (_) {} } catch (_) {}
} }
@@ -424,7 +424,7 @@ class ChatsModule {
'chatId': chatId, 'chatId': chatId,
'messageId': msgIdNum, 'messageId': msgIdNum,
'mark': mark, 'mark': mark,
}); }, silent: true);
} catch (_) {} } catch (_) {}
} }
@@ -1348,12 +1348,36 @@ class ChatsModule {
await api.sendRequest(Opcode.chatSubscribe, { await api.sendRequest(Opcode.chatSubscribe, {
'chatId': chatId, 'chatId': chatId,
'subscribe': subscribe, 'subscribe': subscribe,
}); }, silent: true);
} catch (e) { } catch (e) {
logger.w('subscribeChat failed: $e'); logger.w('subscribeChat failed: $e');
} }
} }
Future<({CachedChat chat, int? subscribersCount})> joinChannel(
Api api,
String link,
int accountId,
) async {
final packet = await api.sendRequest(Opcode.chatJoin, {
'link': link,
}, silent: true);
if (!packet.isOk) {
throw PacketError(messageFromErrorPayload(packet.payload));
}
final payload = packet.payload;
final chatMap = payload is Map ? payload['chat'] : null;
if (chatMap is! Map) {
throw const PacketError('Не удалось подписаться');
}
final cached = await cacheServerChat(chatMap, accountId);
if (cached == null) {
throw const PacketError('Не удалось подписаться');
}
final count = chatMap['participantsCount'];
return (chat: cached, subscribersCount: count is int ? count : null);
}
Future<bool> ensureChatCached(Api api, int accountId, int chatId) async { Future<bool> ensureChatCached(Api api, int accountId, int chatId) async {
final rows = await AppDatabase.loadChat(accountId, chatId); final rows = await AppDatabase.loadChat(accountId, chatId);
if (rows.isNotEmpty) return true; if (rows.isNotEmpty) return true;
@@ -46,6 +46,9 @@ class ComposerInputBar extends StatelessWidget {
required this.contextMenuBuilder, required this.contextMenuBuilder,
required this.isMuted, required this.isMuted,
required this.onToggleMute, required this.onToggleMute,
this.channelSubscribed = true,
this.channelSubscribing = false,
this.onSubscribe,
}); });
final String chatType; final String chatType;
@@ -73,6 +76,9 @@ class ComposerInputBar extends StatelessWidget {
final Widget Function(BuildContext, EditableTextState) contextMenuBuilder; final Widget Function(BuildContext, EditableTextState) contextMenuBuilder;
final bool isMuted; final bool isMuted;
final VoidCallback onToggleMute; final VoidCallback onToggleMute;
final bool channelSubscribed;
final bool channelSubscribing;
final VoidCallback? onSubscribe;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -80,6 +86,49 @@ class ComposerInputBar extends StatelessWidget {
final mutedIcon = cs.onSurfaceVariant.withValues(alpha: 0.85); final mutedIcon = cs.onSurfaceVariant.withValues(alpha: 0.85);
if (chatType == "CHANNEL") { if (chatType == "CHANNEL") {
if (!channelSubscribed) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8.0,
),
child: GlossyPill(
onTap: channelSubscribing ? null : onSubscribe,
color: cs.primary,
borderRadius: BorderRadius.circular(28),
padding: const EdgeInsets.symmetric(vertical: 16),
depth: 8,
borderSide: BorderSide(
color: cs.outlineVariant.withValues(alpha: 0.5),
width: 0.5,
),
child: SizedBox(
width: double.infinity,
child: Center(
child: channelSubscribing
? SizedBox(
width: 22,
height: 22,
child: CircularProgressIndicator(
strokeWidth: 2,
color: cs.onPrimary,
),
)
: Text(
'Подписаться',
style: TextStyle(
color: cs.onPrimary,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
),
),
),
);
}
return SafeArea( return SafeArea(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
@@ -435,6 +435,8 @@ class _ChatScreenState extends State<ChatScreen>
late AnimationController _shimmerController; late AnimationController _shimmerController;
Timer? _shimmerStartTimer; Timer? _shimmerStartTimer;
bool _previewChat = false; bool _previewChat = false;
bool _subscribing = false;
String? _channelLink;
bool _forwardRequestDone = false; bool _forwardRequestDone = false;
final ChatController _chatController = ChatController(); final ChatController _chatController = ChatController();
@@ -642,6 +644,10 @@ class _ChatScreenState extends State<ChatScreen>
if (widget.chatType != 'CHAT' && widget.chatType != 'CHANNEL') return; if (widget.chatType != 'CHAT' && widget.chatType != 'CHANNEL') return;
final info = await chats.getChatInfo(api, widget.chatId); final info = await chats.getChatInfo(api, widget.chatId);
if (!mounted) return; if (!mounted) return;
if (widget.chatType == 'CHANNEL') {
final link = info?['link'];
if (link is String && link.isNotEmpty) _channelLink = link;
}
final count = info?['participantsCount'] as int?; final count = info?['participantsCount'] as int?;
if (count != null && count != _participantsCount) { if (count != null && count != _participantsCount) {
_participantsCount = count; _participantsCount = count;
@@ -2166,6 +2172,9 @@ class _ChatScreenState extends State<ChatScreen>
_formatContextMenu(_messageController, ctx, state), _formatContextMenu(_messageController, ctx, state),
isMuted: chat?.isMuted ?? false, isMuted: chat?.isMuted ?? false,
onToggleMute: _toggleChatMute, onToggleMute: _toggleChatMute,
channelSubscribed: !_previewChat,
channelSubscribing: _subscribing,
onSubscribe: _subscribeChannel,
), ),
StickerPanelView( StickerPanelView(
stickers: _stickers, stickers: _stickers,
@@ -2754,6 +2763,39 @@ class _ChatScreenState extends State<ChatScreen>
); );
} }
Future<void> _subscribeChannel() async {
if (_subscribing) return;
setState(() => _subscribing = true);
try {
var link = _channelLink;
if (link == null || link.isEmpty) {
final info = await chats.getChatInfo(api, widget.chatId);
link = info?['link'] as String?;
}
if (link == null || link.isEmpty) {
throw const PacketError('Не удалось получить ссылку канала');
}
final result = await chats.joinChannel(api, link, _myId);
if (!mounted) return;
setState(() {
_previewChat = false;
_subscribing = false;
chat = result.chat;
_participantsCount =
result.subscribersCount ?? ((_participantsCount ?? 0) + 1);
});
_recomputeHeaderStatus();
showCustomNotification(context, 'Вы подписались на канал');
} catch (e) {
if (!mounted) return;
setState(() => _subscribing = false);
showCustomNotification(
context,
e is PacketError ? e.message : 'Не удалось подписаться',
);
}
}
Future<void> _toggleChatMute() async { Future<void> _toggleChatMute() async {
final current = chat; final current = chat;
if (current == null) return; if (current == null) return;