Skip to content

Commit eaa8a19

Browse files
hopleusdeptyped
andauthored
Add support for BiometricManager (#20)
* Implement BiometricManager * Implement BiometricManager * Implement BiometricManager (Updated README) * Consistent naming, make exported refs read-only * Simplify code * Remove slot support, #21 * Update docs --------- Co-authored-by: deptyped <deptyped@gmail.com>
1 parent 3f717b1 commit eaa8a19

File tree

11 files changed

+256
-16
lines changed

11 files changed

+256
-16
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ import { Alert } from 'vue-tg'
8585

8686
- [Alert](https://vue-tg.pages.dev/mini-apps.html#alert)
8787
- [BackButton](https://vue-tg.pages.dev/mini-apps.html#backbutton)
88+
- [BiometricManager](https://vue-tg.pages.dev/mini-apps.html#biometricmanager)
8889
- [ClosingConfirmation](https://vue-tg.pages.dev/mini-apps.html#closingconfirmation)
8990
- [Confirm](https://vue-tg.pages.dev/mini-apps.html#confirm)
9091
- [ExpandedViewport](https://vue-tg.pages.dev/mini-apps.html#expandedviewport)
@@ -97,6 +98,7 @@ import { Alert } from 'vue-tg'
9798

9899
- [useWebApp](https://vue-tg.pages.dev/mini-apps.html#usewebapp)
99100
- [useWebAppBackButton](https://vue-tg.pages.dev/mini-apps.html#usewebappbackbutton)
101+
- [useWebAppBiometricManager](https://vue-tg.pages.dev/mini-apps.html#usewebappgiometricmanager)
100102
- [useWebAppClipboard](https://vue-tg.pages.dev/mini-apps.html#usewebappclipboard)
101103
- [useWebAppClosingConfirmation](https://vue-tg.pages.dev/mini-apps.html#usewebappclosingconfirmation)
102104
- [useWebAppCloudStorage](https://vue-tg.pages.dev/mini-apps.html#usewebappcloudstorage)

demo/App.vue

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
<script lang="ts" setup>
2-
import { useWebApp, useWebAppHapticFeedback, useWebAppMainButton, useWebAppNavigation, useWebAppPopup, useWebAppQrScanner, useWebAppTheme, useWebAppViewport } from '../src'
2+
import {
3+
useWebApp,
4+
useWebAppHapticFeedback,
5+
useWebAppMainButton,
6+
useWebAppNavigation,
7+
useWebAppPopup,
8+
useWebAppQrScanner,
9+
useWebAppTheme,
10+
useWebAppViewport,
11+
useWebAppBiometricManager,
12+
} from '../src'
313
414
const { version, platform, initData, initDataUnsafe, sendData } = useWebApp()
515
const { expand, isExpanded, viewportHeight, viewportStableHeight } = useWebAppViewport()
@@ -21,6 +31,18 @@ const {
2131
const { colorScheme, themeParams, headerColor, backgroundColor } = useWebAppTheme()
2232
const { impactOccurred, notificationOccurred, selectionChanged } = useWebAppHapticFeedback()
2333
const { showScanQrPopup } = useWebAppQrScanner()
34+
const {
35+
isBiometricInited,
36+
isBiometricAccessRequested,
37+
isBiometricAccessGranted,
38+
isBiometricTokenSaved,
39+
isBiometricAvailable,
40+
biometricDeviceId,
41+
initBiometric,
42+
requestBiometricAccess,
43+
authenticateBiometric,
44+
openBiometricSettings,
45+
} = useWebAppBiometricManager()
2446
2547
function toggleMainButton() {
2648
isMainButtonVisible.value
@@ -33,6 +55,24 @@ function toggleMainButtonProgress() {
3355
? hideMainButtonProgress()
3456
: showMainButtonProgress(true)
3557
}
58+
59+
function initBiometricManager() {
60+
initBiometric(() => console.log('init: isAccessGranted'))
61+
}
62+
63+
function requestAccessBiometricManager() {
64+
requestBiometricAccess({})
65+
}
66+
67+
function authenticateBiometricManager() {
68+
authenticateBiometric({}, (isAuthenticated) => {
69+
showAlert(`isAuthenticated: ${isAuthenticated}`)
70+
})
71+
}
72+
73+
function openSettingsBiometricManager() {
74+
openBiometricSettings()
75+
}
3676
</script>
3777

3878
<template>
@@ -261,6 +301,27 @@ function toggleMainButtonProgress() {
261301
<pre><code>{{ themeParams }}</code></pre>
262302
</div>
263303

304+
<div>
305+
<h4>Biometric Manager</h4>
306+
<p>isBiometricInited: {{ isBiometricInited }}</p>
307+
<p>isBiometricAccessRequested: {{ isBiometricAccessRequested }}</p>
308+
<p>isBiometricAccessGranted: {{ isBiometricAccessGranted }}</p>
309+
<p>isBiometricTokenSaved: {{ isBiometricTokenSaved }}</p>
310+
<p>isBiometricAvailable: {{ isBiometricAvailable }}</p>
311+
<p>biometricDeviceId: {{ biometricDeviceId }}</p>
312+
313+
<button @click.prevent="initBiometricManager">Init</button>
314+
<button @click.prevent="requestAccessBiometricManager">
315+
request access
316+
</button>
317+
<button @click.prevent="authenticateBiometricManager">
318+
authenticate
319+
</button>
320+
<button @click.prevent="openSettingsBiometricManager">
321+
open settings
322+
</button>
323+
</div>
324+
264325
<div>
265326
Version: {{ version }}
266327
<br>

docs/mini-apps.md

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ outline: [2, 3]
1313

1414
<!--@include: @/mini-apps/components/back-button.md-->
1515

16+
<!--@include: @/mini-apps/components/biometric-manager.md-->
17+
1618
<!--@include: @/mini-apps/components/closing-confirmation.md-->
1719

1820
<!--@include: @/mini-apps/components/confirm.md-->
@@ -48,6 +50,7 @@ outline: [2, 3]
4850
| BackButton | [useWebAppBackButton](#usewebappbackbutton) |
4951
| MainButton | [useWebAppMainButton](#usewebappmainbutton) |
5052
| HapticFeedback | [useWebAppHapticFeedback](#usewebapphapticfeedback) |
53+
| BiometricManager | [useWebAppBiometricManager](#usewebappbiometricmanager) |
5154
| isVersionAtLeast | [useWebApp](#usewebapp) |
5255
| setHeaderColor | [useWebAppTheme](#usewebapptheme) |
5356
| setBackgroundColor | [useWebAppTheme](#usewebapptheme) |
@@ -88,24 +91,29 @@ onThemeChanged(() => {
8891

8992
#### Mapping
9093

91-
| Event name | Handler |
92-
| --------------------- | ----------------------------------------------------------------------------- |
93-
| themeChanged | [useWebAppTheme → onThemeChanged](#usewebapptheme) |
94-
| viewportChanged | [useWebAppViewport → onViewportChanged](#usewebappviewport) |
95-
| mainButtonClicked | [useWebAppMainButton → onMainButtonClicked](#usewebappmainbutton) |
96-
| backButtonClicked | [useWebAppBackButton → onBackButtonClicked](#usewebappbackbutton) |
97-
| settingsButtonClicked | [useWebAppSettingsButton → onSettingsButtonClicked](#usewebappsettingsbutton) |
98-
| invoiceClosed | [useWebAppNavigation → onInvoiceClosed](#usewebappnavigation) |
99-
| popupClosed | [useWebAppPopup → onPopupClosed](#usewebapppopup) |
100-
| qrTextReceived | [useWebAppQrScanner → onQrTextReceived](#usewebappqrscanner) |
101-
| clipboardTextReceived | [useWebAppClipboard → onClipboardTextReceived](#usewebappclipboard) |
102-
| writeAccessRequested | [useWebAppRequests → onWriteAccessRequested](#usewebapprequests) |
103-
| contactRequested | [useWebAppRequests → onContactRequested](#usewebapprequests) |
94+
| Event name | Handler |
95+
|-------------------------|-------------------------------------------------------------------------------------|
96+
| themeChanged | [useWebAppTheme → onThemeChanged](#usewebapptheme) |
97+
| viewportChanged | [useWebAppViewport → onViewportChanged](#usewebappviewport) |
98+
| mainButtonClicked | [useWebAppMainButton → onMainButtonClicked](#usewebappmainbutton) |
99+
| backButtonClicked | [useWebAppBackButton → onBackButtonClicked](#usewebappbackbutton) |
100+
| settingsButtonClicked | [useWebAppSettingsButton → onSettingsButtonClicked](#usewebappsettingsbutton) |
101+
| invoiceClosed | [useWebAppNavigation → onInvoiceClosed](#usewebappnavigation) |
102+
| popupClosed | [useWebAppPopup → onPopupClosed](#usewebapppopup) |
103+
| qrTextReceived | [useWebAppQrScanner → onQrTextReceived](#usewebappqrscanner) |
104+
| clipboardTextReceived | [useWebAppClipboard → onClipboardTextReceived](#usewebappclipboard) |
105+
| writeAccessRequested | [useWebAppRequests → onWriteAccessRequested](#usewebapprequests) |
106+
| contactRequested | [useWebAppRequests → onContactRequested](#usewebapprequests) |
107+
| biometricManagerUpdated | [useWebAppBiometricManager → onBiometricManagerUpdated](#usewebappbiometricmanager) |
108+
| biometricAuthRequested | [useWebAppBiometricManager → onBiometricAuthRequested](#usewebappbiometricmanager) |
109+
| biometricTokenUpdated | [useWebAppBiometricManager → onBiometricTokenUpdated](#usewebappbiometricmanager) |
104110

105111
<!--@include: @/mini-apps/composables/use-web-app.md-->
106112

107113
<!--@include: @/mini-apps/composables/use-web-app-back-button.md-->
108114

115+
<!--@include: @/mini-apps/composables/use-web-app-biometric-manager.md-->
116+
109117
<!--@include: @/mini-apps/composables/use-web-app-clipboard.md-->
110118

111119
<!--@include: @/mini-apps/composables/use-web-app-closing-confirmation.md-->
@@ -211,3 +219,24 @@ onThemeChanged(() => {
211219
| :----------------- | :------------------------- |
212220
| `eventData` | `Object` |
213221
| `eventData.status` | `"allowed" \| "cancelled"` |
222+
223+
### OnBiometricAuthRequested
224+
225+
Ƭ **OnBiometricAuthRequested**: `(eventData) => void`
226+
227+
##### Parameters
228+
229+
| Name | Type |
230+
|:------------------|:----------------------|
231+
| `isAuthenticated` | `boolean` |
232+
| `biometricToken` | `string \| undefined` |
233+
234+
### OnBiometricTokenUpdated
235+
236+
Ƭ **OnBiometricTokenUpdated**: `(eventData) => void`
237+
238+
##### Parameters
239+
240+
| Name | Type |
241+
|:------------|:----------|
242+
| `isUpdated` | `boolean` |
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
### BiometricManager
2+
3+
A component that init the biometric manager when is rendered.
4+
5+
```vue
6+
<script lang="ts" setup>
7+
import { BiometricManager } from 'vue-tg'
8+
9+
const handleInit = () => {
10+
// ...
11+
}
12+
</script>
13+
14+
<template>
15+
<BiometricManager @init="handleInit" />
16+
</template>
17+
```
18+
19+
#### Events
20+
21+
| Name | Type | Description |
22+
| ---- | ------------ | ----------------------------------------- |
23+
| init | `() => void` | Emits when the biometric manager is init. |
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
### useWebAppBiometricManager
2+
3+
```ts
4+
import { useWebAppBiometricManager } from 'vue-tg'
5+
```
6+
7+
**useWebAppBiometricManager**(): `Object`
8+
9+
#### Returns
10+
11+
| Name | Type |
12+
| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
13+
| `isBiometricInited` | `Readonly<Ref<boolean>>` |
14+
| `isBiometricAvailable` | `Readonly<Ref<boolean>>` |
15+
| `biometricType` | `Readonly<Ref<"finger" \| "face" \| "unknown">>` |
16+
| `isBiometricAccessRequested` | `Readonly<Ref<boolean>>` |
17+
| `isBiometricAccessGranted` | `Readonly<Ref<boolean>>` |
18+
| `isBiometricTokenSaved` | `Readonly<Ref<boolean>>` |
19+
| `biometricDeviceId` | `Readonly<Ref<string>>` |
20+
| `initBiometric` | `(callback?: () => void) => void` |
21+
| `requestBiometricAccess` | `(params: BiometricRequestAccessParams, callback?: (isAccessGranted: boolean) => void) => void` |
22+
| `authenticateBiometric` | `(params: BiometricAuthenticateParams, callback?: (isAuthenticated: boolean, biometricToken?: string) => void) => void` |
23+
| `updateBiometricToken` | `(token: string, callback?: (applied: boolean) => void) => void` |
24+
| `openBiometricSettings` | `() => void` |
25+
| `onBiometricManagerUpdated` | `(eventHandler: () => void) => void` |
26+
| `onBiometricAuthRequested` | `(eventHandler: `[`OnBiometricAuthRequested`](#onbiometricauthrequested)`)) => void` |
27+
| `onBiometricTokenUpdated` | `(eventHandler: `[`OnBiometricTokenUpdated`](#onbiometrictokenupdated)`)) => void` |

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-tg",
3-
"version": "0.4.0",
3+
"version": "0.5.0",
44
"description": "Telegram integration for Vue",
55
"author": "deptyped <deptyped@gmail.com>",
66
"license": "MIT",
@@ -49,7 +49,7 @@
4949
"docs:preview": "vitepress preview docs"
5050
},
5151
"dependencies": {
52-
"@types/telegram-web-app": "^7.0.0",
52+
"@types/telegram-web-app": "^7.2.0",
5353
"vue": "^3"
5454
},
5555
"devDependencies": {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts" setup>
2+
import { onMounted } from "vue"
3+
import { useWebAppBiometricManager } from ".."
4+
5+
const emit = defineEmits<{
6+
(eventName: "init"): void
7+
}>()
8+
9+
const { initBiometric } = useWebAppBiometricManager()
10+
11+
onMounted(() => initBiometric(() => emit("init")))
12+
</script>
13+
14+
<template></template>

src/composables/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export { useWebApp } from "./useWebApp"
22
export { useWebAppBackButton } from "./useWebAppBackButton"
3+
export { useWebAppBiometricManager } from "./useWebAppBiometricManager"
34
export { useWebAppClipboard } from "./useWebAppClipboard"
45
export { useWebAppClosingConfirmation } from "./useWebAppClosingConfirmation"
56
export { useWebAppCloudStorage } from "./useWebAppCloudStorage"
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { readonly, ref } from "vue"
2+
import { OnBiometricAuthRequested, OnBiometricTokenUpdated } from "~/types"
3+
import { useWebApp } from "./useWebApp"
4+
5+
const {
6+
init,
7+
requestAccess,
8+
authenticate,
9+
updateBiometricToken,
10+
openSettings,
11+
} = Telegram.WebApp.BiometricManager
12+
13+
const isBiometricInited = ref(Telegram.WebApp.BiometricManager.isInited)
14+
const isBiometricAvailable = ref(
15+
Telegram.WebApp.BiometricManager.isBiometricAvailable,
16+
)
17+
const biometricType = ref(Telegram.WebApp.BiometricManager.biometricType)
18+
const isBiometricAccessRequested = ref(
19+
Telegram.WebApp.BiometricManager.isAccessRequested,
20+
)
21+
const isBiometricAccessGranted = ref(
22+
Telegram.WebApp.BiometricManager.isAccessGranted,
23+
)
24+
const isBiometricTokenSaved = ref(
25+
Telegram.WebApp.BiometricManager.isAccessGranted,
26+
)
27+
const biometricDeviceId = ref(Telegram.WebApp.BiometricManager.deviceId)
28+
29+
function updateState() {
30+
isBiometricInited.value = Telegram.WebApp.BiometricManager.isInited
31+
isBiometricAvailable.value =
32+
Telegram.WebApp.BiometricManager.isBiometricAvailable
33+
biometricType.value = Telegram.WebApp.BiometricManager.biometricType
34+
isBiometricAccessRequested.value =
35+
Telegram.WebApp.BiometricManager.isAccessRequested
36+
isBiometricAccessGranted.value =
37+
Telegram.WebApp.BiometricManager.isAccessGranted
38+
biometricDeviceId.value = Telegram.WebApp.BiometricManager.deviceId
39+
isBiometricTokenSaved.value =
40+
Telegram.WebApp.BiometricManager.isBiometricTokenSaved
41+
}
42+
43+
export function useWebAppBiometricManager() {
44+
const { onEvent } = useWebApp()
45+
46+
const onBiometricManagerUpdated = (eventHandler: () => void) =>
47+
onEvent("biometricManagerUpdated", eventHandler)
48+
const onBiometricAuthRequested = (eventHandler: OnBiometricAuthRequested) =>
49+
onEvent("biometricAuthRequested", eventHandler)
50+
const onBiometricTokenUpdated = (eventHandler: OnBiometricTokenUpdated) =>
51+
onEvent("biometricTokenUpdated", eventHandler)
52+
53+
onBiometricManagerUpdated(updateState)
54+
55+
return {
56+
isBiometricInited: readonly(isBiometricInited),
57+
isBiometricAvailable: readonly(isBiometricAvailable),
58+
biometricType: readonly(biometricType),
59+
isBiometricAccessRequested: readonly(isBiometricAccessRequested),
60+
isBiometricAccessGranted: readonly(isBiometricAccessGranted),
61+
isBiometricTokenSaved: readonly(isBiometricTokenSaved),
62+
biometricDeviceId: readonly(biometricDeviceId),
63+
initBiometric: init,
64+
requestBiometricAccess: requestAccess,
65+
authenticateBiometric: authenticate,
66+
updateBiometricToken,
67+
openBiometricSettings: openSettings,
68+
onBiometricManagerUpdated,
69+
onBiometricAuthRequested,
70+
onBiometricTokenUpdated,
71+
}
72+
}

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { App } from "vue"
22

33
import Alert from "./components/Alert.vue"
44
import BackButton from "./components/BackButton.vue"
5+
import BiometricManager from "./components/BiometricManager.vue"
56
import ClosingConfirmation from "./components/ClosingConfirmation.vue"
67
import Confirm from "./components/Confirm.vue"
78
import ExpandedViewport from "./components/ExpandedViewport.vue"
@@ -17,6 +18,7 @@ import DiscussionWidget from "./widgets/DiscussionWidget.vue"
1718
export {
1819
Alert,
1920
BackButton,
21+
BiometricManager,
2022
ClosingConfirmation,
2123
Confirm,
2224
ExpandedViewport,
@@ -38,6 +40,7 @@ const plugin = {
3840
install(Vue: App) {
3941
Vue.component("TgAlert", Alert)
4042
Vue.component("TgBackButton", BackButton)
43+
Vue.component("TgBiometricManager", BiometricManager)
4144
Vue.component("TgClosingConfirmation", ClosingConfirmation)
4245
Vue.component("TgConfirm", Confirm)
4346
Vue.component("TgExpandedViewport", ExpandedViewport)
@@ -56,6 +59,7 @@ declare module "@vue/runtime-core" {
5659
export interface GlobalComponents {
5760
TgAlert: typeof Alert
5861
TgBackButton: typeof BackButton
62+
TgBiometricManager: typeof BiometricManager
5963
TgClosingConfirmation: typeof ClosingConfirmation
6064
TgConfirm: typeof Confirm
6165
TgExpandedViewport: typeof ExpandedViewport

0 commit comments

Comments
 (0)