use std::sync::Arc;
use matrix_sdk::deserialized_responses::EncryptionInfo;
use ruma::{
MilliSecondsSinceUnixEpoch,
events::{beacon_info::BeaconInfoEventContent, location::AssetType},
};
#[derive(Clone, Debug)]
pub struct BeaconInfo {
pub(in crate::timeline) geo_uri: String,
pub(in crate::timeline) ts: MilliSecondsSinceUnixEpoch,
pub(in crate::timeline) description: Option<String>,
pub(in crate::timeline) encryption_info: Option<Arc<EncryptionInfo>>,
}
impl BeaconInfo {
pub fn geo_uri(&self) -> &str {
&self.geo_uri
}
pub fn ts(&self) -> MilliSecondsSinceUnixEpoch {
self.ts
}
pub fn description(&self) -> Option<&str> {
self.description.as_deref()
}
pub fn encryption_info(&self) -> Option<&EncryptionInfo> {
self.encryption_info.as_deref()
}
}
#[derive(Clone, Debug)]
pub struct LiveLocationState {
pub(in crate::timeline) beacon_info: BeaconInfoEventContent,
pub(in crate::timeline) locations: Vec<BeaconInfo>,
}
impl LiveLocationState {
pub fn new(beacon_info: BeaconInfoEventContent) -> Self {
Self { beacon_info, locations: Vec::new() }
}
pub(in crate::timeline) fn add_location(&mut self, location: BeaconInfo) {
match self.locations.binary_search_by_key(&location.ts, |l| l.ts) {
Ok(_) => (), Err(index) => self.locations.insert(index, location),
}
}
pub(in crate::timeline) fn remove_location(&mut self, ts: MilliSecondsSinceUnixEpoch) {
self.locations.retain(|l| l.ts != ts);
}
pub fn locations(&self) -> &[BeaconInfo] {
&self.locations
}
pub fn latest_location(&self) -> Option<&BeaconInfo> {
self.locations.last()
}
pub fn is_live(&self) -> bool {
self.beacon_info.is_live()
}
pub fn ts(&self) -> MilliSecondsSinceUnixEpoch {
self.beacon_info.ts
}
pub fn description(&self) -> Option<&str> {
self.beacon_info.description.as_deref()
}
pub fn timeout(&self) -> std::time::Duration {
self.beacon_info.timeout
}
pub fn asset_type(&self) -> AssetType {
self.beacon_info.asset.type_.clone()
}
pub(in crate::timeline) fn stop(&mut self, beacon_info: BeaconInfoEventContent) {
assert!(!beacon_info.is_live(), "A stop `beacon_info` event must not be live.");
self.beacon_info = beacon_info;
}
pub(in crate::timeline) fn matches_stop(&self, stop: &BeaconInfoEventContent) -> bool {
self.beacon_info.live && beacon_info_matches(&self.beacon_info, stop)
}
}
pub fn beacon_info_matches(a: &BeaconInfoEventContent, b: &BeaconInfoEventContent) -> bool {
a.ts == b.ts && a.timeout == b.timeout && a.description == b.description && a.asset == b.asset
}