Flutter web app replacing legacy WPF CCTV surveillance keyboard controller. Includes wall overview, section view with monitor grid, camera input, PTZ control, alarm/lock/sequence BLoCs, and legacy-matching UI styling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
128 lines
3.0 KiB
Dart
128 lines
3.0 KiB
Dart
import 'package:equatable/equatable.dart';
|
|
|
|
/// Play mode enumeration matching SDK values
|
|
enum PlayMode {
|
|
unknown(0),
|
|
playStop(1),
|
|
playForward(2),
|
|
playBackward(3),
|
|
fastForward(4),
|
|
fastBackward(5),
|
|
stepForward(6),
|
|
stepBackward(7),
|
|
playBOD(8),
|
|
playEOD(9),
|
|
quasiLive(10),
|
|
live(11),
|
|
nextEvent(12),
|
|
prevEvent(13),
|
|
peekLivePicture(14),
|
|
nextDetectedMotion(17),
|
|
prevDetectedMotion(18);
|
|
|
|
final int value;
|
|
const PlayMode(this.value);
|
|
|
|
static PlayMode fromValue(int value) {
|
|
return PlayMode.values.firstWhere(
|
|
(m) => m.value == value,
|
|
orElse: () => PlayMode.unknown,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// State of a single monitor/viewer
|
|
class MonitorState extends Equatable {
|
|
final int viewerId;
|
|
final int currentChannel;
|
|
final PlayMode playMode;
|
|
final String? serverId;
|
|
final DateTime lastUpdated;
|
|
final bool hasAlarm;
|
|
|
|
const MonitorState({
|
|
required this.viewerId,
|
|
required this.currentChannel,
|
|
required this.playMode,
|
|
this.serverId,
|
|
required this.lastUpdated,
|
|
this.hasAlarm = false,
|
|
});
|
|
|
|
/// Check if monitor is currently displaying a camera
|
|
bool get isActive => currentChannel > 0;
|
|
|
|
/// Check if monitor is in live mode
|
|
bool get isLive => playMode == PlayMode.live || playMode == PlayMode.quasiLive;
|
|
|
|
/// Create a cleared state
|
|
MonitorState cleared() {
|
|
return MonitorState(
|
|
viewerId: viewerId,
|
|
currentChannel: 0,
|
|
playMode: PlayMode.unknown,
|
|
serverId: serverId,
|
|
lastUpdated: DateTime.now(),
|
|
hasAlarm: hasAlarm,
|
|
);
|
|
}
|
|
|
|
/// Create updated state with new camera
|
|
MonitorState withCamera(int channel, PlayMode mode) {
|
|
return MonitorState(
|
|
viewerId: viewerId,
|
|
currentChannel: channel,
|
|
playMode: mode,
|
|
serverId: serverId,
|
|
lastUpdated: DateTime.now(),
|
|
hasAlarm: hasAlarm,
|
|
);
|
|
}
|
|
|
|
/// Create state with alarm flag updated
|
|
MonitorState withAlarm(bool alarm) {
|
|
return MonitorState(
|
|
viewerId: viewerId,
|
|
currentChannel: currentChannel,
|
|
playMode: playMode,
|
|
serverId: serverId,
|
|
lastUpdated: lastUpdated,
|
|
hasAlarm: alarm,
|
|
);
|
|
}
|
|
|
|
factory MonitorState.fromJson(Map<String, dynamic> json) {
|
|
return MonitorState(
|
|
viewerId: json['viewer_id'] as int? ?? 0,
|
|
currentChannel: json['current_channel'] as int? ?? 0,
|
|
playMode: PlayMode.fromValue(json['play_mode'] as int? ?? 0),
|
|
serverId: json['server_id'] as String?,
|
|
lastUpdated: json['last_updated'] != null
|
|
? DateTime.parse(json['last_updated'] as String)
|
|
: DateTime.now(),
|
|
hasAlarm: json['has_alarm'] as bool? ?? false,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'viewer_id': viewerId,
|
|
'current_channel': currentChannel,
|
|
'play_mode': playMode.value,
|
|
'server_id': serverId,
|
|
'last_updated': lastUpdated.toIso8601String(),
|
|
'has_alarm': hasAlarm,
|
|
};
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
viewerId,
|
|
currentChannel,
|
|
playMode,
|
|
serverId,
|
|
lastUpdated,
|
|
hasAlarm,
|
|
];
|
|
}
|