Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alarm component, x parameters #6

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 196 additions & 24 deletions Sources/SwiftIcal/Component.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ extension LibicalComponent {
}
return result
}

subscript(kind: icalparameter_kind)-> [LibicalParameter] {
var result: [LibicalParameter] = []
if let first = icalproperty_get_first_parameter(self, kind) {
result.append(first)
}
while let property = icalproperty_get_next_parameter(self, kind) {
result.append(property)
}
return result
}
}

extension LibicalProperty {
Expand All @@ -50,6 +61,37 @@ extension LibicalProperty {
}
}

extension LibicalComponent {
public var icalComponentString: String {
let c = self

guard let stringPointer = icalcomponent_as_ical_string(c) else {
fatalError("Failed to get component as string")
}
defer {
icalmemory_free_buffer(stringPointer)
}

let string = String(cString: stringPointer)
return string
}
}

extension LibicalComponent {
public var icalPropertyString: String {
let c = self

guard let stringPointer = icalproperty_as_ical_string(c) else {
fatalError("Failed to get property as string")
}
defer {
icalmemory_free_buffer(UnsafeMutableRawPointer(mutating: stringPointer))
}

let string = String(cString: stringPointer)
return string
}
}

extension DateComponents {
var icaltime: icaltimetype {
Expand Down Expand Up @@ -127,7 +169,6 @@ extension CalendarUserType: LibicalPropertyConvertible {
case .unknown:
return icalparameter_new_cutype(ICAL_CUTYPE_UNKNOWN)
}

}
}

Expand Down Expand Up @@ -171,8 +212,6 @@ extension EventParticipationStatus: LibicalParameterConvertible {
return parameter!
}
}


}

public enum Role: Equatable {
Expand Down Expand Up @@ -200,8 +239,6 @@ extension Role: LibicalParameterConvertible {
return parameter!
}
}


}


Expand All @@ -217,7 +254,8 @@ public struct Attendee {
delegatedTo: [CalendarUserAddress]? = nil,
delegatedFrom: [CalendarUserAddress]? = nil,
sentBy: CalendarUserAddress? = nil,
commonName: CommonName? = nil) {
commonName: CommonName? = nil,
xParameters: [String: String] = [:]) {
self.address = address
self.type = type
self.participationStatus = participationStatus
Expand All @@ -228,6 +266,7 @@ public struct Attendee {
self.delegatedFrom = delegatedFrom
self.sentBy = sentBy
self.commonName = commonName
self.xParameters = xParameters
}

/// E-Mail address of the attendee
Expand All @@ -241,23 +280,23 @@ public struct Attendee {

/// Role of the attendee, the default value is `.requiredParticipant`
public var role: Role = .requiredParticipant

/// Group membership.
///
/// See [RFC 5545 Section 3.2.11](https://tools.ietf.org/html/rfc5545#section-3.2.11) for more details
public var member: CalendarUserAddress?

/// List for users the attendance has been delegated to
/// List for users the attendance has been delegated to.
///
/// See [RFC 5545 Section 3.2.4](https://tools.ietf.org/html/rfc5545#section-3.2.5) for more details
public var delegatedTo: [CalendarUserAddress]?

/// List for users the attendance has been delegated from
/// List for users the attendance has been delegated from.
///
/// See [RFC 5545 Section 3.2.4](https://tools.ietf.org/html/rfc5545#section-3.2.4) for more details
public var delegatedFrom: [CalendarUserAddress]?

/// User that has sent the invitation
/// User that has sent the invitation.
///
/// See [RFC 5545 Section 3.2.18](https://tools.ietf.org/html/rfc5545#section-3.2.18) for more details
public var sentBy: CalendarUserAddress?
Expand All @@ -268,6 +307,9 @@ public struct Attendee {

/// Property if the attendee is requested to send
public var rsvp: Bool

/// Custom X parameters
public var xParameters: [String: String] = [:]
}

extension Attendee: LibicalPropertyConvertible {
Expand All @@ -276,6 +318,10 @@ extension Attendee: LibicalPropertyConvertible {
if type != .individual {
icalproperty_add_parameter(property, type.libicalProperty())
}

if let member = member {
icalproperty_add_parameter(property, icalparameter_new_member(member))
}

if participationStatus != .needsAction {
icalproperty_add_parameter(property, participationStatus.libicalParameter())
Expand Down Expand Up @@ -306,6 +352,12 @@ extension Attendee: LibicalPropertyConvertible {
if rsvp == true {
icalproperty_add_parameter(property, icalparameter_new_rsvp(ICAL_RSVP_TRUE))
}

for xParameter in xParameters {
let param = icalparameter_new_from_string("\(xParameter.key)=\(xParameter.value)")
icalproperty_add_parameter(property, param)
}

return property!
}
}
Expand All @@ -318,25 +370,34 @@ public struct Organizer {
self.commonName = commonName
self.sentBy = sentBy
}



/// E-Mail address of the Organizer
public var address: CalendarUserAddress

/// Name of the Organizer
public var commonName: CommonName?
public var sentBy: CalendarUserAddress?

/// Custom X parameters
public var xParameters: [String: String] = [:]
}

extension Organizer: LibicalPropertyConvertible {
func libicalProperty() -> LibicalProperty {
let property = icalproperty_new_organizer(self.address)
let property = icalproperty_new_organizer(self.address.mailtoAddress)

if let commonName = commonName {
icalproperty_add_parameter(property, icalparameter_new_cn(commonName))
}
if let sentBy = sentBy {
icalproperty_add_parameter(property, icalparameter_new_sentby(sentBy))
icalproperty_add_parameter(property, icalparameter_new_sentby(sentBy.mailtoAddress))
}

for xParameter in xParameters {
let param = icalparameter_new_from_string("\(xParameter.key)=\(xParameter.value)")
icalproperty_add_parameter(property, param)
}

return property!
}
}
Expand All @@ -356,8 +417,6 @@ extension Transparency: LibicalPropertyConvertible {
return icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT)
}
}


}

