Skip to content
Merged
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
6 changes: 6 additions & 0 deletions .changes/in-app-browser.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"opener": patch:feat
"opener-js": patch:feat
---

Add `inAppBrowser` option to open URLs in an in-app browser on Android and iOS.
9 changes: 9 additions & 0 deletions examples/api/src-tauri/capabilities/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@
},
"store:default",
"opener:default",
{
"identifier": "opener:allow-open-url",
"allow": [
{
"url": "https://*",
"app": "inAppBrowser"
}
]
},
{
"identifier": "opener:allow-open-path",
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
Expand Down
6 changes: 4 additions & 2 deletions examples/api/src/views/Opener.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<script>
import * as opener from '@tauri-apps/plugin-opener'
import { platform } from '@tauri-apps/plugin-os'

export let onMessage

let url = ''
let urlProgram = ''
let url = 'https://tauri.app'
let urlProgram =
platform() === 'ios' || platform() === 'android' ? 'inAppBrowser' : ''
function openUrl() {
opener.openUrl(url, urlProgram ? urlProgram : undefined).catch(onMessage)
}
Expand Down
1 change: 1 addition & 0 deletions plugins/opener/android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ android {
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
implementation("androidx.browser:browser:1.8.0")
implementation(project(":tauri-android"))
}
26 changes: 20 additions & 6 deletions plugins/opener/android/src/main/java/OpenerPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,36 @@ package app.tauri.opener

import android.app.Activity
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import app.tauri.annotation.Command
import app.tauri.annotation.TauriPlugin
import app.tauri.plugin.Invoke
import app.tauri.plugin.Plugin
import java.io.File
import androidx.core.net.toUri
import app.tauri.annotation.InvokeArg

@InvokeArg
class OpenArgs {
lateinit var url: String
var with: String? = null
}

@TauriPlugin
class OpenerPlugin(private val activity: Activity) : Plugin(activity) {
@Command
fun open(invoke: Invoke) {
try {
val url = invoke.parseArgs(String::class.java)
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.applicationContext?.startActivity(intent)
val args = invoke.parseArgs(OpenArgs::class.java)

if (args.with == "inAppBrowser") {
val builder = CustomTabsIntent.Builder()
val intent = builder.build()
intent.launchUrl(activity, args.url.toUri())
} else {
val intent = Intent(Intent.ACTION_VIEW, args.url.toUri())
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.applicationContext?.startActivity(intent)
}
invoke.resolve()
} catch (ex: Exception) {
invoke.reject(ex.message)
Expand Down
4 changes: 3 additions & 1 deletion plugins/opener/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ import { invoke } from '@tauri-apps/api/core'
*
* @param url The URL to open.
* @param openWith The app to open the URL with. If not specified, defaults to the system default application for the specified url type.
* On mobile, `openWith` can be provided as `inAppBrowser` to open the URL in an in-app browser. Otherwise, it will open the URL in the system default browser.
*
* @since 2.0.0
*/
export async function openUrl(
url: string | URL,
openWith?: string
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
openWith?: 'inAppBrowser' | string
Comment on lines +44 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need the 'inAppBrowser' | (string & {}) hack for the autocomplete to work 🙃

): Promise<void> {
await invoke('plugin:opener|open_url', {
url,
Expand Down
24 changes: 19 additions & 5 deletions plugins/opener/ios/Sources/OpenerPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,35 @@
// SPDX-License-Identifier: MIT

import Foundation
import SafariServices
import SwiftRs
import Tauri
import UIKit
import WebKit

struct OpenArgs: Decodable {
let url: String
let with: String?
}

class OpenerPlugin: Plugin {
@objc public func open(_ invoke: Invoke) throws {
do {
let urlString = try invoke.parseArgs(String.self)
if let url = URL(string: urlString) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:])
let args = try invoke.parseArgs(OpenArgs.self)
if let url = URL(string: args.url) {
if args.with == "inAppBrowser" {
DispatchQueue.main.async {
let safariVC = SFSafariViewController(url: url)
self.manager.viewController?.present(safariVC, animated: true)
}
} else {
UIApplication.shared.openURL(url)
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:])
} else {
UIApplication.shared.openURL(url)
}
}

}
invoke.resolve()
} catch {
Expand Down
11 changes: 7 additions & 4 deletions plugins/opener/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<R: Runtime> Opener<R> {
///
/// ## Platform-specific:
///
/// - **Android / iOS**: Always opens using default program.
/// - **Android / iOS**: Always opens using default program, unless `with` is provided as "inAppBrowser".
#[cfg(desktop)]
pub fn open_url(&self, url: impl Into<String>, with: Option<impl Into<String>>) -> Result<()> {
crate::open::open(url.into(), with.map(Into::into))
Expand All @@ -78,11 +78,14 @@ impl<R: Runtime> Opener<R> {
///
/// ## Platform-specific:
///
/// - **Android / iOS**: Always opens using default program.
/// - **Android / iOS**: Always opens using default program, unless `with` is provided as "inAppBrowser".
#[cfg(mobile)]
pub fn open_url(&self, url: impl Into<String>, _with: Option<impl Into<String>>) -> Result<()> {
pub fn open_url(&self, url: impl Into<String>, with: Option<impl Into<String>>) -> Result<()> {
self.mobile_plugin_handle
.run_mobile_plugin("open", url.into())
.run_mobile_plugin(
"open",
serde_json::json!({ "url": url.into(), "with": with.map(Into::into) }),
)
.map_err(Into::into)
}

Expand Down
Loading