Skip to content

Commit

Permalink
feat(ios): add support to universal links
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed Jun 28, 2023
1 parent 50e69d7 commit c4f750f
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changes/ios-universal-links.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": minor:feat
---

Handle universal links on iOS and send `Event::Opened { event: OpenEvent::Url(url) }`.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ serde = { version = "1", optional = true, features = [ "serde_derive" ] }
raw-window-handle = "0.5"
bitflags = "1"
crossbeam-channel = "0.5"
url = "2"

[dev-dependencies]
image = "0.24"
Expand Down
15 changes: 15 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ pub enum Event<'a, T: 'static> {
/// This is irreversable - if this event is emitted, it is guaranteed to be the last event that
/// gets emitted. You generally want to treat this as an "do on quit" event.
LoopDestroyed,

/// Emitted when the app is opening an URL.
Opened { event: OpenEvent },
}

/// What the app is opening.
#[derive(Debug, PartialEq, Clone)]
pub enum OpenEvent {
/// App is opening an URL.
Url(url::Url),
}

impl<T: Clone> Clone for Event<'static, T> {
Expand Down Expand Up @@ -207,6 +217,9 @@ impl<T: Clone> Clone for Event<'static, T> {
position: *position,
},
GlobalShortcutEvent(accelerator_id) => GlobalShortcutEvent(*accelerator_id),
Opened { event } => Opened {
event: event.clone(),
},
}
}
}
Expand Down Expand Up @@ -246,6 +259,7 @@ impl<'a, T> Event<'a, T> {
position,
}),
GlobalShortcutEvent(accelerator_id) => Ok(GlobalShortcutEvent(accelerator_id)),
Opened { event } => Ok(Opened { event }),
}
}

Expand Down Expand Up @@ -287,6 +301,7 @@ impl<'a, T> Event<'a, T> {
position,
}),
GlobalShortcutEvent(accelerator_id) => Some(GlobalShortcutEvent(accelerator_id)),
Opened { event } => Some(Opened { event }),
}
}
}
Expand Down
42 changes: 40 additions & 2 deletions src/platform_impl/ios/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright 2021-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0

use std::collections::HashMap;
use std::{collections::HashMap, ffi::c_char};

use objc::{
declare::ClassDecl,
Expand All @@ -11,7 +11,7 @@ use objc::{

use crate::{
dpi::PhysicalPosition,
event::{DeviceId as RootDeviceId, Event, Force, Touch, TouchPhase, WindowEvent},
event::{DeviceId as RootDeviceId, Event, Force, OpenEvent, Touch, TouchPhase, WindowEvent},
platform::ios::MonitorHandleExtIOS,
platform_impl::platform::{
app_state::{self, OSCapabilities},
Expand Down Expand Up @@ -555,6 +555,39 @@ pub fn create_delegate_class() {
YES
}

// universal links
extern "C" fn application_continue(
_: &mut Object,
_: Sel,
_application: id,
user_activity: id,
_restoration_handler: id,
) -> BOOL {
unsafe {
let webpage_url: id = msg_send![user_activity, webpageURL];
if webpage_url == nil {
return false;
}
let absolute_url: id = msg_send![webpage_url, absoluteString];
let bytes = {
let bytes: *const c_char = msg_send![absolute_url, UTF8String];
bytes as *const u8
};

// 4 represents utf8 encoding
let len = msg_send![absolute_url, lengthOfBytesUsingEncoding: 4];
let bytes = std::slice::from_raw_parts(bytes, len);

let url = url::Url::parse(std::str::from_utf8(bytes).unwrap()).unwrap();

app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Opened {
event: OpenEvent::Url(url),
}));

YES
}
}

extern "C" fn did_become_active(_: &Object, _: Sel, _: id) {
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) }
}
Expand Down Expand Up @@ -600,6 +633,11 @@ pub fn create_delegate_class() {
did_finish_launching as extern "C" fn(&mut Object, Sel, id, id) -> BOOL,
);

decl.add_method(
sel!(application:continueUserActivity:restorationHandler:),
application_continue as extern "C" fn(&mut Object, Sel, id, id, id) -> BOOL,
);

decl.add_method(
sel!(applicationDidBecomeActive:),
did_become_active as extern "C" fn(&Object, Sel, id),
Expand Down

0 comments on commit c4f750f

Please sign in to comment.