public struct VEvent {
Expand All @@ -367,6 +426,8 @@ public struct VEvent {
self.dtstart = dtstart
self.dtend = dtend
}

public var useTZIDPrefix = true

/// A short summary or subject for the calendar component.
///
Expand All @@ -387,16 +448,21 @@ public struct VEvent {
public var uid: String = UUID().uuidString

public var created: Date = Date()

public var recurranceRule: RecurranceRule?

public var duration: TimeInterval?
public var duration: Duration?

public var attendees: [Attendee]? = nil

public var organizer: Organizer? = nil

public var transparency: Transparency = .opaque

public var alarm: VAlarm? = nil

/// Custom X properties
public var xProperties: [String: String] = [:]
}

extension VEvent: LibicalComponentConvertible {
Expand All @@ -409,17 +475,30 @@ extension VEvent: LibicalComponentConvertible {
let dtstartProperty = icalproperty_new_dtstart(dtstart.date!.icalTime(timeZone: dtstart.timeZone ?? .utc))

if let timezone = dtstart.timeZone {
icalproperty_add_parameter(dtstartProperty, icalparameter_new_tzid(String(cString: icaltimezone_tzid_prefix()!) + timezone.identifier))
if useTZIDPrefix {
icalproperty_add_parameter(dtstartProperty, icalparameter_new_tzid(String(cString: icaltimezone_tzid_prefix()!) + timezone.identifier))
} else {
icalproperty_add_parameter(dtstartProperty, icalparameter_new_tzid(timezone.identifier))
}
}
icalcomponent_add_property(comp, dtstartProperty)

if let dtend = dtend {
let dtendProperty = icalproperty_new_dtend(dtend.date!.icalTime(timeZone: dtend.timeZone ?? .utc))
if let timezone = dtend.timeZone {
icalproperty_add_parameter(dtendProperty, icalparameter_new_tzid(String(cString: icaltimezone_tzid_prefix()!) + timezone.identifier))
if useTZIDPrefix {
icalproperty_add_parameter(dtendProperty, icalparameter_new_tzid(String(cString: icaltimezone_tzid_prefix()!) + timezone.identifier))
} else {
icalproperty_add_parameter(dtendProperty, icalparameter_new_tzid(timezone.identifier))
}
}
icalcomponent_add_property(comp, dtendProperty)
}

if let duration = duration {
let duration = icaldurationtype(is_neg: 0, days: UInt32(duration.days), weeks: UInt32(duration.weeks), hours: UInt32(duration.hours), minutes: UInt32(duration.minutes), seconds: UInt32(duration.seconds))
icalcomponent_add_property(comp, icalproperty_new_duration(duration))
}

icalcomponent_add_property(comp, icalproperty_new_summary(summary))
icalcomponent_add_property(comp, icalproperty_new_uid(uid))
Expand All @@ -437,7 +516,100 @@ extension VEvent: LibicalComponentConvertible {
if let organizer = organizer {
icalcomponent_add_property(comp, organizer.libicalProperty())
}

if let alarm = alarm {
icalcomponent_add_component(comp, alarm.libicalComponent())
}

for xProperty in xProperties {
let param = icalproperty_new_x(xProperty.value)
icalproperty_set_x_name(param, xProperty.key)
icalcomponent_add_property(comp, param)
}

return comp!
}
}

public struct Duration {
public let seconds: Int
public let minutes: Int
public let hours: Int
public let days: Int
public let weeks: Int

public init(seconds: Int, minutes: Int, hours: Int, days: Int, weeks: Int) {
self.seconds = seconds
self.minutes = minutes
self.hours = hours
self.days = days
self.weeks = weeks
}
}

public enum AlarmTrigger {
case duration(duration: Duration)
case time(date: DateComponents)
}

public struct AlarmFrequent {
let frequent: Int
let duration: Duration
}

public enum AlarmAction {
case display(description: String)
case email(summary: String, description: String, attendees: [Attendee])
}

public struct VAlarm {
public var trigger: AlarmTrigger
public var action: AlarmAction
public var frequent: AlarmFrequent?

public init(trigger: AlarmTrigger, action: AlarmAction) {
self.trigger = trigger
self.action = action
}
}

extension VAlarm: LibicalComponentConvertible {
func libicalComponent() -> LibicalComponent {
let alarm = icalcomponent_new_valarm()

var triggertype = icaltriggertype()
switch trigger {
case .duration(duration: let duration):
let duration = icaldurationtype(is_neg: 1, days: UInt32(duration.days), weeks: UInt32(duration.weeks), hours: UInt32(duration.hours), minutes: UInt32(duration.minutes), seconds: UInt32(duration.seconds))
triggertype.duration = duration
triggertype.time = icaltime_null_time()
case .time(date: let date):
triggertype.duration = icaldurationtype_null_duration()
triggertype.time = date.date!.icalTime(timeZone: date.timeZone ?? .utc)
}

let trigger = icalproperty_new_trigger(triggertype)
icalcomponent_add_property(alarm, trigger)

switch action {
case .display(description: let description):
icalcomponent_add_property(alarm, icalproperty_new_action(ICAL_ACTION_DISPLAY));
icalcomponent_add_property(alarm, icalproperty_new_description(description));
case .email(summary: let summary, description: let description, attendees: let attendees):
icalcomponent_add_property(alarm, icalproperty_new_action(ICAL_ACTION_EMAIL));
icalcomponent_add_property(alarm, icalproperty_new_summary(summary));
icalcomponent_add_property(alarm, icalproperty_new_description(description));
attendees.forEach({ (attendee) in
icalcomponent_add_property(alarm, attendee.libicalProperty())
})
}

if let frequent = frequent {
let duration = icaldurationtype(is_neg: 0, days: UInt32(frequent.duration.days), weeks: UInt32(frequent.duration.weeks), hours: UInt32(frequent.duration.hours), minutes: UInt32(frequent.duration.minutes), seconds: UInt32(frequent.duration.seconds))
icalcomponent_add_property(alarm, icalproperty_new_duration(duration))
icalcomponent_add_property(alarm, icalproperty_new_repeat(Int32(frequent.frequent)));
}

return alarm!
}
}
Loading