Skip to content

Commit

Permalink
Fix serde_with usage and update sound support (WalletConnect#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacob Lee committed Nov 15, 2022
1 parent d6c081e commit c22510e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -12,7 +12,7 @@ reqwest-middleware = "0.1.6"
serde = { version = "1.0.147", features = ["derive"] }
serde_json = "1.0.87"
serde_repr = "0.1.9"
serde_with = "2.0.1"
serde_with = { version = "2.0.1", features = ["time_0_3"] }
thiserror = "1.0.37"
time = { version = "0.3.16", features = ["serde"] }
url = "2.3.1"
Expand Down
33 changes: 27 additions & 6 deletions src/apns/mod.rs
Expand Up @@ -164,7 +164,7 @@ pub struct ApnsRequest<T> {
///
/// Specify 1 to prioritize the device’s power considerations over all other
/// factors for delivery, and prevent awakening the device.
pub apns_priority: Option<ApnsPriority>,
pub apns_priority: ApnsPriority,

/// The topic for the notification. In general, the topic is your app’s
/// bundle ID/app ID. It can have a suffix based on the type of push
Expand Down Expand Up @@ -213,14 +213,14 @@ pub struct ApnsRequest<T> {
/// specify the value `1` and don’t include the `alert`, `badge`, or `sound`
/// keys in your payload. See [Pushing Background Updates to Your
/// App](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app).
pub content_available: Option<bool>,
pub content_available: bool,

/// The notification service app extension flag. If the value is `1`, the
/// system passes the notification to your notification service app
/// extension before delivery. Use your extension to modify the
/// notification’s content. See [Modifying Content in Newly Delivered
/// Notifications](https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications).
pub mutable_content: Option<bool>,
pub mutable_content: bool,

/// The identifier of the window brought forward. The value of this key will
/// be populated on the
Expand Down Expand Up @@ -269,8 +269,8 @@ where
let _ = headers.insert(APNS_EXPIRATION.clone(), apns_expiration);
}

if let Some(apns_priority) = this.apns_priority {
let _ = headers.insert(APNS_PRIORITY.clone(), apns_priority.into());
if this.apns_priority != ApnsPriority::default() {
let _ = headers.insert(APNS_PRIORITY.clone(), this.apns_priority.into());
}

if let Some(apns_topic) = this.apns_topic {
Expand All @@ -283,10 +283,31 @@ where
let _ = headers.insert(APNS_COLLAPSE_ID.clone(), apns_collapse_id);
}

let is_critical = this
.interruption_level
.as_ref()
.map(|il| *il == InterruptionLevel::Critical)
.unwrap_or_default();

let is_critical_sound = this
.sound
.as_ref()
.map(|sound| sound.critical)
.unwrap_or_default();

if is_critical != is_critical_sound {
return Err(Error::CriticalSound);
}

let sound = this.sound.map(|mut sound| {
sound.critical = is_critical || is_critical_sound;
sound.into()
});

let payload = ApnsPayload {
alert: this.alert.map(Into::into),
badge: this.badge,
sound: this.sound.map(Into::into),
sound,
thread_id: this.thread_id,
category: this.category,
content_available: this.content_available,
Expand Down
50 changes: 33 additions & 17 deletions src/apns/request.rs
@@ -1,15 +1,19 @@
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, skip_serializing_none};
use serde_with::{serde_as, skip_serializing_none, BoolFromInt};

fn is_false(v: &bool) -> bool {
!v
}

/// Put the JSON payload with the notification’s content into the body of your
/// request. The JSON payload must not be compressed and is limited to a maximum
/// size of 4 KB (4096 bytes). For a Voice over Internet Protocol (VoIP)
/// notification, the maximum size is 5 KB (5120 bytes).
#[derive(Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
#[serde_as]
#[skip_serializing_none]
pub struct ApnsPayload<T>
#[derive(Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct ApnsPayload<T = ()>
where
T: Serialize,
{
Expand Down Expand Up @@ -42,16 +46,18 @@ where
/// specify the value `1` and don’t include the `alert`, `badge`, or `sound`
/// keys in your payload. See [Pushing Background Updates to Your
/// App](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app).
#[serde(skip_serializing_if = "is_false")]
#[serde_as(as = "BoolFromInt")]
pub content_available: Option<bool>,
pub content_available: bool,

/// The notification service app extension flag. If the value is `1`, the
/// system passes the notification to your notification service app
/// extension before delivery. Use your extension to modify the
/// notification’s content. See [Modifying Content in Newly Delivered
/// Notifications](https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications).
#[serde(skip_serializing_if = "is_false")]
#[serde_as(as = "BoolFromInt")]
pub mutable_content: Option<bool>,
pub mutable_content: bool,

/// The identifier of the window brought forward. The value of this key will
/// be populated on the
Expand Down Expand Up @@ -169,7 +175,7 @@ impl From<Alert> for ApnsAlert {
}
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
#[derive(Debug, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ApnsSound {
/// The name of a sound file in your app’s main bundle or in the
Expand All @@ -180,37 +186,47 @@ pub enum ApnsSound {
/// [`UNNotificationSound`](https://developer.apple.com/documentation/usernotifications/unnotificationsound).
Name(String),

Sound(Sound),
Critical(Sound),
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde_as]
#[skip_serializing_none]
#[derive(Debug, PartialEq, Deserialize, Serialize)]
pub struct Sound {
/// The critical alert flag. Set to `1` to enable the critical alert.
#[serde(skip_serializing_if = "is_false")]
#[serde_as(as = "BoolFromInt")]
critical: Option<bool>,
pub critical: bool,

/// The name of a sound file in your app’s main bundle or in the
/// `Library/Sounds` folder of your app’s container directory. Specify
/// the string `default` to play the system sound. For information about
/// how to prepare sounds, see
/// [`UNNotificationSound`](https://developer.apple.com/documentation/usernotifications/unnotificationsound).
name: Option<String>,
pub name: String,

/// The volume for the critical alert’s sound. Set this to a value
/// between `0` (silent) and `1` (full volume).
volume: Option<f64>,
pub volume: f64,
}

impl Default for Sound {
fn default() -> Self {
Self {
critical: false,
name: "default".into(),
volume: 1f64,
}
}
}

impl From<Sound> for ApnsSound {
fn from(this: Sound) -> Self {
if this.critical.is_none() && this.volume.is_none() {
if let Some(name) = this.name {
return ApnsSound::Name(name);
}
if !this.critical {
ApnsSound::Name(this.name)
} else {
ApnsSound::Critical(this)
}
ApnsSound::Sound(this)
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/apns/response.rs
@@ -1,21 +1,21 @@
use http::StatusCode;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, skip_serializing_none};
use serde_with::{serde_as, skip_serializing_none, TimestampMilliSeconds};
use time::OffsetDateTime;

use crate::result::Error;

#[derive(Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[serde_as]
#[skip_serializing_none]
#[derive(Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct ApnsResponse {
/// The error code indicating the reason for the failure.
pub reason: Option<Reason>,

/// The time, in milliseconds since Epoch, at which APNs confirmed the token
/// was no longer valid for the topic. This key is included only when the
/// error in the `:status` field is 410.
#[serde_as(as = "TimestampMilliSeconds<i64>")]
#[serde_as(as = "Option<TimestampMilliSeconds>")]
pub timestamp: Option<OffsetDateTime>,
}

Expand Down
3 changes: 3 additions & 0 deletions src/result.rs
Expand Up @@ -97,6 +97,9 @@ pub enum Error {
#[error("{0}")]
ApnsOther(String),

#[error("interruption level does not match sound critical flag")]
CriticalSound,

#[error(transparent)]
InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),

Expand Down

0 comments on commit c22510e

Please sign in to comment.