-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.ts
152 lines (142 loc) · 4.08 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
* Converts a Base64-encoded data URL to a {@linkcode File} object.
*
* @param dataurl - A string representing the Base64-encoded data URL. The format should be `"data:[<MIME type>];base64,<data>"`.
* @returns A {@linkcode File} object containing the image data if the input string is valid, or `undefined` if the input is invalid.
*
* @example
* ```ts
* const dataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...";
* const imageFile = dataURLtoFile(dataUrl);
* if (imageFile) {
* console.log(imageFile.name); // "image.jpg"
* console.log(imageFile.type); // extracted MIME type (e.g., "image/png")
* }
* ```
*/
const dataURLtoFile = (dataurl: string) => {
if (!dataurl) {
return
}
const arr = dataurl.split(",")
const mime = arr[0].match(/:(.*?);/)![1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], "image.jpg", { type: mime })
}
/**
* Represents the structure for data intended to be shared across
* various platforms using Web APIs.
*/
export interface Data {
/**
* The title of the content to be shared.
* This field is mandatory and typically used as the primary label or
* identifier of the shared content.
*/
title: string
/**
* Optional text to accompany the shared content.
* This could be a description or additional text not covered by the title.
*/
text?: string
/**
* Optional URL to share. This could point to a webpage, a media file, or any
* other online resource.
*/
url?: string
/**
* An optional array of image URLs (in Base64 format or standard URLs)
* intended to be included in the share.
*/
images?: string[]
}
/**
* Shares content on mobile devices using the
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API Web Share API}.
* If the Web Share API is not available, a fallback function can be provided.
*
* @param data - The data to be shared, which includes a URL, a title, and an optional array of image URLs.
* @param fallbackFunction - An optional fallback function to be called if sharing is not possible.
*
* @example
* ```tsx
* import React from "react"
* import { shareOnMobile } from "react-mobile-share"
*
* const imgBase64 = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2..."
*
* const App = () => {
* return (
* <div>
* <button
* onClick={() =>
* shareOnMobile(
* {
* text: "Hey checkout our package react-mobile-share",
* url: "https://www.npmjs.com/package/react-mobile-share",
* title: "React-Mobile-Share",
* images: [imgBase64],
* },
* errorMessage => console.error("Share failed:", errorMessage),
* )
* }
* >
* Share
* </button>
* </div>
* )
* }
*
* export default App
* ```
*/
const shareOnMobile = (
data: Data,
fallbackFunction?: (message: string) => void
) => {
const { url, title, images, text } = data
if (navigator.share === undefined) {
fallbackFunction?.(
"Can't share on this, make sure you are running on Android or iOS devices"
)
console.error("error: navigator.share is not available")
return
}
if (!title) {
fallbackFunction?.("Title is required")
console.error("error: title is required")
return
}
const shareData: ShareData = { text, title }
if (url) {
shareData.url = url
}
if (Array.isArray(images)) {
const files = images.map(image => dataURLtoFile(image)!)
if (files) {
shareData.files = files
}
}
try {
if (navigator.canShare && navigator.canShare(shareData)) {
navigator
.share(shareData)
.then(() => console.info("Shared successful."))
.catch(error => {
fallbackFunction?.(error.message)
console.error("Sharing failed ..", error)
})
}
} catch (error) {
if (error instanceof Error) {
fallbackFunction?.(error.message)
}
console.error("error: ", error)
}
}
export { shareOnMobile }