mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-07-30 17:48:50 +02:00
feat(opener): add inAppBrowser option for iOS and Android (#2803)
This commit is contained in:
@@ -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.
|
||||||
@@ -83,6 +83,15 @@
|
|||||||
},
|
},
|
||||||
"store:default",
|
"store:default",
|
||||||
"opener:default",
|
"opener:default",
|
||||||
|
{
|
||||||
|
"identifier": "opener:allow-open-url",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"url": "https://*",
|
||||||
|
"app": "inAppBrowser"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identifier": "opener:allow-open-path",
|
"identifier": "opener:allow-open-path",
|
||||||
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
|
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import * as opener from '@tauri-apps/plugin-opener'
|
import * as opener from '@tauri-apps/plugin-opener'
|
||||||
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
|
||||||
export let onMessage
|
export let onMessage
|
||||||
|
|
||||||
let url = ''
|
let url = 'https://tauri.app'
|
||||||
let urlProgram = ''
|
let urlProgram =
|
||||||
|
platform() === 'ios' || platform() === 'android' ? 'inAppBrowser' : ''
|
||||||
function openUrl() {
|
function openUrl() {
|
||||||
opener.openUrl(url, urlProgram ? urlProgram : undefined).catch(onMessage)
|
opener.openUrl(url, urlProgram ? urlProgram : undefined).catch(onMessage)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.9.0")
|
implementation("androidx.core:core-ktx:1.9.0")
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
|
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
|
||||||
|
implementation("androidx.browser:browser:1.8.0")
|
||||||
implementation(project(":tauri-android"))
|
implementation(project(":tauri-android"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,22 +6,36 @@ package app.tauri.opener
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import androidx.browser.customtabs.CustomTabsIntent
|
||||||
import app.tauri.annotation.Command
|
import app.tauri.annotation.Command
|
||||||
import app.tauri.annotation.TauriPlugin
|
import app.tauri.annotation.TauriPlugin
|
||||||
import app.tauri.plugin.Invoke
|
import app.tauri.plugin.Invoke
|
||||||
import app.tauri.plugin.Plugin
|
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
|
@TauriPlugin
|
||||||
class OpenerPlugin(private val activity: Activity) : Plugin(activity) {
|
class OpenerPlugin(private val activity: Activity) : Plugin(activity) {
|
||||||
@Command
|
@Command
|
||||||
fun open(invoke: Invoke) {
|
fun open(invoke: Invoke) {
|
||||||
try {
|
try {
|
||||||
val url = invoke.parseArgs(String::class.java)
|
val args = invoke.parseArgs(OpenArgs::class.java)
|
||||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
if (args.with == "inAppBrowser") {
|
||||||
activity.applicationContext?.startActivity(intent)
|
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()
|
invoke.resolve()
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
invoke.reject(ex.message)
|
invoke.reject(ex.message)
|
||||||
|
|||||||
@@ -35,12 +35,14 @@ import { invoke } from '@tauri-apps/api/core'
|
|||||||
*
|
*
|
||||||
* @param url The URL to open.
|
* @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.
|
* @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
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
export async function openUrl(
|
export async function openUrl(
|
||||||
url: string | URL,
|
url: string | URL,
|
||||||
openWith?: string
|
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
||||||
|
openWith?: 'inAppBrowser' | string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await invoke('plugin:opener|open_url', {
|
await invoke('plugin:opener|open_url', {
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -3,21 +3,35 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import SafariServices
|
||||||
import SwiftRs
|
import SwiftRs
|
||||||
import Tauri
|
import Tauri
|
||||||
import UIKit
|
import UIKit
|
||||||
import WebKit
|
import WebKit
|
||||||
|
|
||||||
|
struct OpenArgs: Decodable {
|
||||||
|
let url: String
|
||||||
|
let with: String?
|
||||||
|
}
|
||||||
|
|
||||||
class OpenerPlugin: Plugin {
|
class OpenerPlugin: Plugin {
|
||||||
@objc public func open(_ invoke: Invoke) throws {
|
@objc public func open(_ invoke: Invoke) throws {
|
||||||
do {
|
do {
|
||||||
let urlString = try invoke.parseArgs(String.self)
|
let args = try invoke.parseArgs(OpenArgs.self)
|
||||||
if let url = URL(string: urlString) {
|
if let url = URL(string: args.url) {
|
||||||
if #available(iOS 10, *) {
|
if args.with == "inAppBrowser" {
|
||||||
UIApplication.shared.open(url, options: [:])
|
DispatchQueue.main.async {
|
||||||
|
let safariVC = SFSafariViewController(url: url)
|
||||||
|
self.manager.viewController?.present(safariVC, animated: true)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
UIApplication.shared.openURL(url)
|
if #available(iOS 10, *) {
|
||||||
|
UIApplication.shared.open(url, options: [:])
|
||||||
|
} else {
|
||||||
|
UIApplication.shared.openURL(url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
invoke.resolve()
|
invoke.resolve()
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ impl<R: Runtime> Opener<R> {
|
|||||||
///
|
///
|
||||||
/// ## Platform-specific:
|
/// ## Platform-specific:
|
||||||
///
|
///
|
||||||
/// - **Android / iOS**: Always opens using default program.
|
/// - **Android / iOS**: Always opens using default program, unless `with` is provided as "inAppBrowser".
|
||||||
#[cfg(desktop)]
|
#[cfg(desktop)]
|
||||||
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<()> {
|
||||||
crate::open::open(url.into(), with.map(Into::into))
|
crate::open::open(url.into(), with.map(Into::into))
|
||||||
@@ -78,11 +78,14 @@ impl<R: Runtime> Opener<R> {
|
|||||||
///
|
///
|
||||||
/// ## Platform-specific:
|
/// ## Platform-specific:
|
||||||
///
|
///
|
||||||
/// - **Android / iOS**: Always opens using default program.
|
/// - **Android / iOS**: Always opens using default program, unless `with` is provided as "inAppBrowser".
|
||||||
#[cfg(mobile)]
|
#[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
|
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)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user