feat(stories): публикация видео-историй + фикс TTL
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'persisted_setting.dart';
|
||||
|
||||
class AppVideoNoteResolution {
|
||||
static const prefKey = 'dev_video_note_resolution';
|
||||
static const int defaultValue = 480;
|
||||
static const List<int> presets = [480, 720, 1080];
|
||||
|
||||
static final _setting = PersistedSetting<int>(
|
||||
prefKey: prefKey,
|
||||
defaultValue: defaultValue,
|
||||
read: (prefs, key) => prefs.getInt(key),
|
||||
write: (prefs, key, value) async {
|
||||
await prefs.setInt(key, value);
|
||||
},
|
||||
sanitize: (value) => presets.contains(value) ? value : defaultValue,
|
||||
);
|
||||
|
||||
static ValueNotifier<int> get current => _setting.current;
|
||||
|
||||
static Future<int> load() => _setting.load();
|
||||
|
||||
static Future<void> save(int value) => _setting.save(value);
|
||||
}
|
||||
|
||||
class AppVideoNoteRearCamera {
|
||||
static const prefKey = 'dev_video_note_rear_camera';
|
||||
static const bool defaultValue = false;
|
||||
|
||||
static final _setting = PersistedSetting<bool>(
|
||||
prefKey: prefKey,
|
||||
defaultValue: defaultValue,
|
||||
read: (prefs, key) => prefs.getBool(key),
|
||||
write: (prefs, key, value) async {
|
||||
await prefs.setBool(key, value);
|
||||
},
|
||||
);
|
||||
|
||||
static ValueNotifier<bool> get current => _setting.current;
|
||||
|
||||
static Future<bool> load() => _setting.load();
|
||||
|
||||
static Future<void> save(bool value) => _setting.save(value);
|
||||
}
|
||||
|
||||
class AppVideoNoteFps {
|
||||
static const prefKey = 'dev_video_note_fps';
|
||||
static const int defaultValue = 30;
|
||||
static const List<int> presets = [30, 60];
|
||||
|
||||
static final _setting = PersistedSetting<int>(
|
||||
prefKey: prefKey,
|
||||
defaultValue: defaultValue,
|
||||
read: (prefs, key) => prefs.getInt(key),
|
||||
write: (prefs, key, value) async {
|
||||
await prefs.setInt(key, value);
|
||||
},
|
||||
sanitize: (value) => presets.contains(value) ? value : defaultValue,
|
||||
);
|
||||
|
||||
static ValueNotifier<int> get current => _setting.current;
|
||||
|
||||
static Future<int> load() => _setting.load();
|
||||
|
||||
static Future<void> save(int value) => _setting.save(value);
|
||||
}
|
||||
@@ -5,20 +5,23 @@ import 'package:flutter/services.dart';
|
||||
import '../utils/logger.dart';
|
||||
|
||||
/// Нативная запись видео-кружка (Android, Camera2 + MediaRecorder): пишет
|
||||
/// квадрат 480×480 сразу при съёмке — как официальный клиент. Превью отдаётся
|
||||
/// через Flutter [Texture] по [textureId]. media3-перекод не используется
|
||||
/// (серверный валидатор принимает только нативно записанный MP4).
|
||||
/// квадрат сразу при съёмке — как официальный клиент (по умолчанию 480×480@30,
|
||||
/// размер и fps настраиваются в дев-меню). Превью отдаётся через Flutter
|
||||
/// [Texture] по [textureId]. media3-перекод не используется (серверный
|
||||
/// валидатор принимает только нативно записанный MP4).
|
||||
class NativeVideoNoteRecorder {
|
||||
static const _channel = MethodChannel('ru.komet.app/video_note');
|
||||
|
||||
int? textureId;
|
||||
bool get isAvailable => Platform.isAndroid;
|
||||
|
||||
Future<bool> init({bool front = true}) async {
|
||||
Future<bool> init({bool front = true, int size = 480, int fps = 30}) async {
|
||||
if (!isAvailable) return false;
|
||||
try {
|
||||
final res = await _channel.invokeMapMethod<String, dynamic>('init', {
|
||||
'front': front,
|
||||
'size': size,
|
||||
'fps': fps,
|
||||
});
|
||||
textureId = res?['textureId'] as int?;
|
||||
return textureId != null;
|
||||
@@ -28,6 +31,17 @@ class NativeVideoNoteRecorder {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> switchCamera() async {
|
||||
if (!isAvailable) return false;
|
||||
try {
|
||||
await _channel.invokeMethod('switch');
|
||||
return true;
|
||||
} catch (e) {
|
||||
logger.w('NativeVideoNoteRecorder.switchCamera: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> start() async {
|
||||
if (!isAvailable) return false;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user