Опросы (новый тип сообщения):
- модель Poll/PollAnswer и PollAttachment (_type: POLL)
- PollsModule: загрузка через opcode 306 (GET_POLL_UPDATES) с кэшем
- рендер опроса в баблах (вопрос, варианты, прогресс-бары, голоса)
Видео:
- getVideoUrl через opcode 83 (VIDEO_PLAY): выбор MP4_*/HLS из ответа
- полноэкранный плеер (video_player) с play/pause и перемоткой
- тап по видео в чате запускает воспроизведение
Файлы:
- getFileUrl через opcode 88 (FILE_DOWNLOAD) с корректным форматом
{messageId, chatId, fileId} → url (раньше слался неверный {url, token})
- скачивание во временную папку и открытие системным приложением
(path_provider, open_filex)
Фото:
- полноэкранный просмотрщик с зумом (был TODO-заглушкой)
- фикс «сжатости»: декодирование с учётом devicePixelRatio вместо ×2
62 lines
1.5 KiB
Dart
62 lines
1.5 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
|
|
import '../api.dart';
|
|
import '../../core/protocol/opcode_map.dart';
|
|
import '../../models/poll.dart';
|
|
|
|
class PollsModule extends ChangeNotifier {
|
|
final Api _api;
|
|
|
|
PollsModule(this._api);
|
|
|
|
final Map<int, Poll> _cache = {};
|
|
final Set<int> _inFlight = {};
|
|
|
|
Poll? get(int pollId) => _cache[pollId];
|
|
|
|
Future<void> fetch(
|
|
int chatId,
|
|
String messageId,
|
|
int pollId, {
|
|
bool force = false,
|
|
}) async {
|
|
if (pollId == 0) return;
|
|
if (!force && (_cache.containsKey(pollId) || _inFlight.contains(pollId))) {
|
|
return;
|
|
}
|
|
_inFlight.add(pollId);
|
|
try {
|
|
final mid = int.tryParse(messageId) ?? 0;
|
|
final response = await _api.sendRequest(Opcode.getPollUpdates, {
|
|
'chatId': chatId,
|
|
'polls': [
|
|
{'messageId': mid, 'pollId': pollId},
|
|
],
|
|
});
|
|
if (!response.isOk) return;
|
|
|
|
final data = response.payload;
|
|
if (data is! Map) return;
|
|
|
|
final polls = data['polls'];
|
|
if (polls is! List) return;
|
|
|
|
var changed = false;
|
|
for (final p in polls) {
|
|
if (p is Map) {
|
|
final poll = Poll.fromServerMap(p);
|
|
if (poll.pollId != 0) {
|
|
_cache[poll.pollId] = poll;
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
if (changed) notifyListeners();
|
|
} catch (_) {
|
|
// тихо игнорируем — опрос просто не отобразится
|
|
} finally {
|
|
_inFlight.remove(pollId);
|
|
}
|
|
}
|
|
}
|