Support for iCal UID

This commit is contained in:
daladim 2021-04-12 09:21:50 +02:00
parent 9d2d83e06f
commit 0fe487c988
4 changed files with 34 additions and 6 deletions

View file

@ -23,6 +23,10 @@ impl Event {
&self.id &self.id
} }
pub fn uid(&self) -> &str {
unimplemented!()
}
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }

View file

@ -29,6 +29,7 @@ pub fn parse(content: &str, item_id: ItemId, sync_status: SyncStatus) -> Result<
CurrentType::Todo(todo) => { CurrentType::Todo(todo) => {
let mut name = None; let mut name = None;
let mut uid = None;
let mut completed = false; let mut completed = false;
for prop in &todo.properties { for prop in &todo.properties {
if prop.name == "SUMMARY" { if prop.name == "SUMMARY" {
@ -44,13 +45,20 @@ pub fn parse(content: &str, item_id: ItemId, sync_status: SyncStatus) -> Result<
completed = true; completed = true;
} }
} }
if prop.name == "UID" {
uid = prop.value.clone();
}
} }
let name = match name { let name = match name {
Some(name) => name, Some(name) => name,
None => return Err(format!("Missing name for item {}", item_id).into()), None => return Err(format!("Missing name for item {}", item_id).into()),
}; };
let uid = match uid {
Some(uid) => uid,
None => return Err(format!("Missing UID for item {}", item_id).into()),
};
Item::Task(Task::new_with_parameters(name, completed, item_id, sync_status)) Item::Task(Task::new_with_parameters(name, completed, uid, item_id, sync_status))
}, },
}; };
@ -99,7 +107,7 @@ mod test {
VERSION:2.0 VERSION:2.0
PRODID:-//Nextcloud Tasks v0.13.6 PRODID:-//Nextcloud Tasks v0.13.6
BEGIN:VTODO BEGIN:VTODO
UID:0633de27-8c32-42be-bcb8-63bc879c6185 UID:0633de27-8c32-42be-bcb8-63bc879c6185@some-domain.com
CREATED:20210321T001600 CREATED:20210321T001600
LAST-MODIFIED:20210321T001600 LAST-MODIFIED:20210321T001600
DTSTAMP:20210321T001600 DTSTAMP:20210321T001600
@ -112,7 +120,7 @@ END:VCALENDAR
VERSION:2.0 VERSION:2.0
PRODID:-//Nextcloud Tasks v0.13.6 PRODID:-//Nextcloud Tasks v0.13.6
BEGIN:VTODO BEGIN:VTODO
UID:0633de27-8c32-42be-bcb8-63bc879c6185 UID:19960401T080045Z-4000F192713-0052@example.com
CREATED:20210321T001600 CREATED:20210321T001600
LAST-MODIFIED:20210402T081557 LAST-MODIFIED:20210402T081557
DTSTAMP:20210402T081557 DTSTAMP:20210402T081557
@ -160,6 +168,7 @@ END:VCALENDAR
assert_eq!(task.name(), "Do not forget to do this"); assert_eq!(task.name(), "Do not forget to do this");
assert_eq!(task.id(), &item_id); assert_eq!(task.id(), &item_id);
assert_eq!(task.uid(), "0633de27-8c32-42be-bcb8-63bc879c6185@some-domain.com");
assert_eq!(task.completed(), false); assert_eq!(task.completed(), false);
assert_eq!(task.sync_status(), &sync_status); assert_eq!(task.sync_status(), &sync_status);
} }

View file

@ -25,6 +25,13 @@ impl Item {
} }
} }
pub fn uid(&self) -> &str {
match self {
Item::Event(e) => e.uid(),
Item::Task(t) => t.uid(),
}
}
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
match self { match self {
Item::Event(e) => e.name(), Item::Event(e) => e.name(),

View file

@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::item::ItemId; use crate::item::ItemId;
use crate::item::SyncStatus; use crate::item::SyncStatus;
@ -7,9 +8,13 @@ use crate::calendar::CalendarId;
/// A to-do task /// A to-do task
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Task { pub struct Task {
/// The task unique ID, that will never change /// The task URL
id: ItemId, id: ItemId,
/// Persistent, globally unique identifier for the calendar component
/// The [RFC](https://tools.ietf.org/html/rfc5545#page-117) recommends concatenating a timestamp with the server's domain name, but UUID are even better
uid: String,
/// The sync status of this item /// The sync status of this item
sync_status: SyncStatus, sync_status: SyncStatus,
@ -25,13 +30,15 @@ impl Task {
pub fn new(name: String, completed: bool, parent_calendar_id: &CalendarId) -> Self { pub fn new(name: String, completed: bool, parent_calendar_id: &CalendarId) -> Self {
let new_item_id = ItemId::random(parent_calendar_id); let new_item_id = ItemId::random(parent_calendar_id);
let new_sync_status = SyncStatus::NotSynced; let new_sync_status = SyncStatus::NotSynced;
Self::new_with_parameters(name, completed, new_item_id, new_sync_status) let new_uid = Uuid::new_v4().to_hyphenated().to_string();
Self::new_with_parameters(name, completed, new_uid, new_item_id, new_sync_status)
} }
/// Create a new Task instance, that may be synced already /// Create a new Task instance, that may be synced already
pub fn new_with_parameters(name: String, completed: bool, id: ItemId, sync_status: SyncStatus) -> Self { pub fn new_with_parameters(name: String, completed: bool, uid: String, id: ItemId, sync_status: SyncStatus) -> Self {
Self { Self {
id, id,
uid,
name, name,
sync_status, sync_status,
completed, completed,
@ -39,6 +46,7 @@ impl Task {
} }
pub fn id(&self) -> &ItemId { &self.id } pub fn id(&self) -> &ItemId { &self.id }
pub fn uid(&self) -> &str { &self.uid }
pub fn name(&self) -> &str { &self.name } pub fn name(&self) -> &str { &self.name }
pub fn completed(&self) -> bool { self.completed } pub fn completed(&self) -> bool { self.completed }
pub fn sync_status(&self) -> &SyncStatus { &self.sync_status } pub fn sync_status(&self) -> &SyncStatus { &self.sync_status }