Skip to content

Commit

Permalink
Add support for BiometricManager (#20)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
hopleus and deptyped authored Apr 2, 2024
1 parent 3f717b1 commit eaa8a19
Showing 11 changed files with 256 additions and 16 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -85,6 +85,7 @@ import { Alert } from 'vue-tg'

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

- [useWebApp](https://vue-tg.pages.dev/mini-apps.html#usewebapp)
- [useWebAppBackButton](https://vue-tg.pages.dev/mini-apps.html#usewebappbackbutton)
- [useWebAppBiometricManager](https://vue-tg.pages.dev/mini-apps.html#usewebappgiometricmanager)
- [useWebAppClipboard](https://vue-tg.pages.dev/mini-apps.html#usewebappclipboard)
- [useWebAppClosingConfirmation](https://vue-tg.pages.dev/mini-apps.html#usewebappclosingconfirmation)
- [useWebAppCloudStorage](https://vue-tg.pages.dev/mini-apps.html#usewebappcloudstorage)
63 changes: 62 additions & 1 deletion demo/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
<script lang="ts" setup>
import { useWebApp, useWebAppHapticFeedback, useWebAppMainButton, useWebAppNavigation, useWebAppPopup, useWebAppQrScanner, useWebAppTheme, useWebAppViewport } from '../src'
import {
useWebApp,
useWebAppHapticFeedback,
useWebAppMainButton,
useWebAppNavigation,
useWebAppPopup,
useWebAppQrScanner,
useWebAppTheme,
useWebAppViewport,
useWebAppBiometricManager,
} from '../src'
const { version, platform, initData, initDataUnsafe, sendData } = useWebApp()
const { expand, isExpanded, viewportHeight, viewportStableHeight } = useWebAppViewport()
@@ -21,6 +31,18 @@ const {
const { colorScheme, themeParams, headerColor, backgroundColor } = useWebAppTheme()
const { impactOccurred, notificationOccurred, selectionChanged } = useWebAppHapticFeedback()
const { showScanQrPopup } = useWebAppQrScanner()
const {
isBiometricInited,
isBiometricAccessRequested,
isBiometricAccessGranted,
isBiometricTokenSaved,
isBiometricAvailable,
biometricDeviceId,
initBiometric,
requestBiometricAccess,
authenticateBiometric,
openBiometricSettings,
} = useWebAppBiometricManager()
function toggleMainButton() {
isMainButtonVisible.value
@@ -33,6 +55,24 @@ function toggleMainButtonProgress() {
? hideMainButtonProgress()
: showMainButtonProgress(true)
}
function initBiometricManager() {
initBiometric(() => console.log('init: isAccessGranted'))
}
function requestAccessBiometricManager() {
requestBiometricAccess({})
}
function authenticateBiometricManager() {
authenticateBiometric({}, (isAuthenticated) => {
showAlert(`isAuthenticated: ${isAuthenticated}`)
})
}
function openSettingsBiometricManager() {
openBiometricSettings()
}
</script>

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

<div>
<h4>Biometric Manager</h4>
<p>isBiometricInited: {{ isBiometricInited }}</p>
<p>isBiometricAccessRequested: {{ isBiometricAccessRequested }}</p>
<p>isBiometricAccessGranted: {{ isBiometricAccessGranted }}</p>
<p>isBiometricTokenSaved: {{ isBiometricTokenSaved }}</p>
<p>isBiometricAvailable: {{ isBiometricAvailable }}</p>
<p>biometricDeviceId: {{ biometricDeviceId }}</p>

<button @click.prevent="initBiometricManager">Init</button>
<button @click.prevent="requestAccessBiometricManager">
request access
</button>
<button @click.prevent="authenticateBiometricManager">
authenticate
</button>
<button @click.prevent="openSettingsBiometricManager">
open settings
</button>
</div>

<div>
Version: {{ version }}
<br>
55 changes: 42 additions & 13 deletions docs/mini-apps.md
Original file line number Diff line number Diff line change
@@ -13,6 +13,8 @@ outline: [2, 3]

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

<!--@include: @/mini-apps/components/biometric-manager.md-->

<!--@include: @/mini-apps/components/closing-confirmation.md-->

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

#### Mapping

| Event name | Handler |
| --------------------- | ----------------------------------------------------------------------------- |
| themeChanged | [useWebAppTheme → onThemeChanged](#usewebapptheme) |
| viewportChanged | [useWebAppViewport → onViewportChanged](#usewebappviewport) |
| mainButtonClicked | [useWebAppMainButton → onMainButtonClicked](#usewebappmainbutton) |
| backButtonClicked | [useWebAppBackButton → onBackButtonClicked](#usewebappbackbutton) |
| settingsButtonClicked | [useWebAppSettingsButton → onSettingsButtonClicked](#usewebappsettingsbutton) |
| invoiceClosed | [useWebAppNavigation → onInvoiceClosed](#usewebappnavigation) |
| popupClosed | [useWebAppPopup → onPopupClosed](#usewebapppopup) |
| qrTextReceived | [useWebAppQrScanner → onQrTextReceived](#usewebappqrscanner) |
| clipboardTextReceived | [useWebAppClipboard → onClipboardTextReceived](#usewebappclipboard) |
| writeAccessRequested | [useWebAppRequests → onWriteAccessRequested](#usewebapprequests) |
| contactRequested | [useWebAppRequests → onContactRequested](#usewebapprequests) |
| Event name | Handler |
|-------------------------|-------------------------------------------------------------------------------------|
| themeChanged | [useWebAppTheme → onThemeChanged](#usewebapptheme) |
| viewportChanged | [useWebAppViewport → onViewportChanged](#usewebappviewport) |
| mainButtonClicked | [useWebAppMainButton → onMainButtonClicked](#usewebappmainbutton) |
| backButtonClicked | [useWebAppBackButton → onBackButtonClicked](#usewebappbackbutton) |
| settingsButtonClicked | [useWebAppSettingsButton → onSettingsButtonClicked](#usewebappsettingsbutton) |
| invoiceClosed | [useWebAppNavigation → onInvoiceClosed](#usewebappnavigation) |
| popupClosed | [useWebAppPopup → onPopupClosed](#usewebapppopup) |
| qrTextReceived | [useWebAppQrScanner → onQrTextReceived](#usewebappqrscanner) |
| clipboardTextReceived | [useWebAppClipboard → onClipboardTextReceived](#usewebappclipboard) |
| writeAccessRequested | [useWebAppRequests → onWriteAccessRequested](#usewebapprequests) |
| contactRequested | [useWebAppRequests → onContactRequested](#usewebapprequests) |
| biometricManagerUpdated | [useWebAppBiometricManager → onBiometricManagerUpdated](#usewebappbiometricmanager) |
| biometricAuthRequested | [useWebAppBiometricManager → onBiometricAuthRequested](#usewebappbiometricmanager) |
| biometricTokenUpdated | [useWebAppBiometricManager → onBiometricTokenUpdated](#usewebappbiometricmanager) |

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

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

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

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

<!--@include: @/mini-apps/composables/use-web-app-closing-confirmation.md-->
@@ -211,3 +219,24 @@ onThemeChanged(() => {
| :----------------- | :------------------------- |
| `eventData` | `Object` |
| `eventData.status` | `"allowed" \| "cancelled"` |

### OnBiometricAuthRequested

Ƭ **OnBiometricAuthRequested**: `(eventData) => void`

##### Parameters

| Name | Type |
|:------------------|:----------------------|
| `isAuthenticated` | `boolean` |
| `biometricToken` | `string \| undefined` |

### OnBiometricTokenUpdated

Ƭ **OnBiometricTokenUpdated**: `(eventData) => void`

##### Parameters

| Name | Type |
|:------------|:----------|
| `isUpdated` | `boolean` |
23 changes: 23 additions & 0 deletions docs/mini-apps/components/biometric-manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### BiometricManager

A component that init the biometric manager when is rendered.

```vue
<script lang="ts" setup>
import { BiometricManager } from 'vue-tg'
const handleInit = () => {
// ...
}
</script>
<template>
<BiometricManager @init="handleInit" />
</template>
```

#### Events

| Name | Type | Description |
| ---- | ------------ | ----------------------------------------- |
| init | `() => void` | Emits when the biometric manager is init. |
27 changes: 27 additions & 0 deletions docs/mini-apps/composables/use-web-app-biometric-manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
### useWebAppBiometricManager

```ts
import { useWebAppBiometricManager } from 'vue-tg'
```

**useWebAppBiometricManager**(): `Object`

#### Returns

| Name | Type |
| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| `isBiometricInited` | `Readonly<Ref<boolean>>` |
| `isBiometricAvailable` | `Readonly<Ref<boolean>>` |
| `biometricType` | `Readonly<Ref<"finger" \| "face" \| "unknown">>` |
| `isBiometricAccessRequested` | `Readonly<Ref<boolean>>` |
| `isBiometricAccessGranted` | `Readonly<Ref<boolean>>` |
| `isBiometricTokenSaved` | `Readonly<Ref<boolean>>` |
| `biometricDeviceId` | `Readonly<Ref<string>>` |
| `initBiometric` | `(callback?: () => void) => void` |
| `requestBiometricAccess` | `(params: BiometricRequestAccessParams, callback?: (isAccessGranted: boolean) => void) => void` |
| `authenticateBiometric` | `(params: BiometricAuthenticateParams, callback?: (isAuthenticated: boolean, biometricToken?: string) => void) => void` |
| `updateBiometricToken` | `(token: string, callback?: (applied: boolean) => void) => void` |
| `openBiometricSettings` | `() => void` |
| `onBiometricManagerUpdated` | `(eventHandler: () => void) => void` |
| `onBiometricAuthRequested` | `(eventHandler: `[`OnBiometricAuthRequested`](#onbiometricauthrequested)`)) => void` |
| `onBiometricTokenUpdated` | `(eventHandler: `[`OnBiometricTokenUpdated`](#onbiometrictokenupdated)`)) => void` |
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-tg",
"version": "0.4.0",
"version": "0.5.0",
"description": "Telegram integration for Vue",
"author": "deptyped <deptyped@gmail.com>",
"license": "MIT",
@@ -49,7 +49,7 @@
"docs:preview": "vitepress preview docs"
},
"dependencies": {
"@types/telegram-web-app": "^7.0.0",
"@types/telegram-web-app": "^7.2.0",
"vue": "^3"
},
"devDependencies": {
14 changes: 14 additions & 0 deletions src/components/BiometricManager.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts" setup>
import { onMounted } from "vue"
import { useWebAppBiometricManager } from ".."
const emit = defineEmits<{
(eventName: "init"): void
}>()
const { initBiometric } = useWebAppBiometricManager()
onMounted(() => initBiometric(() => emit("init")))
</script>

<template></template>
1 change: 1 addition & 0 deletions src/composables/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { useWebApp } from "./useWebApp"
export { useWebAppBackButton } from "./useWebAppBackButton"
export { useWebAppBiometricManager } from "./useWebAppBiometricManager"
export { useWebAppClipboard } from "./useWebAppClipboard"
export { useWebAppClosingConfirmation } from "./useWebAppClosingConfirmation"
export { useWebAppCloudStorage } from "./useWebAppCloudStorage"
72 changes: 72 additions & 0 deletions src/composables/useWebAppBiometricManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { readonly, ref } from "vue"
import { OnBiometricAuthRequested, OnBiometricTokenUpdated } from "~/types"
import { useWebApp } from "./useWebApp"

const {
init,
requestAccess,
authenticate,
updateBiometricToken,
openSettings,
} = Telegram.WebApp.BiometricManager

const isBiometricInited = ref(Telegram.WebApp.BiometricManager.isInited)
const isBiometricAvailable = ref(
Telegram.WebApp.BiometricManager.isBiometricAvailable,
)
const biometricType = ref(Telegram.WebApp.BiometricManager.biometricType)
const isBiometricAccessRequested = ref(
Telegram.WebApp.BiometricManager.isAccessRequested,
)
const isBiometricAccessGranted = ref(
Telegram.WebApp.BiometricManager.isAccessGranted,
)
const isBiometricTokenSaved = ref(
Telegram.WebApp.BiometricManager.isAccessGranted,
)
const biometricDeviceId = ref(Telegram.WebApp.BiometricManager.deviceId)

function updateState() {
isBiometricInited.value = Telegram.WebApp.BiometricManager.isInited
isBiometricAvailable.value =
Telegram.WebApp.BiometricManager.isBiometricAvailable
biometricType.value = Telegram.WebApp.BiometricManager.biometricType
isBiometricAccessRequested.value =
Telegram.WebApp.BiometricManager.isAccessRequested
isBiometricAccessGranted.value =
Telegram.WebApp.BiometricManager.isAccessGranted
biometricDeviceId.value = Telegram.WebApp.BiometricManager.deviceId
isBiometricTokenSaved.value =
Telegram.WebApp.BiometricManager.isBiometricTokenSaved
}

export function useWebAppBiometricManager() {
const { onEvent } = useWebApp()

const onBiometricManagerUpdated = (eventHandler: () => void) =>
onEvent("biometricManagerUpdated", eventHandler)
const onBiometricAuthRequested = (eventHandler: OnBiometricAuthRequested) =>
onEvent("biometricAuthRequested", eventHandler)
const onBiometricTokenUpdated = (eventHandler: OnBiometricTokenUpdated) =>
onEvent("biometricTokenUpdated", eventHandler)

onBiometricManagerUpdated(updateState)

return {
isBiometricInited: readonly(isBiometricInited),
isBiometricAvailable: readonly(isBiometricAvailable),
biometricType: readonly(biometricType),
isBiometricAccessRequested: readonly(isBiometricAccessRequested),
isBiometricAccessGranted: readonly(isBiometricAccessGranted),
isBiometricTokenSaved: readonly(isBiometricTokenSaved),
biometricDeviceId: readonly(biometricDeviceId),
initBiometric: init,
requestBiometricAccess: requestAccess,
authenticateBiometric: authenticate,
updateBiometricToken,
openBiometricSettings: openSettings,
onBiometricManagerUpdated,
onBiometricAuthRequested,
onBiometricTokenUpdated,
}
}
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import type { App } from "vue"

import Alert from "./components/Alert.vue"
import BackButton from "./components/BackButton.vue"
import BiometricManager from "./components/BiometricManager.vue"
import ClosingConfirmation from "./components/ClosingConfirmation.vue"
import Confirm from "./components/Confirm.vue"
import ExpandedViewport from "./components/ExpandedViewport.vue"
@@ -17,6 +18,7 @@ import DiscussionWidget from "./widgets/DiscussionWidget.vue"
export {
Alert,
BackButton,
BiometricManager,
ClosingConfirmation,
Confirm,
ExpandedViewport,
@@ -38,6 +40,7 @@ const plugin = {
install(Vue: App) {
Vue.component("TgAlert", Alert)
Vue.component("TgBackButton", BackButton)
Vue.component("TgBiometricManager", BiometricManager)
Vue.component("TgClosingConfirmation", ClosingConfirmation)
Vue.component("TgConfirm", Confirm)
Vue.component("TgExpandedViewport", ExpandedViewport)
@@ -56,6 +59,7 @@ declare module "@vue/runtime-core" {
export interface GlobalComponents {
TgAlert: typeof Alert
TgBackButton: typeof BackButton
TgBiometricManager: typeof BiometricManager
TgClosingConfirmation: typeof ClosingConfirmation
TgConfirm: typeof Confirm
TgExpandedViewport: typeof ExpandedViewport
Loading

0 comments on commit eaa8a19

Please sign in to comment.