mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-07-30 17:48:50 +02:00
chore: adjust prettier config, .gitignore and use taplo to format toml files (#1728)
* chore: adjust prettier config, .gitignore and use taplo to format toml files This brings the plugins-workspace repository to the same code style of the main tauri repo * format toml * ignore examples gen dir * add .vscode/extensions.json * remove packageManager field * fmt * fix audit * taplo ignore permissions autogenerated files * remove create dummy dist * fix prettier workflow * install fmt in prettier workflow --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
co-authored by
Lucas Nogueira
parent
72c2ce82c1
commit
cf4d7d4e6c
+1
-1
@@ -7,5 +7,5 @@ ignore = [
|
|||||||
# wry needs kuchiki on Android
|
# wry needs kuchiki on Android
|
||||||
"RUSTSEC-2023-0019",
|
"RUSTSEC-2023-0019",
|
||||||
# atty is only used when the `colored` feature is enabled on tauri-plugin-log
|
# atty is only used when the `colored` feature is enabled on tauri-plugin-log
|
||||||
"RUSTSEC-2021-0145"
|
"RUSTSEC-2021-0145",
|
||||||
]
|
]
|
||||||
@@ -7,23 +7,23 @@ name: Audit JavaScript
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 0 * * *"
|
- cron: '0 0 * * *'
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/audit-javascript.yml"
|
- '.github/workflows/audit-javascript.yml'
|
||||||
- "**/pnpm-lock.yaml"
|
- '**/pnpm-lock.yaml'
|
||||||
- "**/package.json"
|
- '**/package.json'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/audit-javascript.yml"
|
- '.github/workflows/audit-javascript.yml'
|
||||||
- "**/pnpm-lock.yaml"
|
- '**/pnpm-lock.yaml'
|
||||||
- "**/package.json"
|
- '**/package.json'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
${{ runner.os }}-
|
${{ runner.os }}-
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: 'lts/*'
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 9.x.x
|
version: 9.x.x
|
||||||
|
|||||||
@@ -7,23 +7,23 @@ name: Audit Rust
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 0 * * *"
|
- cron: '0 0 * * *'
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/audit-rust.yml"
|
- '.github/workflows/audit-rust.yml'
|
||||||
- "**/Cargo.lock"
|
- '**/Cargo.lock'
|
||||||
- "**/Cargo.toml"
|
- '**/Cargo.toml'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/audit-rust.yml"
|
- '.github/workflows/audit-rust.yml'
|
||||||
- "**/Cargo.lock"
|
- '**/Cargo.lock'
|
||||||
- "**/Cargo.toml"
|
- '**/Cargo.toml'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ name: check generated files
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/check-generated-files.yml"
|
- '.github/workflows/check-generated-files.yml'
|
||||||
- "**/guest-js/**"
|
- '**/guest-js/**'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -136,7 +136,7 @@ jobs:
|
|||||||
${{ runner.os }}-
|
${{ runner.os }}-
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: 'lts/*'
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 9.x.x
|
version: 9.x.x
|
||||||
|
|||||||
@@ -27,4 +27,4 @@ jobs:
|
|||||||
uses: jbolda/covector/packages/action@covector-v0
|
uses: jbolda/covector/packages/action@covector-v0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
command: "status"
|
command: 'status'
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ jobs:
|
|||||||
uses: jbolda/covector/packages/action@covector-v0
|
uses: jbolda/covector/packages/action@covector-v0
|
||||||
id: covector
|
id: covector
|
||||||
with:
|
with:
|
||||||
command: "status"
|
command: 'status'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
comment: true
|
comment: true
|
||||||
@@ -34,8 +34,8 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: 'lts/*'
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
@@ -65,7 +65,7 @@ jobs:
|
|||||||
NODE_AUTH_TOKEN: ${{ secrets.ORG_NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.ORG_NPM_TOKEN }}
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
command: "version-or-publish"
|
command: 'version-or-publish'
|
||||||
createRelease: true
|
createRelease: true
|
||||||
recognizeContributors: true
|
recognizeContributors: true
|
||||||
|
|
||||||
@@ -78,8 +78,8 @@ jobs:
|
|||||||
uses: tauri-apps/create-pull-request@v3
|
uses: tauri-apps/create-pull-request@v3
|
||||||
if: steps.covector.outputs.commandRan == 'version'
|
if: steps.covector.outputs.commandRan == 'version'
|
||||||
with:
|
with:
|
||||||
title: "Publish New Versions (${{ github.ref_name }})"
|
title: 'Publish New Versions (${{ github.ref_name }})'
|
||||||
commit-message: "publish new versions"
|
commit-message: 'publish new versions'
|
||||||
labels: "version updates"
|
labels: 'version updates'
|
||||||
branch: "ci/release-${{ github.ref_name }}"
|
branch: 'ci/release-${{ github.ref_name }}'
|
||||||
body: ${{ steps.covector.outputs.change }}
|
body: ${{ steps.covector.outputs.change }}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
name: check formatting
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
rustfmt:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: install Rust stable and rustfmt
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
components: rustfmt
|
||||||
|
|
||||||
|
- name: run cargo fmt
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
prettier:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Cache pnpm modules
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.pnpm-store
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 'lts/*'
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9.x.x
|
||||||
|
run_install: true
|
||||||
|
- run: pnpm format:check
|
||||||
|
|
||||||
|
taplo:
|
||||||
|
name: taplo (.toml files)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: install Rust stable
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: install taplo-cli
|
||||||
|
uses: taiki-e/install-action@v2
|
||||||
|
with:
|
||||||
|
tool: taplo-cli
|
||||||
|
|
||||||
|
- run: taplo fmt --check --diff
|
||||||
@@ -10,15 +10,15 @@ on:
|
|||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/integration-tests.yml"
|
- '.github/workflows/integration-tests.yml'
|
||||||
- "plugins/updater/src/**"
|
- 'plugins/updater/src/**'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/integration-tests.yml"
|
- '.github/workflows/integration-tests.yml'
|
||||||
- "plugins/updater/src/**"
|
- 'plugins/updater/src/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-integration-tests:
|
run-integration-tests:
|
||||||
|
|||||||
@@ -10,23 +10,23 @@ on:
|
|||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/lint-javascript.yml"
|
- '.github/workflows/lint-javascript.yml'
|
||||||
- "plugins/*/guest-js/**"
|
- 'plugins/*/guest-js/**'
|
||||||
- ".eslintignore"
|
- '.eslintignore'
|
||||||
- ".eslintrc.json"
|
- '.eslintrc.json'
|
||||||
- ".prettierignore"
|
- '.prettierignore'
|
||||||
- "**/package.json"
|
- '**/package.json'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/lint-javascript.yml"
|
- '.github/workflows/lint-javascript.yml'
|
||||||
- "plugins/*/guest-js/**"
|
- 'plugins/*/guest-js/**'
|
||||||
- ".eslintignore"
|
- '.eslintignore'
|
||||||
- ".eslintrc.json"
|
- '.eslintrc.json'
|
||||||
- ".prettierignore"
|
- '.prettierignore'
|
||||||
- "**/package.json"
|
- '**/package.json'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -46,30 +46,10 @@ jobs:
|
|||||||
${{ runner.os }}-
|
${{ runner.os }}-
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: 'lts/*'
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 9.x.x
|
version: 9.x.x
|
||||||
run_install: true
|
run_install: true
|
||||||
- name: eslint
|
- name: eslint
|
||||||
run: pnpm lint
|
run: pnpm lint
|
||||||
prettier:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Cache pnpm modules
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "lts/*"
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.x.x
|
|
||||||
run_install: true
|
|
||||||
- name: prettier check
|
|
||||||
run: pnpm format-check
|
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ on:
|
|||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/lint-rust.yml"
|
- '.github/workflows/lint-rust.yml'
|
||||||
- "plugins/*/src/**"
|
- 'plugins/*/src/**'
|
||||||
- "!plugins/*/src/api-iife.js"
|
- '!plugins/*/src/api-iife.js'
|
||||||
- "**/Cargo.toml"
|
- '**/Cargo.toml'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/lint-rust.yml"
|
- '.github/workflows/lint-rust.yml'
|
||||||
- "plugins/*/src/**"
|
- 'plugins/*/src/**'
|
||||||
- "!plugins/*/src/api-iife.js"
|
- '!plugins/*/src/api-iife.js'
|
||||||
- "**/Cargo.toml"
|
- '**/Cargo.toml'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -147,10 +147,6 @@ jobs:
|
|||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
- name: create dummy dist
|
|
||||||
working-directory: examples/api
|
|
||||||
run: mkdir dist
|
|
||||||
|
|
||||||
- name: clippy ${{ matrix.package }}
|
- name: clippy ${{ matrix.package }}
|
||||||
if: matrix.package != 'tauri-plugin-sql'
|
if: matrix.package != 'tauri-plugin-sql'
|
||||||
run: cargo clippy --package ${{ matrix.package }} --all-targets -- -D warnings
|
run: cargo clippy --package ${{ matrix.package }} --all-targets -- -D warnings
|
||||||
@@ -162,17 +158,3 @@ jobs:
|
|||||||
- name: clippy ${{ matrix.package }} postgres
|
- name: clippy ${{ matrix.package }} postgres
|
||||||
if: matrix.package == 'tauri-plugin-sql'
|
if: matrix.package == 'tauri-plugin-sql'
|
||||||
run: cargo clippy --package ${{ matrix.package }} --all-targets --no-default-features --features postgres -- -D warnings
|
run: cargo clippy --package ${{ matrix.package }} --all-targets --no-default-features --features postgres -- -D warnings
|
||||||
|
|
||||||
fmt:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install rustfmt with nightly toolchain
|
|
||||||
uses: dtolnay/rust-toolchain@nightly
|
|
||||||
with:
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- name: Check formatting
|
|
||||||
run: cargo fmt --all -- --check
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: 'lts/*'
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -10,21 +10,21 @@ on:
|
|||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/test-rust.yml"
|
- '.github/workflows/test-rust.yml'
|
||||||
- "plugins/*/src/**"
|
- 'plugins/*/src/**'
|
||||||
- "!plugins/*/src/api-iife.js"
|
- '!plugins/*/src/api-iife.js'
|
||||||
- "**/Cargo.toml"
|
- '**/Cargo.toml'
|
||||||
- "**/Cargo.lock"
|
- '**/Cargo.lock'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- v1
|
||||||
- v2
|
- v2
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/test-rust.yml"
|
- '.github/workflows/test-rust.yml'
|
||||||
- "plugins/*/src/**"
|
- 'plugins/*/src/**'
|
||||||
- "!plugins/*/src/api-iife.js"
|
- '!plugins/*/src/api-iife.js'
|
||||||
- "**/Cargo.toml"
|
- '**/Cargo.toml'
|
||||||
- "**/Cargo.lock"
|
- '**/Cargo.lock'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -163,32 +163,32 @@ jobs:
|
|||||||
- {
|
- {
|
||||||
target: x86_64-pc-windows-msvc,
|
target: x86_64-pc-windows-msvc,
|
||||||
os: windows-latest,
|
os: windows-latest,
|
||||||
runner: "cargo",
|
runner: 'cargo',
|
||||||
command: "test",
|
command: 'test'
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
target: x86_64-unknown-linux-gnu,
|
target: x86_64-unknown-linux-gnu,
|
||||||
os: ubuntu-latest,
|
os: ubuntu-latest,
|
||||||
runner: "cargo",
|
runner: 'cargo',
|
||||||
command: "test",
|
command: 'test'
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
target: aarch64-apple-darwin,
|
target: aarch64-apple-darwin,
|
||||||
os: macos-latest,
|
os: macos-latest,
|
||||||
runner: "cargo",
|
runner: 'cargo',
|
||||||
command: "test",
|
command: 'test'
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
target: aarch64-apple-ios,
|
target: aarch64-apple-ios,
|
||||||
os: macos-latest,
|
os: macos-latest,
|
||||||
runner: "cargo",
|
runner: 'cargo',
|
||||||
command: "build",
|
command: 'build'
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
target: aarch64-linux-android,
|
target: aarch64-linux-android,
|
||||||
os: ubuntu-latest,
|
os: ubuntu-latest,
|
||||||
runner: "cross",
|
runner: 'cross',
|
||||||
command: "build",
|
command: 'build'
|
||||||
}
|
}
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform.os }}
|
runs-on: ${{ matrix.platform.os }}
|
||||||
@@ -210,10 +210,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
key: cache-${{ matrix.package }}-${{ matrix.platform.target }}
|
key: cache-${{ matrix.package }}-${{ matrix.platform.target }}
|
||||||
|
|
||||||
- name: create dummy dist
|
|
||||||
working-directory: examples/api
|
|
||||||
run: mkdir dist
|
|
||||||
|
|
||||||
- name: install cross
|
- name: install cross
|
||||||
if: ${{ matrix.platform.runner == 'cross' }}
|
if: ${{ matrix.platform.runner == 'cross' }}
|
||||||
run: cargo +stable install cross --git https://github.com/cross-rs/cross
|
run: cargo +stable install cross --git https://github.com/cross-rs/cross
|
||||||
|
|||||||
+51
-9
@@ -1,10 +1,52 @@
|
|||||||
target
|
# dependency directories
|
||||||
node_modules
|
node_modules/
|
||||||
dist-js
|
target/
|
||||||
dist
|
|
||||||
|
# Optional npm and yarn cache directory
|
||||||
|
.npm/
|
||||||
|
.yarn/
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# .vscode workspace settings file
|
||||||
|
.vscode/settings.json
|
||||||
|
|
||||||
|
# npm, yarn and bun lock files
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
bun.lockb
|
||||||
|
|
||||||
|
# rust compiled folders
|
||||||
|
target/
|
||||||
|
|
||||||
|
# compiled plugins
|
||||||
|
dist-js/
|
||||||
|
|
||||||
|
# plugins .tauri director
|
||||||
|
/plugins/*/.tauri
|
||||||
|
|
||||||
|
# logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# miscellaneous
|
||||||
|
/.vs
|
||||||
|
.DS_Store
|
||||||
|
.Thumbs.db
|
||||||
|
*.sublime*
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
debug.log
|
||||||
.gradle
|
TODO.md
|
||||||
**/capabilities/schemas
|
|
||||||
.build
|
|
||||||
.tauri
|
|
||||||
+18
-8
@@ -1,12 +1,22 @@
|
|||||||
target
|
/.changes
|
||||||
node_modules
|
/.vscode
|
||||||
dist
|
|
||||||
dist-js
|
# dependcies and artifacts directories
|
||||||
|
node_modules/
|
||||||
|
target/
|
||||||
|
dist-js/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# lock files
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
Cargo.lock
|
|
||||||
.build
|
# examples gen directory
|
||||||
build
|
examples/*/src-tauri/gen/
|
||||||
|
plugins/examples/*/src-tauri/gen/
|
||||||
|
|
||||||
|
# autogenerated files
|
||||||
|
**/autogenerated/**/*.md
|
||||||
api-iife.js
|
api-iife.js
|
||||||
init-iife.js
|
init-iife.js
|
||||||
intermediates/
|
CHANGELOG.md
|
||||||
*schema.json
|
*schema.json
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": false,
|
||||||
|
"trailingComma": "none"
|
||||||
|
}
|
||||||
@@ -2,129 +2,129 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import fs from "fs";
|
import fs from 'fs'
|
||||||
import path from "path";
|
import path from 'path'
|
||||||
import readline from "readline";
|
import readline from 'readline'
|
||||||
|
|
||||||
const header = `Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
const header = `Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||||
SPDX-License-Identifier: Apache-2.0
|
SPDX-License-Identifier: Apache-2.0
|
||||||
SPDX-License-Identifier: MIT`;
|
SPDX-License-Identifier: MIT`
|
||||||
const ignoredLicenses = [
|
const ignoredLicenses = [
|
||||||
"// Copyright 2021 Flavio Oliveira",
|
'// Copyright 2021 Flavio Oliveira',
|
||||||
"// Copyright 2021 Jonas Kruckenberg",
|
'// Copyright 2021 Jonas Kruckenberg',
|
||||||
"// Copyright 2018-2023 the Deno authors.",
|
'// Copyright 2018-2023 the Deno authors.'
|
||||||
];
|
]
|
||||||
|
|
||||||
const extensions = [".rs", ".js", ".ts", ".yml", ".swift", ".kt"];
|
const extensions = ['.rs', '.js', '.ts', '.yml', '.swift', '.kt']
|
||||||
const ignore = [
|
const ignore = [
|
||||||
"target",
|
'target',
|
||||||
"templates",
|
'templates',
|
||||||
"node_modules",
|
'node_modules',
|
||||||
"gen",
|
'gen',
|
||||||
"dist",
|
'dist',
|
||||||
"dist-js",
|
'dist-js',
|
||||||
".svelte-kit",
|
'.svelte-kit',
|
||||||
"api-iife.js",
|
'api-iife.js',
|
||||||
"init-iife.js",
|
'init-iife.js',
|
||||||
".build",
|
'.build',
|
||||||
"notify_rust",
|
'notify_rust'
|
||||||
];
|
]
|
||||||
|
|
||||||
async function checkFile(file) {
|
async function checkFile(file) {
|
||||||
if (
|
if (
|
||||||
extensions.some((e) => file.endsWith(e)) &&
|
extensions.some((e) => file.endsWith(e)) &&
|
||||||
!ignore.some((i) => file.includes(`${path.sep}${i}`))
|
!ignore.some((i) => file.includes(`${path.sep}${i}`))
|
||||||
) {
|
) {
|
||||||
const fileStream = fs.createReadStream(file);
|
const fileStream = fs.createReadStream(file)
|
||||||
const rl = readline.createInterface({
|
const rl = readline.createInterface({
|
||||||
input: fileStream,
|
input: fileStream,
|
||||||
crlfDelay: Infinity,
|
crlfDelay: Infinity
|
||||||
});
|
})
|
||||||
|
|
||||||
let contents = ``;
|
let contents = ``
|
||||||
let i = 0;
|
let i = 0
|
||||||
for await (let line of rl) {
|
for await (let line of rl) {
|
||||||
// ignore empty lines, allow shebang, swift-tools-version and bundler license
|
// ignore empty lines, allow shebang, swift-tools-version and bundler license
|
||||||
if (
|
if (
|
||||||
line.length === 0 ||
|
line.length === 0 ||
|
||||||
line.startsWith("#!") ||
|
line.startsWith('#!') ||
|
||||||
line.startsWith("// swift-tools-version:") ||
|
line.startsWith('// swift-tools-version:') ||
|
||||||
ignoredLicenses.includes(line)
|
ignoredLicenses.includes(line)
|
||||||
) {
|
) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// strip comment marker
|
// strip comment marker
|
||||||
if (line.startsWith("// ")) {
|
if (line.startsWith('// ')) {
|
||||||
line = line.substring(3);
|
line = line.substring(3)
|
||||||
} else if (line.startsWith("# ")) {
|
} else if (line.startsWith('# ')) {
|
||||||
line = line.substring(2);
|
line = line.substring(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
contents += line;
|
contents += line
|
||||||
if (++i === 3) {
|
if (++i === 3) {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
contents += "\n";
|
contents += '\n'
|
||||||
}
|
}
|
||||||
if (contents !== header) {
|
if (contents !== header) {
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function check(src) {
|
async function check(src) {
|
||||||
const missingHeader = [];
|
const missingHeader = []
|
||||||
|
|
||||||
for (const entry of fs.readdirSync(src, {
|
for (const entry of fs.readdirSync(src, {
|
||||||
withFileTypes: true,
|
withFileTypes: true
|
||||||
})) {
|
})) {
|
||||||
const p = path.join(src, entry.name);
|
const p = path.join(src, entry.name)
|
||||||
|
|
||||||
if (entry.isSymbolicLink() || ignore.includes(entry.name)) {
|
if (entry.isSymbolicLink() || ignore.includes(entry.name)) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
const missing = await check(p);
|
const missing = await check(p)
|
||||||
missingHeader.push(...missing);
|
missingHeader.push(...missing)
|
||||||
} else {
|
} else {
|
||||||
const isMissing = await checkFile(p);
|
const isMissing = await checkFile(p)
|
||||||
if (isMissing) {
|
if (isMissing) {
|
||||||
missingHeader.push(p);
|
missingHeader.push(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return missingHeader;
|
return missingHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
const [_bin, _script, ...files] = process.argv;
|
const [_bin, _script, ...files] = process.argv
|
||||||
|
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
async function run() {
|
async function run() {
|
||||||
const missing = [];
|
const missing = []
|
||||||
for (const f of files) {
|
for (const f of files) {
|
||||||
const isMissing = await checkFile(f);
|
const isMissing = await checkFile(f)
|
||||||
if (isMissing) {
|
if (isMissing) {
|
||||||
missing.push(f);
|
missing.push(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (missing.length > 0) {
|
if (missing.length > 0) {
|
||||||
console.log(missing.join("\n"));
|
console.log(missing.join('\n'))
|
||||||
process.exit(1);
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run();
|
run()
|
||||||
} else {
|
} else {
|
||||||
check(path.resolve(new URL(import.meta.url).pathname, "../../..")).then(
|
check(path.resolve(new URL(import.meta.url).pathname, '../../..')).then(
|
||||||
(missing) => {
|
(missing) => {
|
||||||
if (missing.length > 0) {
|
if (missing.length > 0) {
|
||||||
console.log(missing.join("\n"));
|
console.log(missing.join('\n'))
|
||||||
process.exit(1);
|
process.exit(1)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"rust-lang.rust-analyzer",
|
||||||
|
"EditorConfig.EditorConfig",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"tamasfe.even-better-toml"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
## Plugins Found Here
|
## Plugins Found Here
|
||||||
|
|
||||||
| | | Win | Mac | Lin | iOS | And |
|
| | | Win | Mac | Lin | iOS | And |
|
||||||
| ----------------------------------------------- | ------------------------------------------------------ | --- | --- | --- | --- | --- |
|
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | --- | --- | --- | --- |
|
||||||
| [autostart](plugins/autostart) | Automatically launch your app at system startup. | ✅ | ✅ | ✅ | ? | ? |
|
| [autostart](plugins/autostart) | Automatically launch your app at system startup. | ✅ | ✅ | ✅ | ? | ? |
|
||||||
| [barcode-scanner](plugins/barcode-scanner) | Allows your mobile application to use the camera to scan QR codes, EAN-13 and other kinds of barcodes. | ? | ? | ? | ✅ | ✅ |
|
| [barcode-scanner](plugins/barcode-scanner) | Allows your mobile application to use the camera to scan QR codes, EAN-13 and other kinds of barcodes. | ? | ? | ? | ✅ | ✅ |
|
||||||
| [biometric](plugins/biometric) | Prompt the user for biometric authentication on Android and iOS. | ? | ? | ? | ✅ | ✅ |
|
| [biometric](plugins/biometric) | Prompt the user for biometric authentication on Android and iOS. | ? | ? | ? | ✅ | ✅ |
|
||||||
|
|||||||
+23
-23
@@ -2,29 +2,29 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import eslint from "@eslint/js";
|
import eslint from '@eslint/js'
|
||||||
import eslintConfigPrettier from "eslint-config-prettier";
|
import eslintConfigPrettier from 'eslint-config-prettier'
|
||||||
import eslintPluginSecurity from "eslint-plugin-security";
|
import eslintPluginSecurity from 'eslint-plugin-security'
|
||||||
import tseslint from "typescript-eslint";
|
import tseslint from 'typescript-eslint'
|
||||||
|
|
||||||
export default tseslint.config(
|
export default tseslint.config(
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
"**/target",
|
'**/target',
|
||||||
"**/node_modules",
|
'**/node_modules',
|
||||||
"**/examples",
|
'**/examples',
|
||||||
"**/dist",
|
'**/dist',
|
||||||
"**/dist-js",
|
'**/dist-js',
|
||||||
"**/build",
|
'**/build',
|
||||||
"**/api-iife.js",
|
'**/api-iife.js',
|
||||||
"**/init-iife.js",
|
'**/init-iife.js',
|
||||||
"**/init.js",
|
'**/init.js',
|
||||||
"**/rollup.config.js",
|
'**/rollup.config.js',
|
||||||
"**/bindings.ts",
|
'**/bindings.ts',
|
||||||
"**/.test-server",
|
'**/.test-server',
|
||||||
".scripts",
|
'.scripts',
|
||||||
"eslint.config.js",
|
'eslint.config.js'
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
eslint.configs.recommended,
|
eslint.configs.recommended,
|
||||||
eslintConfigPrettier,
|
eslintConfigPrettier,
|
||||||
@@ -32,7 +32,7 @@ export default tseslint.config(
|
|||||||
...tseslint.configs.recommendedTypeChecked,
|
...tseslint.configs.recommendedTypeChecked,
|
||||||
{
|
{
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
parserOptions: { project: true, tsconfigRootDir: import.meta.dirname },
|
parserOptions: { project: true, tsconfigRootDir: import.meta.dirname }
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
);
|
)
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
/node_modules/
|
/dist/*
|
||||||
/.vscode/
|
!/dist/.gitkeep
|
||||||
.DS_Store
|
|
||||||
.cargo
|
|
||||||
|
|||||||
Vendored
@@ -3,5 +3,5 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
window.__TAURI_ISOLATION_HOOK__ = (payload) => {
|
window.__TAURI_ISOLATION_HOOK__ = (payload) => {
|
||||||
return payload;
|
return payload
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "bundler",
|
||||||
"target": "esnext",
|
"target": "ESNext",
|
||||||
"module": "esnext",
|
"module": "ESNext",
|
||||||
/**
|
/**
|
||||||
* svelte-preprocess cannot figure out whether you have
|
* svelte-preprocess cannot figure out whether you have
|
||||||
* a value or a type, so tell TypeScript to enforce using
|
* a value or a type, so tell TypeScript to enforce using
|
||||||
* `import type` instead of `import` for Types.
|
* `import type` instead of `import` for Types.
|
||||||
*/
|
*/
|
||||||
"importsNotUsedAsValues": "error",
|
"verbatimModuleSyntax": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
/**
|
/**
|
||||||
@@ -18,8 +18,6 @@
|
|||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
/**
|
/**
|
||||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||||
* Disable this if you'd like to use dynamic types.
|
* Disable this if you'd like to use dynamic types.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1",
|
"@sveltejs/vite-plugin-svelte": "^3.0.1",
|
||||||
"@tauri-apps/cli": "2.0.0-rc.10",
|
"@tauri-apps/cli": "2.0.0-rc.10",
|
||||||
"@unocss/extractor-svelte": "^0.62.0",
|
"@unocss/extractor-svelte": "^0.62.0",
|
||||||
"svelte": "^4.2.8",
|
"svelte": "^4.2.19",
|
||||||
"unocss": "^0.62.0",
|
"unocss": "^0.62.0",
|
||||||
"vite": "^5.0.13"
|
"vite": "^5.0.13"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: "Rubik", sans-serif;
|
font-family: 'Rubik', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
export function arrayBufferToBase64(buffer, callback) {
|
export function arrayBufferToBase64(buffer, callback) {
|
||||||
const blob = new Blob([buffer], {
|
const blob = new Blob([buffer], {
|
||||||
type: "application/octet-binary",
|
type: 'application/octet-binary'
|
||||||
});
|
})
|
||||||
const reader = new FileReader();
|
const reader = new FileReader()
|
||||||
reader.onload = function (evt) {
|
reader.onload = function (evt) {
|
||||||
const dataurl = evt.target.result;
|
const dataurl = evt.target.result
|
||||||
callback(dataurl.substr(dataurl.indexOf(",") + 1));
|
callback(dataurl.substr(dataurl.indexOf(',') + 1))
|
||||||
};
|
}
|
||||||
reader.readAsDataURL(blob);
|
reader.readAsDataURL(blob)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import "uno.css";
|
import 'uno.css'
|
||||||
import "./app.css";
|
import './app.css'
|
||||||
import App from "./App.svelte";
|
import App from './App.svelte'
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: document.querySelector("#app"),
|
target: document.querySelector('#app')
|
||||||
});
|
})
|
||||||
|
|
||||||
export default app;
|
export default app
|
||||||
|
|||||||
@@ -2,43 +2,43 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { defineConfig, presetIcons, presetUno, presetWebFonts } from "unocss";
|
import { defineConfig, presetIcons, presetUno, presetWebFonts } from 'unocss'
|
||||||
import extractorSvelte from "@unocss/extractor-svelte";
|
import extractorSvelte from '@unocss/extractor-svelte'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
theme: {
|
theme: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: "#FFFFFF",
|
primary: '#FFFFFF',
|
||||||
primaryLighter: "#e9ecef",
|
primaryLighter: '#e9ecef',
|
||||||
darkPrimary: "#1B1B1D",
|
darkPrimary: '#1B1B1D',
|
||||||
darkPrimaryLighter: "#242526",
|
darkPrimaryLighter: '#242526',
|
||||||
primaryText: "#1C1E21",
|
primaryText: '#1C1E21',
|
||||||
darkPrimaryText: "#E3E3E3",
|
darkPrimaryText: '#E3E3E3',
|
||||||
secondaryText: "#858A91",
|
secondaryText: '#858A91',
|
||||||
darkSecondaryText: "#C2C5CA",
|
darkSecondaryText: '#C2C5CA',
|
||||||
accent: "#3578E5",
|
accent: '#3578E5',
|
||||||
accentDark: "#306cce",
|
accentDark: '#306cce',
|
||||||
accentDarker: "#2d66c3",
|
accentDarker: '#2d66c3',
|
||||||
accentDarkest: "#2554a0",
|
accentDarkest: '#2554a0',
|
||||||
accentLight: "#538ce9",
|
accentLight: '#538ce9',
|
||||||
accentLighter: "#72a1ed",
|
accentLighter: '#72a1ed',
|
||||||
accentLightest: "#9abcf2",
|
accentLightest: '#9abcf2',
|
||||||
accentText: "#FFFFFF",
|
accentText: '#FFFFFF',
|
||||||
darkAccent: "#67d6ed",
|
darkAccent: '#67d6ed',
|
||||||
darkAccentDark: "#49cee9",
|
darkAccentDark: '#49cee9',
|
||||||
darkAccentDarker: "#39cae8",
|
darkAccentDarker: '#39cae8',
|
||||||
darkAccentDarkest: "#19b5d5",
|
darkAccentDarkest: '#19b5d5',
|
||||||
darkAccentLight: "#85def1",
|
darkAccentLight: '#85def1',
|
||||||
darkAccentLighter: "#95e2f2",
|
darkAccentLighter: '#95e2f2',
|
||||||
darkAccentLightest: "#c2eff8",
|
darkAccentLightest: '#c2eff8',
|
||||||
darkAccentText: "#1C1E21",
|
darkAccentText: '#1C1E21',
|
||||||
code: "#d6d8da",
|
code: '#d6d8da',
|
||||||
codeDark: "#282a2e",
|
codeDark: '#282a2e',
|
||||||
hoverOverlay: "rgba(0,0,0,.05)",
|
hoverOverlay: 'rgba(0,0,0,.05)',
|
||||||
hoverOverlayDarker: "rgba(0,0,0,.1)",
|
hoverOverlayDarker: 'rgba(0,0,0,.1)',
|
||||||
darkHoverOverlay: "hsla(0,0%,100%,.05)",
|
darkHoverOverlay: 'hsla(0,0%,100%,.05)',
|
||||||
darkHoverOverlayDarker: "hsla(0,0%,100%,.1)",
|
darkHoverOverlayDarker: 'hsla(0,0%,100%,.1)'
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
preflights: [
|
preflights: [
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ export default defineConfig({
|
|||||||
code {
|
code {
|
||||||
font-size: ${theme.fontSize.xs[0]};
|
font-size: ${theme.fontSize.xs[0]};
|
||||||
font-family: ${theme.fontFamily.mono};
|
font-family: ${theme.fontFamily.mono};
|
||||||
border-radius: ${theme.borderRadius["DEFAULT"]};
|
border-radius: ${theme.borderRadius['DEFAULT']};
|
||||||
background-color: ${theme.colors.code};
|
background-color: ${theme.colors.code};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +66,8 @@ export default defineConfig({
|
|||||||
.dark code {
|
.dark code {
|
||||||
background-color: ${theme.colors.codeDark};
|
background-color: ${theme.colors.codeDark};
|
||||||
}
|
}
|
||||||
`,
|
`
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
shortcuts: {
|
shortcuts: {
|
||||||
btn: `select-none outline-none shadow-md p-2 rd-1 text-primaryText border-none font-400 dark:font-600
|
btn: `select-none outline-none shadow-md p-2 rd-1 text-primaryText border-none font-400 dark:font-600
|
||||||
@@ -81,20 +81,20 @@ export default defineConfig({
|
|||||||
note: `decoration-none flex-inline items-center relative p-2 rd-1
|
note: `decoration-none flex-inline items-center relative p-2 rd-1
|
||||||
border-l-4 border-accent dark:border-darkAccent
|
border-l-4 border-accent dark:border-darkAccent
|
||||||
bg-accent/10 dark:bg-darkAccent/10`,
|
bg-accent/10 dark:bg-darkAccent/10`,
|
||||||
"note-red":
|
'note-red':
|
||||||
"note bg-red-700/10 dark:bg-red-700/10 after:bg-red-700 dark:after:bg-red-700",
|
'note bg-red-700/10 dark:bg-red-700/10 after:bg-red-700 dark:after:bg-red-700',
|
||||||
input:
|
input:
|
||||||
"h-10 flex items-center outline-none border-none p-2 rd-1 shadow-md bg-primaryLighter dark:bg-darkPrimaryLighter text-primaryText dark:text-darkPrimaryText",
|
'h-10 flex items-center outline-none border-none p-2 rd-1 shadow-md bg-primaryLighter dark:bg-darkPrimaryLighter text-primaryText dark:text-darkPrimaryText'
|
||||||
},
|
},
|
||||||
presets: [
|
presets: [
|
||||||
presetUno(),
|
presetUno(),
|
||||||
presetIcons(),
|
presetIcons(),
|
||||||
presetWebFonts({
|
presetWebFonts({
|
||||||
fonts: {
|
fonts: {
|
||||||
sans: "Rubik",
|
sans: 'Rubik',
|
||||||
mono: ["Fira Code", "Fira Mono:400,700"],
|
mono: ['Fira Code', 'Fira Mono:400,700']
|
||||||
},
|
}
|
||||||
}),
|
})
|
||||||
],
|
],
|
||||||
extractors: [extractorSvelte],
|
extractors: [extractorSvelte]
|
||||||
});
|
})
|
||||||
|
|||||||
+15
-15
@@ -2,12 +2,12 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from 'vite'
|
||||||
import Unocss from "unocss/vite";
|
import Unocss from 'unocss/vite'
|
||||||
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||||
import process from "process";
|
import process from 'process'
|
||||||
|
|
||||||
const host = process.env.TAURI_DEV_HOST;
|
const host = process.env.TAURI_DEV_HOST
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig(async () => {
|
export default defineConfig(async () => {
|
||||||
@@ -18,9 +18,9 @@ export default defineConfig(async () => {
|
|||||||
output: {
|
output: {
|
||||||
entryFileNames: `assets/[name].js`,
|
entryFileNames: `assets/[name].js`,
|
||||||
chunkFileNames: `assets/[name].js`,
|
chunkFileNames: `assets/[name].js`,
|
||||||
assetFileNames: `assets/[name].[ext]`,
|
assetFileNames: `assets/[name].[ext]`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
host: host || false,
|
host: host || false,
|
||||||
@@ -28,14 +28,14 @@ export default defineConfig(async () => {
|
|||||||
strictPort: true,
|
strictPort: true,
|
||||||
hmr: host
|
hmr: host
|
||||||
? {
|
? {
|
||||||
protocol: "ws",
|
protocol: 'ws',
|
||||||
host,
|
host,
|
||||||
port: 5183,
|
port: 5183
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
fs: {
|
fs: {
|
||||||
allow: [".", "../../tooling/api/dist"],
|
allow: ['.', '../../tooling/api/dist']
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|||||||
+2
-7
@@ -6,8 +6,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm run -r --parallel --filter !plugins-workspace --filter !\"./plugins/*/examples/**\" --filter !\"./examples/*\" build",
|
"build": "pnpm run -r --parallel --filter !plugins-workspace --filter !\"./plugins/*/examples/**\" --filter !\"./examples/*\" build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"format": "prettier --write \"./**/*.{cjs,mjs,js,jsx,mts,ts,tsx,html,css,json}\" --ignore-path .prettierignore",
|
"format": "prettier --write .",
|
||||||
"format-check": "prettier --check \"./**/*.{cjs,mjs,js,jsx,mts,ts,tsx,html,css,json}\" --ignore-path .prettierignore"
|
"format:check": "prettier --check ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "9.9.1",
|
"@eslint/js": "9.9.1",
|
||||||
@@ -31,10 +31,5 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"pnpm": "^9.0.0"
|
"pnpm": "^9.0.0"
|
||||||
},
|
|
||||||
"pnpm": {
|
|
||||||
"overrides": {
|
|
||||||
"micromatch@<4.0.8": ">=4.0.8"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
node_modules
|
|
||||||
@@ -62,13 +62,13 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { enable, isEnabled, disable } from "@tauri-apps/plugin-autostart";
|
import { enable, isEnabled, disable } from '@tauri-apps/plugin-autostart'
|
||||||
|
|
||||||
await enable();
|
await enable()
|
||||||
|
|
||||||
console.log(`registered for autostart? ${await isEnabled()}`);
|
console.log(`registered for autostart? ${await isEnabled()}`)
|
||||||
|
|
||||||
disable();
|
disable()
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export async function isEnabled(): Promise<boolean> {
|
export async function isEnabled(): Promise<boolean> {
|
||||||
return await invoke("plugin:autostart|is_enabled");
|
return await invoke('plugin:autostart|is_enabled')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function enable(): Promise<void> {
|
export async function enable(): Promise<void> {
|
||||||
await invoke("plugin:autostart|enable");
|
await invoke('plugin:autostart|enable')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function disable(): Promise<void> {
|
export async function disable(): Promise<void> {
|
||||||
await invoke("plugin:autostart|disable");
|
await invoke('plugin:autostart|disable')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,4 @@ disable the automatic start on boot.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
permissions = [
|
permissions = ["allow-enable", "allow-disable", "allow-is-enabled"]
|
||||||
"allow-enable",
|
|
||||||
"allow-disable",
|
|
||||||
"allow-is-enabled",
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -60,12 +60,12 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { scan } from "@tauri-apps/plugin-barcode-scanner";
|
import { scan } from '@tauri-apps/plugin-barcode-scanner'
|
||||||
|
|
||||||
// `windowed: true` actually sets the webview to transparent
|
// `windowed: true` actually sets the webview to transparent
|
||||||
// instead of opening a separate view for the camera
|
// instead of opening a separate view for the camera
|
||||||
// make sure your user interface is ready to show what is underneath with a transparent element
|
// make sure your user interface is ready to show what is underneath with a transparent element
|
||||||
scan({ windowed: true, formats: [""] })
|
scan({ windowed: true, formats: [''] })
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ The camera has two modes. The first one is where the user can see the background
|
|||||||
The second mode allows the developer to assist the user and add a transparent overlay to the image, providing hints or additional information (like a link preview).
|
The second mode allows the developer to assist the user and add a transparent overlay to the image, providing hints or additional information (like a link preview).
|
||||||
The overlay could be made non-transparent by the application frontend and as long as the app is open (and in some cases) it could read QR codes in range of the camera lense.
|
The overlay could be made non-transparent by the application frontend and as long as the app is open (and in some cases) it could read QR codes in range of the camera lense.
|
||||||
|
|
||||||
|
|
||||||
#### Out Of Scope
|
#### Out Of Scope
|
||||||
|
|
||||||
- Exploits in the operating system QR code parsing functionality
|
- Exploits in the operating system QR code parsing functionality
|
||||||
|
|||||||
@@ -5,37 +5,37 @@
|
|||||||
import {
|
import {
|
||||||
invoke,
|
invoke,
|
||||||
requestPermissions as checkPermissions_,
|
requestPermissions as checkPermissions_,
|
||||||
checkPermissions as requestPermissions_,
|
checkPermissions as requestPermissions_
|
||||||
} from "@tauri-apps/api/core";
|
} from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export type { PermissionState } from "@tauri-apps/api/core";
|
export type { PermissionState } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export enum Format {
|
export enum Format {
|
||||||
QRCode = "QR_CODE",
|
QRCode = 'QR_CODE',
|
||||||
UPC_A = "UPC_A",
|
UPC_A = 'UPC_A',
|
||||||
UPC_E = "UPC_E",
|
UPC_E = 'UPC_E',
|
||||||
EAN8 = "EAN_8",
|
EAN8 = 'EAN_8',
|
||||||
EAN13 = "EAN_13",
|
EAN13 = 'EAN_13',
|
||||||
Code39 = "CODE_39",
|
Code39 = 'CODE_39',
|
||||||
Code93 = "CODE_93",
|
Code93 = 'CODE_93',
|
||||||
Code128 = "CODE_128",
|
Code128 = 'CODE_128',
|
||||||
Codabar = "CODABAR",
|
Codabar = 'CODABAR',
|
||||||
ITF = "ITF",
|
ITF = 'ITF',
|
||||||
Aztec = "AZTEC",
|
Aztec = 'AZTEC',
|
||||||
DataMatrix = "DATA_MATRIX",
|
DataMatrix = 'DATA_MATRIX',
|
||||||
PDF417 = "PDF_417",
|
PDF417 = 'PDF_417'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScanOptions {
|
export interface ScanOptions {
|
||||||
cameraDirection?: "back" | "front";
|
cameraDirection?: 'back' | 'front'
|
||||||
formats?: Format[];
|
formats?: Format[]
|
||||||
windowed?: boolean;
|
windowed?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Scanned {
|
export interface Scanned {
|
||||||
content: string;
|
content: string
|
||||||
format: Format;
|
format: Format
|
||||||
bounds: unknown;
|
bounds: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,14 +43,14 @@ export interface Scanned {
|
|||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
export async function scan(options?: ScanOptions): Promise<Scanned> {
|
export async function scan(options?: ScanOptions): Promise<Scanned> {
|
||||||
return await invoke("plugin:barcode-scanner|scan", { ...options });
|
return await invoke('plugin:barcode-scanner|scan', { ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the current scan process.
|
* Cancel the current scan process.
|
||||||
*/
|
*/
|
||||||
export async function cancel(): Promise<void> {
|
export async function cancel(): Promise<void> {
|
||||||
await invoke("plugin:barcode-scanner|cancel");
|
await invoke('plugin:barcode-scanner|cancel')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,8 +58,8 @@ export async function cancel(): Promise<void> {
|
|||||||
*/
|
*/
|
||||||
export async function checkPermissions(): Promise<PermissionState> {
|
export async function checkPermissions(): Promise<PermissionState> {
|
||||||
return await checkPermissions_<{ camera: PermissionState }>(
|
return await checkPermissions_<{ camera: PermissionState }>(
|
||||||
"barcode-scanner",
|
'barcode-scanner'
|
||||||
).then((r) => r.camera);
|
).then((r) => r.camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,13 +67,13 @@ export async function checkPermissions(): Promise<PermissionState> {
|
|||||||
*/
|
*/
|
||||||
export async function requestPermissions(): Promise<PermissionState> {
|
export async function requestPermissions(): Promise<PermissionState> {
|
||||||
return await requestPermissions_<{ camera: PermissionState }>(
|
return await requestPermissions_<{ camera: PermissionState }>(
|
||||||
"barcode-scanner",
|
'barcode-scanner'
|
||||||
).then((r) => r.camera);
|
).then((r) => r.camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open application settings. Useful if permission was denied and the user must manually enable it.
|
* Open application settings. Useful if permission was denied and the user must manually enable it.
|
||||||
*/
|
*/
|
||||||
export async function openAppSettings(): Promise<void> {
|
export async function openAppSettings(): Promise<void> {
|
||||||
await invoke("plugin:barcode-scanner|open_app_settings");
|
await invoke('plugin:barcode-scanner|open_app_settings')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -62,8 +62,8 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { authenticate } from "@tauri-apps/plugin-biometric";
|
import { authenticate } from '@tauri-apps/plugin-biometric'
|
||||||
await authenticate('Open your wallet');
|
await authenticate('Open your wallet')
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export enum BiometryType {
|
export enum BiometryType {
|
||||||
None = 0,
|
None = 0,
|
||||||
@@ -11,39 +11,39 @@ export enum BiometryType {
|
|||||||
// Apple FaceID or Android face authentication
|
// Apple FaceID or Android face authentication
|
||||||
FaceID = 2,
|
FaceID = 2,
|
||||||
// Android iris authentication
|
// Android iris authentication
|
||||||
Iris = 3,
|
Iris = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Status {
|
export interface Status {
|
||||||
isAvailable: boolean;
|
isAvailable: boolean
|
||||||
biometryType: BiometryType;
|
biometryType: BiometryType
|
||||||
error?: string;
|
error?: string
|
||||||
errorCode?:
|
errorCode?:
|
||||||
| "appCancel"
|
| 'appCancel'
|
||||||
| "authenticationFailed"
|
| 'authenticationFailed'
|
||||||
| "invalidContext"
|
| 'invalidContext'
|
||||||
| "notInteractive"
|
| 'notInteractive'
|
||||||
| "passcodeNotSet"
|
| 'passcodeNotSet'
|
||||||
| "systemCancel"
|
| 'systemCancel'
|
||||||
| "userCancel"
|
| 'userCancel'
|
||||||
| "userFallback"
|
| 'userFallback'
|
||||||
| "biometryLockout"
|
| 'biometryLockout'
|
||||||
| "biometryNotAvailable"
|
| 'biometryNotAvailable'
|
||||||
| "biometryNotEnrolled";
|
| 'biometryNotEnrolled'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthOptions {
|
export interface AuthOptions {
|
||||||
allowDeviceCredential?: boolean;
|
allowDeviceCredential?: boolean
|
||||||
cancelTitle?: string;
|
cancelTitle?: string
|
||||||
|
|
||||||
// iOS options
|
// iOS options
|
||||||
fallbackTitle?: string;
|
fallbackTitle?: string
|
||||||
|
|
||||||
// android options
|
// android options
|
||||||
title?: string;
|
title?: string
|
||||||
subtitle?: string;
|
subtitle?: string
|
||||||
confirmationRequired?: boolean;
|
confirmationRequired?: boolean
|
||||||
maxAttemps?: number;
|
maxAttemps?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,7 +51,7 @@ export interface AuthOptions {
|
|||||||
* @returns a promise resolving to an object containing all the information about the status of the biometry.
|
* @returns a promise resolving to an object containing all the information about the status of the biometry.
|
||||||
*/
|
*/
|
||||||
export async function checkStatus(): Promise<Status> {
|
export async function checkStatus(): Promise<Status> {
|
||||||
return await invoke("plugin:biometric|status");
|
return await invoke('plugin:biometric|status')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,10 +68,10 @@ export async function checkStatus(): Promise<Status> {
|
|||||||
*/
|
*/
|
||||||
export async function authenticate(
|
export async function authenticate(
|
||||||
reason: string,
|
reason: string,
|
||||||
options?: AuthOptions,
|
options?: AuthOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await invoke("plugin:biometric|authenticate", {
|
await invoke('plugin:biometric|authenticate', {
|
||||||
reason,
|
reason,
|
||||||
...options,
|
...options
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,4 @@ It allows acccess to all biometric commands.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
permissions = [
|
permissions = ["allow-authenticate", "allow-status"]
|
||||||
"allow-authenticate",
|
|
||||||
"allow-status",
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -67,16 +67,16 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { getMatches } from "@tauri-apps/plugin-cli";
|
import { getMatches } from '@tauri-apps/plugin-cli'
|
||||||
const matches = await getMatches();
|
const matches = await getMatches()
|
||||||
if (matches.subcommand?.name === "run") {
|
if (matches.subcommand?.name === 'run') {
|
||||||
// `./your-app run $ARGS` was executed
|
// `./your-app run $ARGS` was executed
|
||||||
const args = matches.subcommand?.matches.args;
|
const args = matches.subcommand?.matches.args
|
||||||
if ("debug" in args) {
|
if ('debug' in args) {
|
||||||
// `./your-app run --debug` was executed
|
// `./your-app run --debug` was executed
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const args = matches.args;
|
const args = matches.args
|
||||||
// `./your-app $ARGS` was executed
|
// `./your-app $ARGS` was executed
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
@@ -19,27 +19,27 @@ interface ArgMatch {
|
|||||||
* boolean if flag
|
* boolean if flag
|
||||||
* string[] or null if takes multiple values
|
* string[] or null if takes multiple values
|
||||||
*/
|
*/
|
||||||
value: string | boolean | string[] | null;
|
value: string | boolean | string[] | null
|
||||||
/**
|
/**
|
||||||
* Number of occurrences
|
* Number of occurrences
|
||||||
*/
|
*/
|
||||||
occurrences: number;
|
occurrences: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
interface SubcommandMatch {
|
interface SubcommandMatch {
|
||||||
name: string;
|
name: string
|
||||||
matches: CliMatches;
|
matches: CliMatches
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
interface CliMatches {
|
interface CliMatches {
|
||||||
args: Record<string, ArgMatch>;
|
args: Record<string, ArgMatch>
|
||||||
subcommand: SubcommandMatch | null;
|
subcommand: SubcommandMatch | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,9 +64,9 @@ interface CliMatches {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function getMatches(): Promise<CliMatches> {
|
async function getMatches(): Promise<CliMatches> {
|
||||||
return await invoke("plugin:cli|cli_matches");
|
return await invoke('plugin:cli|cli_matches')
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { ArgMatch, SubcommandMatch, CliMatches };
|
export type { ArgMatch, SubcommandMatch, CliMatches }
|
||||||
|
|
||||||
export { getMatches };
|
export { getMatches }
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -60,9 +60,15 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { writeText, readText, writeHtml, readHtml, clear } from "@tauri-apps/plugin-clipboard-manager";
|
import {
|
||||||
await writeText("Tauri is awesome!");
|
writeText,
|
||||||
assert(await readText(), "Tauri is awesome!");
|
readText,
|
||||||
|
writeHtml,
|
||||||
|
readHtml,
|
||||||
|
clear
|
||||||
|
} from '@tauri-apps/plugin-clipboard-manager'
|
||||||
|
await writeText('Tauri is awesome!')
|
||||||
|
assert(await readText(), 'Tauri is awesome!')
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { Image, transformImage } from "@tauri-apps/api/image";
|
import { Image, transformImage } from '@tauri-apps/api/image'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes plain text to the clipboard.
|
* Writes plain text to the clipboard.
|
||||||
@@ -26,12 +26,12 @@ import { Image, transformImage } from "@tauri-apps/api/image";
|
|||||||
*/
|
*/
|
||||||
async function writeText(
|
async function writeText(
|
||||||
text: string,
|
text: string,
|
||||||
opts?: { label?: string },
|
opts?: { label?: string }
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await invoke("plugin:clipboard-manager|write_text", {
|
await invoke('plugin:clipboard-manager|write_text', {
|
||||||
label: opts?.label,
|
label: opts?.label,
|
||||||
text,
|
text
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +44,7 @@ async function writeText(
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function readText(): Promise<string> {
|
async function readText(): Promise<string> {
|
||||||
return await invoke("plugin:clipboard-manager|read_text");
|
return await invoke('plugin:clipboard-manager|read_text')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,11 +66,11 @@ async function readText(): Promise<string> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function writeImage(
|
async function writeImage(
|
||||||
image: string | Image | Uint8Array | ArrayBuffer | number[],
|
image: string | Image | Uint8Array | ArrayBuffer | number[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await invoke("plugin:clipboard-manager|write_image", {
|
await invoke('plugin:clipboard-manager|write_image', {
|
||||||
image: transformImage(image),
|
image: transformImage(image)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,9 +86,9 @@ async function writeImage(
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function readImage(): Promise<Image> {
|
async function readImage(): Promise<Image> {
|
||||||
return await invoke<number>("plugin:clipboard-manager|read_image").then(
|
return await invoke<number>('plugin:clipboard-manager|read_image').then(
|
||||||
(rid) => new Image(rid),
|
(rid) => new Image(rid)
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,10 +106,10 @@ async function readImage(): Promise<Image> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function writeHtml(html: string, altHtml?: string): Promise<void> {
|
async function writeHtml(html: string, altHtml?: string): Promise<void> {
|
||||||
await invoke("plugin:clipboard-manager|write_html", {
|
await invoke('plugin:clipboard-manager|write_html', {
|
||||||
html,
|
html,
|
||||||
altHtml,
|
altHtml
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,7 +122,7 @@ async function writeHtml(html: string, altHtml?: string): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function clear(): Promise<void> {
|
async function clear(): Promise<void> {
|
||||||
await invoke("plugin:clipboard-manager|clear");
|
await invoke('plugin:clipboard-manager|clear')
|
||||||
}
|
}
|
||||||
|
|
||||||
export { writeText, readText, writeHtml, clear, readImage, writeImage };
|
export { writeText, readText, writeHtml, clear, readImage, writeImage }
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -2,26 +2,26 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import http from "http";
|
import http from 'http'
|
||||||
import fs from "fs";
|
import fs from 'fs'
|
||||||
|
|
||||||
const hostname = "localhost";
|
const hostname = 'localhost'
|
||||||
const port = 8080;
|
const port = 8080
|
||||||
|
|
||||||
const server = http.createServer(function (req, res) {
|
const server = http.createServer(function (req, res) {
|
||||||
console.log(req.url);
|
console.log(req.url)
|
||||||
if (req.url == "/.well-known/apple-app-site-association") {
|
if (req.url == '/.well-known/apple-app-site-association') {
|
||||||
const association = fs.readFileSync(
|
const association = fs.readFileSync(
|
||||||
".well-known/apple-app-site-association",
|
'.well-known/apple-app-site-association'
|
||||||
);
|
)
|
||||||
res.writeHead(200, { "Content-Type": "application/json" });
|
res.writeHead(200, { 'Content-Type': 'application/json' })
|
||||||
res.end(association);
|
res.end(association)
|
||||||
} else {
|
} else {
|
||||||
res.writeHead(404);
|
res.writeHead(404)
|
||||||
res.end("404 NOT FOUND");
|
res.end('404 NOT FOUND')
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
server.listen(port, hostname, () => {
|
server.listen(port, hostname, () => {
|
||||||
console.log("Server started on port", port);
|
console.log('Server started on port', port)
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -139,10 +139,10 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { onOpenUrl } from "@tauri-apps/plugin-deep-link";
|
import { onOpenUrl } from '@tauri-apps/plugin-deep-link'
|
||||||
await onOpenUrl((urls) => {
|
await onOpenUrl((urls) => {
|
||||||
console.log("deep link:", urls);
|
console.log('deep link:', urls)
|
||||||
});
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the Plugin will only emit events on macOS, iOS and Android. On Windows and Linux the OS will spawn a new instance of your app with the URL as a CLI argument. If you want your app to behave on Windows & Linux similar to the other platforms you can use the [single-instance](../single-instance/) plugin.
|
Note that the Plugin will only emit events on macOS, iOS and Android. On Windows and Linux the OS will spawn a new instance of your app with the URL as a CLI argument. If you want your app to behave on Windows & Linux similar to the other platforms you can use the [single-instance](../single-instance/) plugin.
|
||||||
|
|||||||
@@ -2,30 +2,30 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import http from "http";
|
import http from 'http'
|
||||||
import fs from "fs";
|
import fs from 'fs'
|
||||||
import path from "path";
|
import path from 'path'
|
||||||
import * as url from "url";
|
import * as url from 'url'
|
||||||
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||||
|
|
||||||
const port = 8125;
|
const port = 8125
|
||||||
|
|
||||||
http
|
http
|
||||||
.createServer(function (request, response) {
|
.createServer(function (request, response) {
|
||||||
if (request.url === "/.well-known/apple-app-site-association") {
|
if (request.url === '/.well-known/apple-app-site-association') {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
fs.readFile(
|
fs.readFile(
|
||||||
path.resolve(__dirname, "apple-app-site-association"),
|
path.resolve(__dirname, 'apple-app-site-association'),
|
||||||
function (_error, content) {
|
function (_error, content) {
|
||||||
response.writeHead(200);
|
response.writeHead(200)
|
||||||
response.end(content, "utf-8");
|
response.end(content, 'utf-8')
|
||||||
},
|
}
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
response.writeHead(404);
|
response.writeHead(404)
|
||||||
response.end();
|
response.end()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.listen(port);
|
.listen(port)
|
||||||
|
|
||||||
console.log(`Server running at http://127.0.0.1:${port}/`);
|
console.log(`Server running at http://127.0.0.1:${port}/`)
|
||||||
|
|||||||
@@ -4,35 +4,35 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
onOpenUrl,
|
onOpenUrl,
|
||||||
getCurrent as getCurrentDeepLinkUrls,
|
getCurrent as getCurrentDeepLinkUrls
|
||||||
} from "@tauri-apps/plugin-deep-link";
|
} from '@tauri-apps/plugin-deep-link'
|
||||||
|
|
||||||
function handler(urls: string[]) {
|
function handler(urls: string[]) {
|
||||||
console.log(urls);
|
console.log(urls)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const updateIntentEl = document.querySelector("#event-intent")!;
|
const updateIntentEl = document.querySelector('#event-intent')!
|
||||||
updateIntentEl.textContent = JSON.stringify(urls);
|
updateIntentEl.textContent = JSON.stringify(urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("DOMContentLoaded", () => {
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
onOpenUrl(handler);
|
onOpenUrl(handler)
|
||||||
|
|
||||||
document.querySelector("#intent-form")?.addEventListener("submit", (e) => {
|
document.querySelector('#intent-form')?.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
getCurrentDeepLinkUrls()
|
getCurrentDeepLinkUrls()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const updateIntentEl = document.querySelector("#update-intent")!;
|
const updateIntentEl = document.querySelector('#update-intent')!
|
||||||
updateIntentEl.textContent = res ? JSON.stringify(res) : "none";
|
updateIntentEl.textContent = res ? JSON.stringify(res) : 'none'
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
|
||||||
});
|
|
||||||
|
|
||||||
getCurrentDeepLinkUrls()
|
getCurrentDeepLinkUrls()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const initialIntentEl = document.querySelector("#initial-intent")!;
|
const initialIntentEl = document.querySelector('#initial-intent')!
|
||||||
initialIntentEl.textContent = res ? JSON.stringify(res) : "none";
|
initialIntentEl.textContent = res ? JSON.stringify(res) : 'none'
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
const host = process.env.TAURI_DEV_HOST;
|
const host = process.env.TAURI_DEV_HOST
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -17,22 +17,22 @@ export default defineConfig({
|
|||||||
port: 1420,
|
port: 1420,
|
||||||
hmr: host
|
hmr: host
|
||||||
? {
|
? {
|
||||||
protocol: "ws",
|
protocol: 'ws',
|
||||||
host,
|
host,
|
||||||
port: 1421,
|
port: 1421
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
strictPort: true,
|
strictPort: true
|
||||||
},
|
},
|
||||||
// to make use of `TAURI_DEBUG` and other env variables
|
// to make use of `TAURI_DEBUG` and other env variables
|
||||||
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
|
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
|
||||||
envPrefix: ["VITE_", "TAURI_"],
|
envPrefix: ['VITE_', 'TAURI_'],
|
||||||
build: {
|
build: {
|
||||||
// Tauri supports es2021
|
// Tauri supports es2021
|
||||||
target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13",
|
target: process.env.TAURI_PLATFORM == 'windows' ? 'chrome105' : 'safari13',
|
||||||
// don't minify for debug builds
|
// don't minify for debug builds
|
||||||
minify: !process.env.TAURI_DEBUG ? "esbuild" : false,
|
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
|
||||||
// produce sourcemaps for debug builds
|
// produce sourcemaps for debug builds
|
||||||
sourcemap: !!process.env.TAURI_DEBUG,
|
sourcemap: !!process.env.TAURI_DEBUG
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { type UnlistenFn, listen } from "@tauri-apps/api/event";
|
import { type UnlistenFn, listen } from '@tauri-apps/api/event'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current URLs that triggered the deep link. Use this on app load to check whether your app was started via a deep link.
|
* Get the current URLs that triggered the deep link. Use this on app load to check whether your app was started via a deep link.
|
||||||
@@ -19,7 +19,7 @@ import { type UnlistenFn, listen } from "@tauri-apps/api/event";
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
export async function getCurrent(): Promise<string[] | null> {
|
export async function getCurrent(): Promise<string[] | null> {
|
||||||
return await invoke("plugin:deep-link|get_current");
|
return await invoke('plugin:deep-link|get_current')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,7 +38,7 @@ export async function getCurrent(): Promise<string[] | null> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
export async function register(protocol: string): Promise<null> {
|
export async function register(protocol: string): Promise<null> {
|
||||||
return await invoke("plugin:deep-link|register", { protocol });
|
return await invoke('plugin:deep-link|register', { protocol })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +57,7 @@ export async function register(protocol: string): Promise<null> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
export async function unregister(protocol: string): Promise<null> {
|
export async function unregister(protocol: string): Promise<null> {
|
||||||
return await invoke("plugin:deep-link|unregister", { protocol });
|
return await invoke('plugin:deep-link|unregister', { protocol })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +76,7 @@ export async function unregister(protocol: string): Promise<null> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
export async function isRegistered(protocol: string): Promise<boolean> {
|
export async function isRegistered(protocol: string): Promise<boolean> {
|
||||||
return await invoke("plugin:deep-link|is_registered", { protocol });
|
return await invoke('plugin:deep-link|is_registered', { protocol })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,14 +95,14 @@ export async function isRegistered(protocol: string): Promise<boolean> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
export async function onOpenUrl(
|
export async function onOpenUrl(
|
||||||
handler: (urls: string[]) => void,
|
handler: (urls: string[]) => void
|
||||||
): Promise<UnlistenFn> {
|
): Promise<UnlistenFn> {
|
||||||
const current = await getCurrent();
|
const current = await getCurrent()
|
||||||
if (current) {
|
if (current) {
|
||||||
handler(current);
|
handler(current)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await listen<string[]>("deep-link://new-url", (event) => {
|
return await listen<string[]>('deep-link://new-url', (event) => {
|
||||||
handler(event.payload);
|
handler(event.payload)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
.tauri
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension filters for the file dialog.
|
* Extension filters for the file dialog.
|
||||||
@@ -11,7 +11,7 @@ import { invoke } from "@tauri-apps/api/core";
|
|||||||
*/
|
*/
|
||||||
interface DialogFilter {
|
interface DialogFilter {
|
||||||
/** Filter name. */
|
/** Filter name. */
|
||||||
name: string;
|
name: string
|
||||||
/**
|
/**
|
||||||
* Extensions to filter, without a `.` prefix.
|
* Extensions to filter, without a `.` prefix.
|
||||||
* @example
|
* @example
|
||||||
@@ -19,7 +19,7 @@ interface DialogFilter {
|
|||||||
* extensions: ['svg', 'png']
|
* extensions: ['svg', 'png']
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
extensions: string[];
|
extensions: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,9 +29,9 @@ interface DialogFilter {
|
|||||||
*/
|
*/
|
||||||
interface OpenDialogOptions {
|
interface OpenDialogOptions {
|
||||||
/** The title of the dialog window (desktop only). */
|
/** The title of the dialog window (desktop only). */
|
||||||
title?: string;
|
title?: string
|
||||||
/** The filters of the dialog. */
|
/** The filters of the dialog. */
|
||||||
filters?: DialogFilter[];
|
filters?: DialogFilter[]
|
||||||
/**
|
/**
|
||||||
* Initial directory or file path.
|
* Initial directory or file path.
|
||||||
* If it's a directory path, the dialog interface will change to that folder.
|
* If it's a directory path, the dialog interface will change to that folder.
|
||||||
@@ -40,18 +40,18 @@ interface OpenDialogOptions {
|
|||||||
* On mobile the file name is always used on the dialog's file name input.
|
* On mobile the file name is always used on the dialog's file name input.
|
||||||
* If not provided, Android uses `(invalid).txt` as default file name.
|
* If not provided, Android uses `(invalid).txt` as default file name.
|
||||||
*/
|
*/
|
||||||
defaultPath?: string;
|
defaultPath?: string
|
||||||
/** Whether the dialog allows multiple selection or not. */
|
/** Whether the dialog allows multiple selection or not. */
|
||||||
multiple?: boolean;
|
multiple?: boolean
|
||||||
/** Whether the dialog is a directory selection or not. */
|
/** Whether the dialog is a directory selection or not. */
|
||||||
directory?: boolean;
|
directory?: boolean
|
||||||
/**
|
/**
|
||||||
* If `directory` is true, indicates that it will be read recursively later.
|
* If `directory` is true, indicates that it will be read recursively later.
|
||||||
* Defines whether subdirectories will be allowed on the scope or not.
|
* Defines whether subdirectories will be allowed on the scope or not.
|
||||||
*/
|
*/
|
||||||
recursive?: boolean;
|
recursive?: boolean
|
||||||
/** Whether to allow creating directories in the dialog. Enabled by default. **macOS Only** */
|
/** Whether to allow creating directories in the dialog. Enabled by default. **macOS Only** */
|
||||||
canCreateDirectories?: boolean;
|
canCreateDirectories?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,9 +61,9 @@ interface OpenDialogOptions {
|
|||||||
*/
|
*/
|
||||||
interface SaveDialogOptions {
|
interface SaveDialogOptions {
|
||||||
/** The title of the dialog window (desktop only). */
|
/** The title of the dialog window (desktop only). */
|
||||||
title?: string;
|
title?: string
|
||||||
/** The filters of the dialog. */
|
/** The filters of the dialog. */
|
||||||
filters?: DialogFilter[];
|
filters?: DialogFilter[]
|
||||||
/**
|
/**
|
||||||
* Initial directory or file path.
|
* Initial directory or file path.
|
||||||
* If it's a directory path, the dialog interface will change to that folder.
|
* If it's a directory path, the dialog interface will change to that folder.
|
||||||
@@ -72,9 +72,9 @@ interface SaveDialogOptions {
|
|||||||
* On mobile the file name is always used on the dialog's file name input.
|
* On mobile the file name is always used on the dialog's file name input.
|
||||||
* If not provided, Android uses `(invalid).txt` as default file name.
|
* If not provided, Android uses `(invalid).txt` as default file name.
|
||||||
*/
|
*/
|
||||||
defaultPath?: string;
|
defaultPath?: string
|
||||||
/** Whether to allow creating directories in the dialog. Enabled by default. **macOS Only** */
|
/** Whether to allow creating directories in the dialog. Enabled by default. **macOS Only** */
|
||||||
canCreateDirectories?: boolean;
|
canCreateDirectories?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,31 +82,31 @@ interface SaveDialogOptions {
|
|||||||
*/
|
*/
|
||||||
interface MessageDialogOptions {
|
interface MessageDialogOptions {
|
||||||
/** The title of the dialog. Defaults to the app name. */
|
/** The title of the dialog. Defaults to the app name. */
|
||||||
title?: string;
|
title?: string
|
||||||
/** The kind of the dialog. Defaults to `info`. */
|
/** The kind of the dialog. Defaults to `info`. */
|
||||||
kind?: "info" | "warning" | "error";
|
kind?: 'info' | 'warning' | 'error'
|
||||||
/** The label of the confirm button. */
|
/** The label of the confirm button. */
|
||||||
okLabel?: string;
|
okLabel?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConfirmDialogOptions {
|
interface ConfirmDialogOptions {
|
||||||
/** The title of the dialog. Defaults to the app name. */
|
/** The title of the dialog. Defaults to the app name. */
|
||||||
title?: string;
|
title?: string
|
||||||
/** The kind of the dialog. Defaults to `info`. */
|
/** The kind of the dialog. Defaults to `info`. */
|
||||||
kind?: "info" | "warning" | "error";
|
kind?: 'info' | 'warning' | 'error'
|
||||||
/** The label of the confirm button. */
|
/** The label of the confirm button. */
|
||||||
okLabel?: string;
|
okLabel?: string
|
||||||
/** The label of the cancel button. */
|
/** The label of the cancel button. */
|
||||||
cancelLabel?: string;
|
cancelLabel?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpenDialogReturn<T extends OpenDialogOptions> = T["directory"] extends true
|
type OpenDialogReturn<T extends OpenDialogOptions> = T['directory'] extends true
|
||||||
? T["multiple"] extends true
|
? T['multiple'] extends true
|
||||||
? string[] | null
|
? string[] | null
|
||||||
: string | null
|
: string | null
|
||||||
: T["multiple"] extends true
|
: T['multiple'] extends true
|
||||||
? string[] | null
|
? string[] | null
|
||||||
: string | null;
|
: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a file/directory selection dialog.
|
* Open a file/directory selection dialog.
|
||||||
@@ -161,13 +161,13 @@ type OpenDialogReturn<T extends OpenDialogOptions> = T["directory"] extends true
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function open<T extends OpenDialogOptions>(
|
async function open<T extends OpenDialogOptions>(
|
||||||
options: T = {} as T,
|
options: T = {} as T
|
||||||
): Promise<OpenDialogReturn<T>> {
|
): Promise<OpenDialogReturn<T>> {
|
||||||
if (typeof options === "object") {
|
if (typeof options === 'object') {
|
||||||
Object.freeze(options);
|
Object.freeze(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await invoke("plugin:dialog|open", { options });
|
return await invoke('plugin:dialog|open', { options })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,11 +195,11 @@ async function open<T extends OpenDialogOptions>(
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function save(options: SaveDialogOptions = {}): Promise<string | null> {
|
async function save(options: SaveDialogOptions = {}): Promise<string | null> {
|
||||||
if (typeof options === "object") {
|
if (typeof options === 'object') {
|
||||||
Object.freeze(options);
|
Object.freeze(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await invoke("plugin:dialog|save", { options });
|
return await invoke('plugin:dialog|save', { options })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -221,15 +221,15 @@ async function save(options: SaveDialogOptions = {}): Promise<string | null> {
|
|||||||
*/
|
*/
|
||||||
async function message(
|
async function message(
|
||||||
message: string,
|
message: string,
|
||||||
options?: string | MessageDialogOptions,
|
options?: string | MessageDialogOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const opts = typeof options === "string" ? { title: options } : options;
|
const opts = typeof options === 'string' ? { title: options } : options
|
||||||
await invoke("plugin:dialog|message", {
|
await invoke('plugin:dialog|message', {
|
||||||
message: message.toString(),
|
message: message.toString(),
|
||||||
title: opts?.title?.toString(),
|
title: opts?.title?.toString(),
|
||||||
kind: opts?.kind,
|
kind: opts?.kind,
|
||||||
okButtonLabel: opts?.okLabel?.toString(),
|
okButtonLabel: opts?.okLabel?.toString()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,16 +250,16 @@ async function message(
|
|||||||
*/
|
*/
|
||||||
async function ask(
|
async function ask(
|
||||||
message: string,
|
message: string,
|
||||||
options?: string | ConfirmDialogOptions,
|
options?: string | ConfirmDialogOptions
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const opts = typeof options === "string" ? { title: options } : options;
|
const opts = typeof options === 'string' ? { title: options } : options
|
||||||
return await invoke("plugin:dialog|ask", {
|
return await invoke('plugin:dialog|ask', {
|
||||||
message: message.toString(),
|
message: message.toString(),
|
||||||
title: opts?.title?.toString(),
|
title: opts?.title?.toString(),
|
||||||
kind: opts?.kind,
|
kind: opts?.kind,
|
||||||
okButtonLabel: opts?.okLabel?.toString() ?? "Yes",
|
okButtonLabel: opts?.okLabel?.toString() ?? 'Yes',
|
||||||
cancelButtonLabel: opts?.cancelLabel?.toString() ?? "No",
|
cancelButtonLabel: opts?.cancelLabel?.toString() ?? 'No'
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,16 +280,16 @@ async function ask(
|
|||||||
*/
|
*/
|
||||||
async function confirm(
|
async function confirm(
|
||||||
message: string,
|
message: string,
|
||||||
options?: string | ConfirmDialogOptions,
|
options?: string | ConfirmDialogOptions
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const opts = typeof options === "string" ? { title: options } : options;
|
const opts = typeof options === 'string' ? { title: options } : options
|
||||||
return await invoke("plugin:dialog|confirm", {
|
return await invoke('plugin:dialog|confirm', {
|
||||||
message: message.toString(),
|
message: message.toString(),
|
||||||
title: opts?.title?.toString(),
|
title: opts?.title?.toString(),
|
||||||
kind: opts?.kind,
|
kind: opts?.kind,
|
||||||
okButtonLabel: opts?.okLabel?.toString() ?? "Ok",
|
okButtonLabel: opts?.okLabel?.toString() ?? 'Ok',
|
||||||
cancelButtonLabel: opts?.cancelLabel?.toString() ?? "Cancel",
|
cancelButtonLabel: opts?.cancelLabel?.toString() ?? 'Cancel'
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
@@ -298,7 +298,7 @@ export type {
|
|||||||
OpenDialogReturn,
|
OpenDialogReturn,
|
||||||
SaveDialogOptions,
|
SaveDialogOptions,
|
||||||
MessageDialogOptions,
|
MessageDialogOptions,
|
||||||
ConfirmDialogOptions,
|
ConfirmDialogOptions
|
||||||
};
|
}
|
||||||
|
|
||||||
export { open, save, message, ask, confirm };
|
export { open, save, message, ask, confirm }
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
window.alert = function (message: string) {
|
window.alert = function (message: string) {
|
||||||
void invoke("plugin:dialog|message", {
|
void invoke('plugin:dialog|message', {
|
||||||
message: message.toString(),
|
message: message.toString()
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
// @ts-expect-error tauri does not have sync IPC :(
|
// @ts-expect-error tauri does not have sync IPC :(
|
||||||
window.confirm = async function (message: string) {
|
window.confirm = async function (message: string) {
|
||||||
return await invoke("plugin:dialog|confirm", {
|
return await invoke('plugin:dialog|confirm', {
|
||||||
message: message.toString(),
|
message: message.toString()
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -2,21 +2,21 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||||
import typescript from "@rollup/plugin-typescript";
|
import typescript from '@rollup/plugin-typescript'
|
||||||
import terser from "@rollup/plugin-terser";
|
import terser from '@rollup/plugin-terser'
|
||||||
|
|
||||||
export default createConfig({
|
export default createConfig({
|
||||||
additionalConfigs: {
|
additionalConfigs: {
|
||||||
input: "guest-js/init.ts",
|
input: 'guest-js/init.ts',
|
||||||
output: {
|
output: {
|
||||||
file: "src/init-iife.js",
|
file: 'src/init-iife.js',
|
||||||
format: "iife",
|
format: 'iife'
|
||||||
},
|
},
|
||||||
plugins: [typescript(), terser(), nodeResolve()],
|
plugins: [typescript(), terser(), nodeResolve()],
|
||||||
onwarn: (warning) => {
|
onwarn: (warning) => {
|
||||||
throw Object.assign(new Error(), warning);
|
throw Object.assign(new Error(), warning)
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
node_modules
|
|
||||||
@@ -60,9 +60,9 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { metadata } from "@tauri-apps/plugin-fs";
|
import { metadata } from '@tauri-apps/plugin-fs'
|
||||||
|
|
||||||
await metadata("/path/to/file");
|
await metadata('/path/to/file')
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ the restrictions imposed by the scope.
|
|||||||
|
|
||||||
The scope is defined at compile time in the used permissions but the user or application developer can grant or revoke access to specific files or folders at runtime by modifying the scope state through the runtime authority, if configured during plugin initialization.
|
The scope is defined at compile time in the used permissions but the user or application developer can grant or revoke access to specific files or folders at runtime by modifying the scope state through the runtime authority, if configured during plugin initialization.
|
||||||
|
|
||||||
|
|
||||||
### Security Assumptions
|
### Security Assumptions
|
||||||
|
|
||||||
- The filesystem access is limited by user permissions
|
- The filesystem access is limited by user permissions
|
||||||
@@ -44,7 +43,6 @@ The scope is defined at compile time in the used permissions but the user or app
|
|||||||
- The scoping mechanism of the Tauri `fs` commands work as intended and has no bypasses
|
- The scoping mechanism of the Tauri `fs` commands work as intended and has no bypasses
|
||||||
- The user or application developer can grant or revoke access to specific files at runtime by modifying the scope
|
- The user or application developer can grant or revoke access to specific files at runtime by modifying the scope
|
||||||
|
|
||||||
|
|
||||||
#### Out Of Scope
|
#### Out Of Scope
|
||||||
|
|
||||||
- Exploits in underlying filesystems
|
- Exploits in underlying filesystems
|
||||||
|
|||||||
+267
-269
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -87,16 +87,16 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { getCurrentPosition, watchPosition } from "@tauri-apps/plugin-log";
|
import { getCurrentPosition, watchPosition } from '@tauri-apps/plugin-log'
|
||||||
|
|
||||||
const pos = await getCurrentPosition();
|
const pos = await getCurrentPosition()
|
||||||
|
|
||||||
await watchPosition(
|
await watchPosition(
|
||||||
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 },
|
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 },
|
||||||
(pos) => {
|
(pos) => {
|
||||||
console.log(pos);
|
console.log(pos)
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -9,77 +9,77 @@
|
|||||||
|
|
||||||
export const commands = {
|
export const commands = {
|
||||||
async getCurrentPosition(
|
async getCurrentPosition(
|
||||||
options: PositionOptions | null,
|
options: PositionOptions | null
|
||||||
): Promise<Result<Position, Error>> {
|
): Promise<Result<Position, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:geolocation|get_current_position", {
|
data: await TAURI_INVOKE('plugin:geolocation|get_current_position', {
|
||||||
options,
|
options
|
||||||
}),
|
})
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async watchPosition(
|
async watchPosition(
|
||||||
options: PositionOptions,
|
options: PositionOptions,
|
||||||
channel: any,
|
channel: any
|
||||||
): Promise<Result<null, Error>> {
|
): Promise<Result<null, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:geolocation|watch_position", {
|
data: await TAURI_INVOKE('plugin:geolocation|watch_position', {
|
||||||
options,
|
options,
|
||||||
channel,
|
channel
|
||||||
}),
|
})
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async clearWatch(channelId: number): Promise<Result<null, Error>> {
|
async clearWatch(channelId: number): Promise<Result<null, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:geolocation|clear_watch", {
|
data: await TAURI_INVOKE('plugin:geolocation|clear_watch', {
|
||||||
channelId,
|
channelId
|
||||||
}),
|
})
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async checkPermissions(): Promise<Result<PermissionStatus, Error>> {
|
async checkPermissions(): Promise<Result<PermissionStatus, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:geolocation|check_permissions"),
|
data: await TAURI_INVOKE('plugin:geolocation|check_permissions')
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async requestPermissions(
|
async requestPermissions(
|
||||||
permissions: PermissionType[] | null,
|
permissions: PermissionType[] | null
|
||||||
): Promise<Result<PermissionStatus, Error>> {
|
): Promise<Result<PermissionStatus, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:geolocation|request_permissions", {
|
data: await TAURI_INVOKE('plugin:geolocation|request_permissions', {
|
||||||
permissions,
|
permissions
|
||||||
}),
|
})
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/** user-defined events **/
|
/** user-defined events **/
|
||||||
|
|
||||||
@@ -97,31 +97,31 @@ export type Coordinates = {
|
|||||||
/**
|
/**
|
||||||
* Latitude in decimal degrees.
|
* Latitude in decimal degrees.
|
||||||
*/
|
*/
|
||||||
latitude: number;
|
latitude: number
|
||||||
/**
|
/**
|
||||||
* Longitude in decimal degrees.
|
* Longitude in decimal degrees.
|
||||||
*/
|
*/
|
||||||
longitude: number;
|
longitude: number
|
||||||
/**
|
/**
|
||||||
* Accuracy level of the latitude and longitude coordinates in meters.
|
* Accuracy level of the latitude and longitude coordinates in meters.
|
||||||
*/
|
*/
|
||||||
accuracy: number;
|
accuracy: number
|
||||||
/**
|
/**
|
||||||
* Accuracy level of the altitude coordinate in meters, if available.
|
* Accuracy level of the altitude coordinate in meters, if available.
|
||||||
* Available on all iOS versions and on Android 8 and above.
|
* Available on all iOS versions and on Android 8 and above.
|
||||||
*/
|
*/
|
||||||
altitudeAccuracy: number | null;
|
altitudeAccuracy: number | null
|
||||||
/**
|
/**
|
||||||
* The altitude the user is at, if available.
|
* The altitude the user is at, if available.
|
||||||
*/
|
*/
|
||||||
altitude: number | null;
|
altitude: number | null
|
||||||
speed: number | null;
|
speed: number | null
|
||||||
/**
|
/**
|
||||||
* The heading the user is facing, if available.
|
* The heading the user is facing, if available.
|
||||||
*/
|
*/
|
||||||
heading: number | null;
|
heading: number | null
|
||||||
};
|
}
|
||||||
export type Error = never;
|
export type Error = never
|
||||||
/**
|
/**
|
||||||
* Permission state.
|
* Permission state.
|
||||||
*/
|
*/
|
||||||
@@ -129,15 +129,15 @@ export type PermissionState =
|
|||||||
/**
|
/**
|
||||||
* Permission access has been granted.
|
* Permission access has been granted.
|
||||||
*/
|
*/
|
||||||
| "granted"
|
| 'granted'
|
||||||
/**
|
/**
|
||||||
* Permission access has been denied.
|
* Permission access has been denied.
|
||||||
*/
|
*/
|
||||||
| "denied"
|
| 'denied'
|
||||||
/**
|
/**
|
||||||
* The end user should be prompted for permission.
|
* The end user should be prompted for permission.
|
||||||
*/
|
*/
|
||||||
| "prompt";
|
| 'prompt'
|
||||||
export type PermissionStatus = {
|
export type PermissionStatus = {
|
||||||
/**
|
/**
|
||||||
* Permission state for the location alias.
|
* Permission state for the location alias.
|
||||||
@@ -146,7 +146,7 @@ export type PermissionStatus = {
|
|||||||
*
|
*
|
||||||
* On iOS it requests/checks location permissions.
|
* On iOS it requests/checks location permissions.
|
||||||
*/
|
*/
|
||||||
location: PermissionState;
|
location: PermissionState
|
||||||
/**
|
/**
|
||||||
* Permissions state for the coarseLoaction alias.
|
* Permissions state for the coarseLoaction alias.
|
||||||
*
|
*
|
||||||
@@ -156,93 +156,93 @@ export type PermissionStatus = {
|
|||||||
*
|
*
|
||||||
* On iOS it will have the same value as the `location` alias.
|
* On iOS it will have the same value as the `location` alias.
|
||||||
*/
|
*/
|
||||||
coarseLocation: PermissionState;
|
coarseLocation: PermissionState
|
||||||
};
|
}
|
||||||
export type PermissionType = "location" | "coarseLocation";
|
export type PermissionType = 'location' | 'coarseLocation'
|
||||||
export type Position = {
|
export type Position = {
|
||||||
/**
|
/**
|
||||||
* Creation time for these coordinates.
|
* Creation time for these coordinates.
|
||||||
*/
|
*/
|
||||||
timestamp: number;
|
timestamp: number
|
||||||
/**
|
/**
|
||||||
* The GPD coordinates along with the accuracy of the data.
|
* The GPD coordinates along with the accuracy of the data.
|
||||||
*/
|
*/
|
||||||
coords: Coordinates;
|
coords: Coordinates
|
||||||
};
|
}
|
||||||
export type PositionOptions = {
|
export type PositionOptions = {
|
||||||
/**
|
/**
|
||||||
* High accuracy mode (such as GPS, if available)
|
* High accuracy mode (such as GPS, if available)
|
||||||
* Will be ignored on Android 12+ if users didn't grant the ACCESS_FINE_LOCATION permission.
|
* Will be ignored on Android 12+ if users didn't grant the ACCESS_FINE_LOCATION permission.
|
||||||
*/
|
*/
|
||||||
enableHighAccuracy: boolean;
|
enableHighAccuracy: boolean
|
||||||
/**
|
/**
|
||||||
* The maximum wait time in milliseconds for location updates.
|
* The maximum wait time in milliseconds for location updates.
|
||||||
* On Android the timeout gets ignored for getCurrentPosition.
|
* On Android the timeout gets ignored for getCurrentPosition.
|
||||||
* Ignored on iOS
|
* Ignored on iOS
|
||||||
*/
|
*/
|
||||||
timeout: number;
|
timeout: number
|
||||||
/**
|
/**
|
||||||
* The maximum age in milliseconds of a possible cached position that is acceptable to return.
|
* The maximum age in milliseconds of a possible cached position that is acceptable to return.
|
||||||
* Default: 0
|
* Default: 0
|
||||||
* Ignored on iOS
|
* Ignored on iOS
|
||||||
*/
|
*/
|
||||||
maximumAge: number;
|
maximumAge: number
|
||||||
};
|
}
|
||||||
//export type RandomNumber = number;
|
//export type RandomNumber = number;
|
||||||
|
|
||||||
/** tauri-specta globals **/
|
/** tauri-specta globals **/
|
||||||
|
|
||||||
import { invoke as TAURI_INVOKE } from "@tauri-apps/api/core";
|
import { invoke as TAURI_INVOKE } from '@tauri-apps/api/core'
|
||||||
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
|
import * as TAURI_API_EVENT from '@tauri-apps/api/event'
|
||||||
import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webviewWindow";
|
import { type WebviewWindow as __WebviewWindow__ } from '@tauri-apps/api/webviewWindow'
|
||||||
|
|
||||||
type __EventObj__<T> = {
|
type __EventObj__<T> = {
|
||||||
listen: (
|
listen: (
|
||||||
cb: TAURI_API_EVENT.EventCallback<T>,
|
cb: TAURI_API_EVENT.EventCallback<T>
|
||||||
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
|
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>
|
||||||
once: (
|
once: (
|
||||||
cb: TAURI_API_EVENT.EventCallback<T>,
|
cb: TAURI_API_EVENT.EventCallback<T>
|
||||||
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
|
) => ReturnType<typeof TAURI_API_EVENT.once<T>>
|
||||||
emit: T extends null
|
emit: T extends null
|
||||||
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
|
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
|
||||||
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
|
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>
|
||||||
};
|
}
|
||||||
|
|
||||||
export type Result<T, E> =
|
export type Result<T, E> =
|
||||||
| { status: "ok"; data: T }
|
| { status: 'ok'; data: T }
|
||||||
| { status: "error"; error: E };
|
| { status: 'error'; error: E }
|
||||||
|
|
||||||
function __makeEvents__<T extends Record<string, any>>(
|
function __makeEvents__<T extends Record<string, any>>(
|
||||||
mappings: Record<keyof T, string>,
|
mappings: Record<keyof T, string>
|
||||||
) {
|
) {
|
||||||
return new Proxy(
|
return new Proxy(
|
||||||
{} as unknown as {
|
{} as unknown as {
|
||||||
[K in keyof T]: __EventObj__<T[K]> & {
|
[K in keyof T]: __EventObj__<T[K]> & {
|
||||||
(handle: __WebviewWindow__): __EventObj__<T[K]>;
|
(handle: __WebviewWindow__): __EventObj__<T[K]>
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
get: (_, event) => {
|
get: (_, event) => {
|
||||||
const name = mappings[event as keyof T];
|
const name = mappings[event as keyof T]
|
||||||
|
|
||||||
return new Proxy((() => {}) as any, {
|
return new Proxy((() => {}) as any, {
|
||||||
apply: (_, __, [window]: [__WebviewWindow__]) => ({
|
apply: (_, __, [window]: [__WebviewWindow__]) => ({
|
||||||
listen: (arg: any) => window.listen(name, arg),
|
listen: (arg: any) => window.listen(name, arg),
|
||||||
once: (arg: any) => window.once(name, arg),
|
once: (arg: any) => window.once(name, arg),
|
||||||
emit: (arg: any) => window.emit(name, arg),
|
emit: (arg: any) => window.emit(name, arg)
|
||||||
}),
|
}),
|
||||||
get: (_, command: keyof __EventObj__<any>) => {
|
get: (_, command: keyof __EventObj__<any>) => {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "listen":
|
case 'listen':
|
||||||
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
|
return (arg: any) => TAURI_API_EVENT.listen(name, arg)
|
||||||
case "once":
|
case 'once':
|
||||||
return (arg: any) => TAURI_API_EVENT.once(name, arg);
|
return (arg: any) => TAURI_API_EVENT.once(name, arg)
|
||||||
case "emit":
|
case 'emit':
|
||||||
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
|
return (arg: any) => TAURI_API_EVENT.emit(name, arg)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,26 +4,26 @@
|
|||||||
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
|
|
||||||
import { Channel } from "@tauri-apps/api/core";
|
import { Channel } from '@tauri-apps/api/core'
|
||||||
import { commands, type PositionOptions, type Position } from "./bindings";
|
import { commands, type PositionOptions, type Position } from './bindings'
|
||||||
|
|
||||||
export async function watchPosition(
|
export async function watchPosition(
|
||||||
options: PositionOptions,
|
options: PositionOptions,
|
||||||
// TODO: This can receive errors too
|
// TODO: This can receive errors too
|
||||||
cb: (location: Position | string) => void,
|
cb: (location: Position | string) => void
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const channel = new Channel<Position>();
|
const channel = new Channel<Position>()
|
||||||
channel.onmessage = cb;
|
channel.onmessage = cb
|
||||||
await commands.watchPosition(options, channel);
|
await commands.watchPosition(options, channel)
|
||||||
return channel.id;
|
return channel.id
|
||||||
}
|
}
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
getCurrentPosition,
|
getCurrentPosition,
|
||||||
clearWatch,
|
clearWatch,
|
||||||
checkPermissions,
|
checkPermissions,
|
||||||
requestPermissions,
|
requestPermissions
|
||||||
} = commands;
|
} = commands
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
PermissionState,
|
PermissionState,
|
||||||
@@ -31,7 +31,7 @@ export type {
|
|||||||
PermissionType,
|
PermissionType,
|
||||||
Position,
|
Position,
|
||||||
PositionOptions,
|
PositionOptions,
|
||||||
Coordinates,
|
Coordinates
|
||||||
} from "./bindings";
|
} from './bindings'
|
||||||
|
|
||||||
// export { events };
|
// export { events };
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -87,12 +87,12 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { register } from "@tauri-apps/plugin-global-shortcut";
|
import { register } from '@tauri-apps/plugin-global-shortcut'
|
||||||
await register("CommandOrControl+Shift+C", (event) => {
|
await register('CommandOrControl+Shift+C', (event) => {
|
||||||
if (event.state === "Pressed") {
|
if (event.state === 'Pressed') {
|
||||||
console.log("Shortcut triggered");
|
console.log('Shortcut triggered')
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -8,15 +8,15 @@
|
|||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { invoke, Channel } from "@tauri-apps/api/core";
|
import { invoke, Channel } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export interface ShortcutEvent {
|
export interface ShortcutEvent {
|
||||||
shortcut: string;
|
shortcut: string
|
||||||
id: number;
|
id: number
|
||||||
state: "Released" | "Pressed";
|
state: 'Released' | 'Pressed'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShortcutHandler = (event: ShortcutEvent) => void;
|
export type ShortcutHandler = (event: ShortcutEvent) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a global shortcut or a list of shortcuts.
|
* Register a global shortcut or a list of shortcuts.
|
||||||
@@ -50,15 +50,15 @@ export type ShortcutHandler = (event: ShortcutEvent) => void;
|
|||||||
*/
|
*/
|
||||||
async function register(
|
async function register(
|
||||||
shortcuts: string | string[],
|
shortcuts: string | string[],
|
||||||
handler: ShortcutHandler,
|
handler: ShortcutHandler
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const h = new Channel<ShortcutEvent>();
|
const h = new Channel<ShortcutEvent>()
|
||||||
h.onmessage = handler;
|
h.onmessage = handler
|
||||||
|
|
||||||
return await invoke("plugin:global-shortcut|register", {
|
return await invoke('plugin:global-shortcut|register', {
|
||||||
shortcuts: Array.isArray(shortcuts) ? shortcuts : [shortcuts],
|
shortcuts: Array.isArray(shortcuts) ? shortcuts : [shortcuts],
|
||||||
handler: h,
|
handler: h
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,9 +80,9 @@ async function register(
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function unregister(shortcuts: string | string[]): Promise<void> {
|
async function unregister(shortcuts: string | string[]): Promise<void> {
|
||||||
return await invoke("plugin:global-shortcut|unregister", {
|
return await invoke('plugin:global-shortcut|unregister', {
|
||||||
shortcuts: Array.isArray(shortcuts) ? shortcuts : [shortcuts],
|
shortcuts: Array.isArray(shortcuts) ? shortcuts : [shortcuts]
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,7 +96,7 @@ async function unregister(shortcuts: string | string[]): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function unregisterAll(): Promise<void> {
|
async function unregisterAll(): Promise<void> {
|
||||||
return await invoke("plugin:global-shortcut|unregister_all", {});
|
return await invoke('plugin:global-shortcut|unregister_all', {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,9 +115,9 @@ async function unregisterAll(): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function isRegistered(shortcut: string): Promise<boolean> {
|
async function isRegistered(shortcut: string): Promise<boolean> {
|
||||||
return await invoke("plugin:global-shortcut|is_registered", {
|
return await invoke('plugin:global-shortcut|is_registered', {
|
||||||
shortcut,
|
shortcut
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export { register, unregister, unregisterAll, isRegistered };
|
export { register, unregister, unregisterAll, isRegistered }
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -68,13 +68,13 @@ import {
|
|||||||
vibrate,
|
vibrate,
|
||||||
impactFeedback,
|
impactFeedback,
|
||||||
notificationFeedback,
|
notificationFeedback,
|
||||||
selectionFeedback,
|
selectionFeedback
|
||||||
} from "@tauri-apps/plugin-haptics";
|
} from '@tauri-apps/plugin-haptics'
|
||||||
|
|
||||||
await vibrate(1);
|
await vibrate(1)
|
||||||
await impactFeedback("medium");
|
await impactFeedback('medium')
|
||||||
await notificationFeedback("warning");
|
await notificationFeedback('warning')
|
||||||
await selectionFeedback();
|
await selectionFeedback()
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -11,54 +11,54 @@ export const commands = {
|
|||||||
async vibrate(duration: number): Promise<Result<null, Error>> {
|
async vibrate(duration: number): Promise<Result<null, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:haptics|vibrate", { duration }),
|
data: await TAURI_INVOKE('plugin:haptics|vibrate', { duration })
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async impactFeedback(
|
async impactFeedback(
|
||||||
style: ImpactFeedbackStyle,
|
style: ImpactFeedbackStyle
|
||||||
): Promise<Result<null, Error>> {
|
): Promise<Result<null, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:haptics|impact_feedback", { style }),
|
data: await TAURI_INVOKE('plugin:haptics|impact_feedback', { style })
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async notificationFeedback(
|
async notificationFeedback(
|
||||||
type: NotificationFeedbackType,
|
type: NotificationFeedbackType
|
||||||
): Promise<Result<null, Error>> {
|
): Promise<Result<null, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:haptics|notification_feedback", {
|
data: await TAURI_INVOKE('plugin:haptics|notification_feedback', {
|
||||||
type,
|
type
|
||||||
}),
|
})
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async selectionFeedback(): Promise<Result<null, Error>> {
|
async selectionFeedback(): Promise<Result<null, Error>> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
data: await TAURI_INVOKE("plugin:haptics|selection_feedback"),
|
data: await TAURI_INVOKE('plugin:haptics|selection_feedback')
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) throw e;
|
if (e instanceof Error) throw e
|
||||||
else return { status: "error", error: e as any };
|
else return { status: 'error', error: e as any }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/** user-defined events **/
|
/** user-defined events **/
|
||||||
|
|
||||||
@@ -72,69 +72,69 @@ export const commands = {
|
|||||||
|
|
||||||
/** user-defined types **/
|
/** user-defined types **/
|
||||||
|
|
||||||
export type Error = never;
|
export type Error = never
|
||||||
export type ImpactFeedbackStyle =
|
export type ImpactFeedbackStyle =
|
||||||
| "light"
|
| 'light'
|
||||||
| "medium"
|
| 'medium'
|
||||||
| "heavy"
|
| 'heavy'
|
||||||
| "soft"
|
| 'soft'
|
||||||
| "rigid";
|
| 'rigid'
|
||||||
export type NotificationFeedbackType = "success" | "warning" | "error";
|
export type NotificationFeedbackType = 'success' | 'warning' | 'error'
|
||||||
//export type RandomNumber = number;
|
//export type RandomNumber = number;
|
||||||
|
|
||||||
/** tauri-specta globals **/
|
/** tauri-specta globals **/
|
||||||
|
|
||||||
import { invoke as TAURI_INVOKE } from "@tauri-apps/api/core";
|
import { invoke as TAURI_INVOKE } from '@tauri-apps/api/core'
|
||||||
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
|
import * as TAURI_API_EVENT from '@tauri-apps/api/event'
|
||||||
import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webviewWindow";
|
import { type WebviewWindow as __WebviewWindow__ } from '@tauri-apps/api/webviewWindow'
|
||||||
|
|
||||||
type __EventObj__<T> = {
|
type __EventObj__<T> = {
|
||||||
listen: (
|
listen: (
|
||||||
cb: TAURI_API_EVENT.EventCallback<T>,
|
cb: TAURI_API_EVENT.EventCallback<T>
|
||||||
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
|
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>
|
||||||
once: (
|
once: (
|
||||||
cb: TAURI_API_EVENT.EventCallback<T>,
|
cb: TAURI_API_EVENT.EventCallback<T>
|
||||||
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
|
) => ReturnType<typeof TAURI_API_EVENT.once<T>>
|
||||||
emit: T extends null
|
emit: T extends null
|
||||||
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
|
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
|
||||||
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
|
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>
|
||||||
};
|
}
|
||||||
|
|
||||||
export type Result<T, E> =
|
export type Result<T, E> =
|
||||||
| { status: "ok"; data: T }
|
| { status: 'ok'; data: T }
|
||||||
| { status: "error"; error: E };
|
| { status: 'error'; error: E }
|
||||||
|
|
||||||
function __makeEvents__<T extends Record<string, any>>(
|
function __makeEvents__<T extends Record<string, any>>(
|
||||||
mappings: Record<keyof T, string>,
|
mappings: Record<keyof T, string>
|
||||||
) {
|
) {
|
||||||
return new Proxy(
|
return new Proxy(
|
||||||
{} as unknown as {
|
{} as unknown as {
|
||||||
[K in keyof T]: __EventObj__<T[K]> & {
|
[K in keyof T]: __EventObj__<T[K]> & {
|
||||||
(handle: __WebviewWindow__): __EventObj__<T[K]>;
|
(handle: __WebviewWindow__): __EventObj__<T[K]>
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
get: (_, event) => {
|
get: (_, event) => {
|
||||||
const name = mappings[event as keyof T];
|
const name = mappings[event as keyof T]
|
||||||
|
|
||||||
return new Proxy((() => {}) as any, {
|
return new Proxy((() => {}) as any, {
|
||||||
apply: (_, __, [window]: [__WebviewWindow__]) => ({
|
apply: (_, __, [window]: [__WebviewWindow__]) => ({
|
||||||
listen: (arg: any) => window.listen(name, arg),
|
listen: (arg: any) => window.listen(name, arg),
|
||||||
once: (arg: any) => window.once(name, arg),
|
once: (arg: any) => window.once(name, arg),
|
||||||
emit: (arg: any) => window.emit(name, arg),
|
emit: (arg: any) => window.emit(name, arg)
|
||||||
}),
|
}),
|
||||||
get: (_, command: keyof __EventObj__<any>) => {
|
get: (_, command: keyof __EventObj__<any>) => {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "listen":
|
case 'listen':
|
||||||
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
|
return (arg: any) => TAURI_API_EVENT.listen(name, arg)
|
||||||
case "once":
|
case 'once':
|
||||||
return (arg: any) => TAURI_API_EVENT.once(name, arg);
|
return (arg: any) => TAURI_API_EVENT.once(name, arg)
|
||||||
case "emit":
|
case 'emit':
|
||||||
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
|
return (arg: any) => TAURI_API_EVENT.emit(name, arg)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,15 @@
|
|||||||
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
|
|
||||||
import { commands } from "./bindings";
|
import { commands } from './bindings'
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
vibrate,
|
vibrate,
|
||||||
impactFeedback,
|
impactFeedback,
|
||||||
notificationFeedback,
|
notificationFeedback,
|
||||||
selectionFeedback,
|
selectionFeedback
|
||||||
} = commands;
|
} = commands
|
||||||
|
|
||||||
export { ImpactFeedbackStyle, NotificationFeedbackType } from "./bindings";
|
export { ImpactFeedbackStyle, NotificationFeedbackType } from './bindings'
|
||||||
|
|
||||||
// export { events };
|
// export { events };
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -60,11 +60,11 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { fetch } from "@tauri-apps/plugin-http";
|
import { fetch } from '@tauri-apps/plugin-http'
|
||||||
const response = await fetch("http://localhost:3003/users/2", {
|
const response = await fetch('http://localhost:3003/users/2', {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
timeout: 30,
|
timeout: 30
|
||||||
});
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration of a proxy that a Client should pass requests to.
|
* Configuration of a proxy that a Client should pass requests to.
|
||||||
@@ -37,34 +37,34 @@ export interface Proxy {
|
|||||||
/**
|
/**
|
||||||
* Proxy all traffic to the passed URL.
|
* Proxy all traffic to the passed URL.
|
||||||
*/
|
*/
|
||||||
all?: string | ProxyConfig;
|
all?: string | ProxyConfig
|
||||||
/**
|
/**
|
||||||
* Proxy all HTTP traffic to the passed URL.
|
* Proxy all HTTP traffic to the passed URL.
|
||||||
*/
|
*/
|
||||||
http?: string | ProxyConfig;
|
http?: string | ProxyConfig
|
||||||
/**
|
/**
|
||||||
* Proxy all HTTPS traffic to the passed URL.
|
* Proxy all HTTPS traffic to the passed URL.
|
||||||
*/
|
*/
|
||||||
https?: string | ProxyConfig;
|
https?: string | ProxyConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProxyConfig {
|
export interface ProxyConfig {
|
||||||
/**
|
/**
|
||||||
* The URL of the proxy server.
|
* The URL of the proxy server.
|
||||||
*/
|
*/
|
||||||
url: string;
|
url: string
|
||||||
/**
|
/**
|
||||||
* Set the `Proxy-Authorization` header using Basic auth.
|
* Set the `Proxy-Authorization` header using Basic auth.
|
||||||
*/
|
*/
|
||||||
basicAuth?: {
|
basicAuth?: {
|
||||||
username: string;
|
username: string
|
||||||
password: string;
|
password: string
|
||||||
};
|
}
|
||||||
/**
|
/**
|
||||||
* A configuration for filtering out requests that shouldn't be proxied.
|
* A configuration for filtering out requests that shouldn't be proxied.
|
||||||
* Entries are expected to be comma-separated (whitespace between entries is ignored)
|
* Entries are expected to be comma-separated (whitespace between entries is ignored)
|
||||||
*/
|
*/
|
||||||
noProxy?: string;
|
noProxy?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,16 +77,16 @@ export interface ClientOptions {
|
|||||||
* Defines the maximum number of redirects the client should follow.
|
* Defines the maximum number of redirects the client should follow.
|
||||||
* If set to 0, no redirects will be followed.
|
* If set to 0, no redirects will be followed.
|
||||||
*/
|
*/
|
||||||
maxRedirections?: number;
|
maxRedirections?: number
|
||||||
/** Timeout in milliseconds */
|
/** Timeout in milliseconds */
|
||||||
connectTimeout?: number;
|
connectTimeout?: number
|
||||||
/**
|
/**
|
||||||
* Configuration of a proxy that a Client should pass requests to.
|
* Configuration of a proxy that a Client should pass requests to.
|
||||||
*/
|
*/
|
||||||
proxy?: Proxy;
|
proxy?: Proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
const ERROR_REQUEST_CANCELLED = "Request canceled";
|
const ERROR_REQUEST_CANCELLED = 'Request canceled'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a resource from the network. It returns a `Promise` that resolves to the
|
* Fetch a resource from the network. It returns a `Promise` that resolves to the
|
||||||
@@ -104,41 +104,41 @@ const ERROR_REQUEST_CANCELLED = "Request canceled";
|
|||||||
*/
|
*/
|
||||||
export async function fetch(
|
export async function fetch(
|
||||||
input: URL | Request | string,
|
input: URL | Request | string,
|
||||||
init?: RequestInit & ClientOptions,
|
init?: RequestInit & ClientOptions
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
// abort early here if needed
|
// abort early here if needed
|
||||||
const signal = init?.signal;
|
const signal = init?.signal
|
||||||
if (signal?.aborted) {
|
if (signal?.aborted) {
|
||||||
throw new Error(ERROR_REQUEST_CANCELLED);
|
throw new Error(ERROR_REQUEST_CANCELLED)
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxRedirections = init?.maxRedirections;
|
const maxRedirections = init?.maxRedirections
|
||||||
const connectTimeout = init?.connectTimeout;
|
const connectTimeout = init?.connectTimeout
|
||||||
const proxy = init?.proxy;
|
const proxy = init?.proxy
|
||||||
|
|
||||||
// Remove these fields before creating the request
|
// Remove these fields before creating the request
|
||||||
if (init) {
|
if (init) {
|
||||||
delete init.maxRedirections;
|
delete init.maxRedirections
|
||||||
delete init.connectTimeout;
|
delete init.connectTimeout
|
||||||
delete init.proxy;
|
delete init.proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = init?.headers
|
const headers = init?.headers
|
||||||
? init.headers instanceof Headers
|
? init.headers instanceof Headers
|
||||||
? init.headers
|
? init.headers
|
||||||
: new Headers(init.headers)
|
: new Headers(init.headers)
|
||||||
: new Headers();
|
: new Headers()
|
||||||
|
|
||||||
const req = new Request(input, init);
|
const req = new Request(input, init)
|
||||||
const buffer = await req.arrayBuffer();
|
const buffer = await req.arrayBuffer()
|
||||||
const data =
|
const data =
|
||||||
buffer.byteLength !== 0 ? Array.from(new Uint8Array(buffer)) : null;
|
buffer.byteLength !== 0 ? Array.from(new Uint8Array(buffer)) : null
|
||||||
|
|
||||||
// append new headers created by the browser `Request` implementation,
|
// append new headers created by the browser `Request` implementation,
|
||||||
// if not already declared by the caller of this function
|
// if not already declared by the caller of this function
|
||||||
for (const [key, value] of req.headers) {
|
for (const [key, value] of req.headers) {
|
||||||
if (!headers.get(key)) {
|
if (!headers.get(key)) {
|
||||||
headers.set(key, value);
|
headers.set(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ export async function fetch(
|
|||||||
? Array.from(headers.entries())
|
? Array.from(headers.entries())
|
||||||
: Array.isArray(headers)
|
: Array.isArray(headers)
|
||||||
? headers
|
? headers
|
||||||
: Object.entries(headers);
|
: Object.entries(headers)
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
const mappedHeaders: Array<[string, string]> = headersArray.map(
|
const mappedHeaders: Array<[string, string]> = headersArray.map(
|
||||||
@@ -155,16 +155,16 @@ export async function fetch(
|
|||||||
name,
|
name,
|
||||||
// we need to ensure we have all header values as strings
|
// we need to ensure we have all header values as strings
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
typeof val === "string" ? val : (val as any).toString(),
|
typeof val === 'string' ? val : (val as any).toString()
|
||||||
],
|
]
|
||||||
);
|
)
|
||||||
|
|
||||||
// abort early here if needed
|
// abort early here if needed
|
||||||
if (signal?.aborted) {
|
if (signal?.aborted) {
|
||||||
throw new Error(ERROR_REQUEST_CANCELLED);
|
throw new Error(ERROR_REQUEST_CANCELLED)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rid = await invoke<number>("plugin:http|fetch", {
|
const rid = await invoke<number>('plugin:http|fetch', {
|
||||||
clientConfig: {
|
clientConfig: {
|
||||||
method: req.method,
|
method: req.method,
|
||||||
url: req.url,
|
url: req.url,
|
||||||
@@ -172,28 +172,28 @@ export async function fetch(
|
|||||||
data,
|
data,
|
||||||
maxRedirections,
|
maxRedirections,
|
||||||
connectTimeout,
|
connectTimeout,
|
||||||
proxy,
|
proxy
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const abort = () => invoke("plugin:http|fetch_cancel", { rid });
|
const abort = () => invoke('plugin:http|fetch_cancel', { rid })
|
||||||
|
|
||||||
// abort early here if needed
|
// abort early here if needed
|
||||||
if (signal?.aborted) {
|
if (signal?.aborted) {
|
||||||
// we don't care about the result of this proimse
|
// we don't care about the result of this proimse
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
abort();
|
abort()
|
||||||
throw new Error(ERROR_REQUEST_CANCELLED);
|
throw new Error(ERROR_REQUEST_CANCELLED)
|
||||||
}
|
}
|
||||||
|
|
||||||
signal?.addEventListener("abort", () => void abort());
|
signal?.addEventListener('abort', () => void abort())
|
||||||
|
|
||||||
interface FetchSendResponse {
|
interface FetchSendResponse {
|
||||||
status: number;
|
status: number
|
||||||
statusText: string;
|
statusText: string
|
||||||
headers: [[string, string]];
|
headers: [[string, string]]
|
||||||
url: string;
|
url: string
|
||||||
rid: number;
|
rid: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -201,17 +201,17 @@ export async function fetch(
|
|||||||
statusText,
|
statusText,
|
||||||
url,
|
url,
|
||||||
headers: responseHeaders,
|
headers: responseHeaders,
|
||||||
rid: responseRid,
|
rid: responseRid
|
||||||
} = await invoke<FetchSendResponse>("plugin:http|fetch_send", {
|
} = await invoke<FetchSendResponse>('plugin:http|fetch_send', {
|
||||||
rid,
|
rid
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await invoke<ArrayBuffer | number[]>(
|
const body = await invoke<ArrayBuffer | number[]>(
|
||||||
"plugin:http|fetch_read_body",
|
'plugin:http|fetch_read_body',
|
||||||
{
|
{
|
||||||
rid: responseRid,
|
rid: responseRid
|
||||||
},
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
const res = new Response(
|
const res = new Response(
|
||||||
body instanceof ArrayBuffer && body.byteLength !== 0
|
body instanceof ArrayBuffer && body.byteLength !== 0
|
||||||
@@ -221,9 +221,9 @@ export async function fetch(
|
|||||||
: null,
|
: null,
|
||||||
{
|
{
|
||||||
status,
|
status,
|
||||||
statusText,
|
statusText
|
||||||
},
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
// url and headers are read only properties
|
// url and headers are read only properties
|
||||||
// but seems like we can set them like this
|
// but seems like we can set them like this
|
||||||
@@ -231,10 +231,10 @@ export async function fetch(
|
|||||||
// we define theme like this, because using `Response`
|
// we define theme like this, because using `Response`
|
||||||
// constructor, it removes url and some headers
|
// constructor, it removes url and some headers
|
||||||
// like `set-cookie` headers
|
// like `set-cookie` headers
|
||||||
Object.defineProperty(res, "url", { value: url });
|
Object.defineProperty(res, 'url', { value: url })
|
||||||
Object.defineProperty(res, "headers", {
|
Object.defineProperty(res, 'headers', {
|
||||||
value: new Headers(responseHeaders),
|
value: new Headers(responseHeaders)
|
||||||
});
|
})
|
||||||
|
|
||||||
return res;
|
return res
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
/.tauri
|
|
||||||
@@ -68,17 +68,17 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { trace, info, error, attachConsole } from "@tauri-apps/plugin-log";
|
import { trace, info, error, attachConsole } from '@tauri-apps/plugin-log'
|
||||||
|
|
||||||
// with TargetKind::Webview enabled this function will print logs to the browser console
|
// with TargetKind::Webview enabled this function will print logs to the browser console
|
||||||
const detach = await attachConsole();
|
const detach = await attachConsole()
|
||||||
|
|
||||||
trace("Trace");
|
trace('Trace')
|
||||||
info("Info");
|
info('Info')
|
||||||
error("Error");
|
error('Error')
|
||||||
|
|
||||||
// detach the browser console from the log stream
|
// detach the browser console from the log stream
|
||||||
detach();
|
detach()
|
||||||
```
|
```
|
||||||
|
|
||||||
To log from rust code, add the log crate to your `Cargo.toml`:
|
To log from rust code, add the log crate to your `Cargo.toml`:
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ One possible threat you need to consider when using this plugin is that secrets
|
|||||||
in logs can theoretically be leaked when the application's frontend gets compromised.
|
in logs can theoretically be leaked when the application's frontend gets compromised.
|
||||||
|
|
||||||
For this threat to be possible all of the following requirements need to be fulfilled:
|
For this threat to be possible all of the following requirements need to be fulfilled:
|
||||||
|
|
||||||
- `TargetKind::Webview` enabled OR secrets stem from frontend logs
|
- `TargetKind::Webview` enabled OR secrets stem from frontend logs
|
||||||
- Frontend application is compromised via something like XSS (cross-site-scripting) OR logs are directly exposed
|
- Frontend application is compromised via something like XSS (cross-site-scripting) OR logs are directly exposed
|
||||||
- Logs contain secrets or sensitive information
|
- Logs contain secrets or sensitive information
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { listen, type UnlistenFn, type Event } from "@tauri-apps/api/event";
|
import { listen, type UnlistenFn, type Event } from '@tauri-apps/api/event'
|
||||||
|
|
||||||
export interface LogOptions {
|
export interface LogOptions {
|
||||||
file?: string;
|
file?: string
|
||||||
line?: number;
|
line?: number
|
||||||
keyValues?: Record<string, string | undefined>;
|
keyValues?: Record<string, string | undefined>
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
@@ -41,35 +41,35 @@ enum LogLevel {
|
|||||||
*
|
*
|
||||||
* Designates very serious errors.
|
* Designates very serious errors.
|
||||||
*/
|
*/
|
||||||
Error,
|
Error
|
||||||
}
|
}
|
||||||
|
|
||||||
async function log(
|
async function log(
|
||||||
level: LogLevel,
|
level: LogLevel,
|
||||||
message: string,
|
message: string,
|
||||||
options?: LogOptions,
|
options?: LogOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const traces = new Error().stack?.split("\n").map((line) => line.split("@"));
|
const traces = new Error().stack?.split('\n').map((line) => line.split('@'))
|
||||||
|
|
||||||
const filtered = traces?.filter(([name, location]) => {
|
const filtered = traces?.filter(([name, location]) => {
|
||||||
return name.length > 0 && location !== "[native code]";
|
return name.length > 0 && location !== '[native code]'
|
||||||
});
|
})
|
||||||
|
|
||||||
const { file, line, keyValues } = options ?? {};
|
const { file, line, keyValues } = options ?? {}
|
||||||
|
|
||||||
let location = filtered?.[0]?.filter((v) => v.length > 0).join("@");
|
let location = filtered?.[0]?.filter((v) => v.length > 0).join('@')
|
||||||
if (location === "Error") {
|
if (location === 'Error') {
|
||||||
location = "webview::unknown";
|
location = 'webview::unknown'
|
||||||
}
|
}
|
||||||
|
|
||||||
await invoke("plugin:log|log", {
|
await invoke('plugin:log|log', {
|
||||||
level,
|
level,
|
||||||
message,
|
message,
|
||||||
location,
|
location,
|
||||||
file,
|
file,
|
||||||
line,
|
line,
|
||||||
keyValues,
|
keyValues
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,9 +90,9 @@ async function log(
|
|||||||
*/
|
*/
|
||||||
export async function error(
|
export async function error(
|
||||||
message: string,
|
message: string,
|
||||||
options?: LogOptions,
|
options?: LogOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await log(LogLevel.Error, message, options);
|
await log(LogLevel.Error, message, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,9 +112,9 @@ export async function error(
|
|||||||
*/
|
*/
|
||||||
export async function warn(
|
export async function warn(
|
||||||
message: string,
|
message: string,
|
||||||
options?: LogOptions,
|
options?: LogOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await log(LogLevel.Warn, message, options);
|
await log(LogLevel.Warn, message, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,9 +134,9 @@ export async function warn(
|
|||||||
*/
|
*/
|
||||||
export async function info(
|
export async function info(
|
||||||
message: string,
|
message: string,
|
||||||
options?: LogOptions,
|
options?: LogOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await log(LogLevel.Info, message, options);
|
await log(LogLevel.Info, message, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,9 +156,9 @@ export async function info(
|
|||||||
*/
|
*/
|
||||||
export async function debug(
|
export async function debug(
|
||||||
message: string,
|
message: string,
|
||||||
options?: LogOptions,
|
options?: LogOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await log(LogLevel.Debug, message, options);
|
await log(LogLevel.Debug, message, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,17 +178,17 @@ export async function debug(
|
|||||||
*/
|
*/
|
||||||
export async function trace(
|
export async function trace(
|
||||||
message: string,
|
message: string,
|
||||||
options?: LogOptions,
|
options?: LogOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await log(LogLevel.Trace, message, options);
|
await log(LogLevel.Trace, message, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RecordPayload {
|
interface RecordPayload {
|
||||||
level: LogLevel;
|
level: LogLevel
|
||||||
message: string;
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoggerFn = (fn: RecordPayload) => void;
|
type LoggerFn = (fn: RecordPayload) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a listener for the log, and calls the passed function for each log entry.
|
* Attaches a listener for the log, and calls the passed function for each log entry.
|
||||||
@@ -197,19 +197,19 @@ type LoggerFn = (fn: RecordPayload) => void;
|
|||||||
* @returns a function to cancel the listener.
|
* @returns a function to cancel the listener.
|
||||||
*/
|
*/
|
||||||
export async function attachLogger(fn: LoggerFn): Promise<UnlistenFn> {
|
export async function attachLogger(fn: LoggerFn): Promise<UnlistenFn> {
|
||||||
return await listen("log://log", (event: Event<RecordPayload>) => {
|
return await listen('log://log', (event: Event<RecordPayload>) => {
|
||||||
const { level } = event.payload;
|
const { level } = event.payload
|
||||||
let { message } = event.payload;
|
let { message } = event.payload
|
||||||
|
|
||||||
// Strip ANSI escape codes
|
// Strip ANSI escape codes
|
||||||
message = message.replace(
|
message = message.replace(
|
||||||
// TODO: Investigate security/detect-unsafe-regex
|
// TODO: Investigate security/detect-unsafe-regex
|
||||||
// eslint-disable-next-line no-control-regex, security/detect-unsafe-regex
|
// eslint-disable-next-line no-control-regex, security/detect-unsafe-regex
|
||||||
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
||||||
"",
|
''
|
||||||
);
|
)
|
||||||
fn({ message, level });
|
fn({ message, level })
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -221,23 +221,23 @@ export async function attachConsole(): Promise<UnlistenFn> {
|
|||||||
return await attachLogger(({ level, message }: RecordPayload) => {
|
return await attachLogger(({ level, message }: RecordPayload) => {
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case LogLevel.Trace:
|
case LogLevel.Trace:
|
||||||
console.log(message);
|
console.log(message)
|
||||||
break;
|
break
|
||||||
case LogLevel.Debug:
|
case LogLevel.Debug:
|
||||||
console.debug(message);
|
console.debug(message)
|
||||||
break;
|
break
|
||||||
case LogLevel.Info:
|
case LogLevel.Info:
|
||||||
console.info(message);
|
console.info(message)
|
||||||
break;
|
break
|
||||||
case LogLevel.Warn:
|
case LogLevel.Warn:
|
||||||
console.warn(message);
|
console.warn(message)
|
||||||
break;
|
break
|
||||||
case LogLevel.Error:
|
case LogLevel.Error:
|
||||||
console.error(message);
|
console.error(message)
|
||||||
break;
|
break
|
||||||
default:
|
default:
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||||
throw new Error(`unknown log level ${level}`);
|
throw new Error(`unknown log level ${level}`)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -62,9 +62,9 @@ fn main() {
|
|||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { scan, textRecord, write } from "@tauri-apps/plugin-nfc";
|
import { scan, textRecord, write } from '@tauri-apps/plugin-nfc'
|
||||||
await scan({ type: "tag", keepSessionAlive: true });
|
await scan({ type: 'tag', keepSessionAlive: true })
|
||||||
await write([textRecord("Tauri is awesome!")]);
|
await write([textRecord('Tauri is awesome!')])
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
+105
-107
@@ -2,15 +2,15 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export const RTD_TEXT = [0x54]; // "T"
|
export const RTD_TEXT = [0x54] // "T"
|
||||||
export const RTD_URI = [0x55]; // "U"
|
export const RTD_URI = [0x55] // "U"
|
||||||
|
|
||||||
export interface UriFilter {
|
export interface UriFilter {
|
||||||
scheme?: string;
|
scheme?: string
|
||||||
host?: string;
|
host?: string
|
||||||
pathPrefix?: string;
|
pathPrefix?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TechKind {
|
export enum TechKind {
|
||||||
@@ -23,19 +23,19 @@ export enum TechKind {
|
|||||||
NfcB,
|
NfcB,
|
||||||
NfcBarcode,
|
NfcBarcode,
|
||||||
NfcF,
|
NfcF,
|
||||||
NfcV,
|
NfcV
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ScanKind =
|
export type ScanKind =
|
||||||
| {
|
| {
|
||||||
type: "tag";
|
type: 'tag'
|
||||||
uri?: UriFilter;
|
uri?: UriFilter
|
||||||
mimeType?: string;
|
mimeType?: string
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: "ndef";
|
type: 'ndef'
|
||||||
uri?: UriFilter;
|
uri?: UriFilter
|
||||||
mimeType?: string;
|
mimeType?: string
|
||||||
/**
|
/**
|
||||||
* Each of the tech-lists is considered independently and the activity is considered a match if
|
* Each of the tech-lists is considered independently and the activity is considered a match if
|
||||||
* any single tech-list matches the tag that was discovered.
|
* any single tech-list matches the tag that was discovered.
|
||||||
@@ -56,25 +56,25 @@ export type ScanKind =
|
|||||||
* ]
|
* ]
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
techLists?: TechKind[][];
|
techLists?: TechKind[][]
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface ScanOptions {
|
export interface ScanOptions {
|
||||||
keepSessionAlive?: boolean;
|
keepSessionAlive?: boolean
|
||||||
/** Message displayed in the UI. iOS only. */
|
/** Message displayed in the UI. iOS only. */
|
||||||
message?: string;
|
message?: string
|
||||||
/** Message displayed in the UI when the message has been read. iOS only. */
|
/** Message displayed in the UI when the message has been read. iOS only. */
|
||||||
successMessage?: string;
|
successMessage?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WriteOptions {
|
export interface WriteOptions {
|
||||||
kind?: ScanKind;
|
kind?: ScanKind
|
||||||
/** Message displayed in the UI when reading the tag. iOS only. */
|
/** Message displayed in the UI when reading the tag. iOS only. */
|
||||||
message?: string;
|
message?: string
|
||||||
/** Message displayed in the UI when the tag has been read. iOS only. */
|
/** Message displayed in the UI when the tag has been read. iOS only. */
|
||||||
successfulReadMessage?: string;
|
successfulReadMessage?: string
|
||||||
/** Message displayed in the UI when the message has been written. iOS only. */
|
/** Message displayed in the UI when the message has been written. iOS only. */
|
||||||
successMessage?: string;
|
successMessage?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NFCTypeNameFormat {
|
export enum NFCTypeNameFormat {
|
||||||
@@ -84,122 +84,120 @@ export enum NFCTypeNameFormat {
|
|||||||
AbsoluteURI = 3,
|
AbsoluteURI = 3,
|
||||||
NfcExternal = 4,
|
NfcExternal = 4,
|
||||||
Unknown = 5,
|
Unknown = 5,
|
||||||
Unchanged = 6,
|
Unchanged = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TagRecord {
|
export interface TagRecord {
|
||||||
tnf: NFCTypeNameFormat;
|
tnf: NFCTypeNameFormat
|
||||||
kind: number[];
|
kind: number[]
|
||||||
id: number[];
|
id: number[]
|
||||||
payload: number[];
|
payload: number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Tag {
|
export interface Tag {
|
||||||
id: number[];
|
id: number[]
|
||||||
kind: string[];
|
kind: string[]
|
||||||
records: TagRecord[];
|
records: TagRecord[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NFCRecord {
|
export interface NFCRecord {
|
||||||
format: NFCTypeNameFormat;
|
format: NFCTypeNameFormat
|
||||||
kind: number[];
|
kind: number[]
|
||||||
id: number[];
|
id: number[]
|
||||||
payload: number[];
|
payload: number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function record(
|
export function record(
|
||||||
format: NFCTypeNameFormat,
|
format: NFCTypeNameFormat,
|
||||||
kind: string | number[],
|
kind: string | number[],
|
||||||
id: string | number[],
|
id: string | number[],
|
||||||
payload: string | number[],
|
payload: string | number[]
|
||||||
): NFCRecord {
|
): NFCRecord {
|
||||||
return {
|
return {
|
||||||
format,
|
format,
|
||||||
kind:
|
kind:
|
||||||
typeof kind === "string"
|
typeof kind === 'string'
|
||||||
? Array.from(new TextEncoder().encode(kind))
|
? Array.from(new TextEncoder().encode(kind))
|
||||||
: kind,
|
: kind,
|
||||||
id: typeof id === "string" ? Array.from(new TextEncoder().encode(id)) : id,
|
id: typeof id === 'string' ? Array.from(new TextEncoder().encode(id)) : id,
|
||||||
payload:
|
payload:
|
||||||
typeof payload === "string"
|
typeof payload === 'string'
|
||||||
? Array.from(new TextEncoder().encode(payload))
|
? Array.from(new TextEncoder().encode(payload))
|
||||||
: payload,
|
: payload
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function textRecord(
|
export function textRecord(
|
||||||
text: string,
|
text: string,
|
||||||
id?: string | number[],
|
id?: string | number[],
|
||||||
language: string = "en",
|
language: string = 'en'
|
||||||
): NFCRecord {
|
): NFCRecord {
|
||||||
const payload = Array.from(new TextEncoder().encode(language + text));
|
const payload = Array.from(new TextEncoder().encode(language + text))
|
||||||
payload.unshift(language.length);
|
payload.unshift(language.length)
|
||||||
return record(NFCTypeNameFormat.NfcWellKnown, RTD_TEXT, id ?? [], payload);
|
return record(NFCTypeNameFormat.NfcWellKnown, RTD_TEXT, id ?? [], payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
const protocols = [
|
const protocols = [
|
||||||
"",
|
'',
|
||||||
"http://www.",
|
'http://www.',
|
||||||
"https://www.",
|
'https://www.',
|
||||||
"http://",
|
'http://',
|
||||||
"https://",
|
'https://',
|
||||||
"tel:",
|
'tel:',
|
||||||
"mailto:",
|
'mailto:',
|
||||||
"ftp://anonymous:anonymous@",
|
'ftp://anonymous:anonymous@',
|
||||||
"ftp://ftp.",
|
'ftp://ftp.',
|
||||||
"ftps://",
|
'ftps://',
|
||||||
"sftp://",
|
'sftp://',
|
||||||
"smb://",
|
'smb://',
|
||||||
"nfs://",
|
'nfs://',
|
||||||
"ftp://",
|
'ftp://',
|
||||||
"dav://",
|
'dav://',
|
||||||
"news:",
|
'news:',
|
||||||
"telnet://",
|
'telnet://',
|
||||||
"imap:",
|
'imap:',
|
||||||
"rtsp://",
|
'rtsp://',
|
||||||
"urn:",
|
'urn:',
|
||||||
"pop:",
|
'pop:',
|
||||||
"sip:",
|
'sip:',
|
||||||
"sips:",
|
'sips:',
|
||||||
"tftp:",
|
'tftp:',
|
||||||
"btspp://",
|
'btspp://',
|
||||||
"btl2cap://",
|
'btl2cap://',
|
||||||
"btgoep://",
|
'btgoep://',
|
||||||
"tcpobex://",
|
'tcpobex://',
|
||||||
"irdaobex://",
|
'irdaobex://',
|
||||||
"file://",
|
'file://',
|
||||||
"urn:epc:id:",
|
'urn:epc:id:',
|
||||||
"urn:epc:tag:",
|
'urn:epc:tag:',
|
||||||
"urn:epc:pat:",
|
'urn:epc:pat:',
|
||||||
"urn:epc:raw:",
|
'urn:epc:raw:',
|
||||||
"urn:epc:",
|
'urn:epc:',
|
||||||
"urn:nfc:",
|
'urn:nfc:'
|
||||||
];
|
]
|
||||||
|
|
||||||
function encodeURI(uri: string): number[] {
|
function encodeURI(uri: string): number[] {
|
||||||
let prefix = "";
|
let prefix = ''
|
||||||
|
|
||||||
protocols.slice(1).forEach(function (protocol) {
|
protocols.slice(1).forEach(function (protocol) {
|
||||||
if (
|
if (
|
||||||
(prefix.length === 0 || prefix === "urn:") &&
|
(prefix.length === 0 || prefix === 'urn:') &&
|
||||||
uri.indexOf(protocol) === 0
|
uri.indexOf(protocol) === 0
|
||||||
) {
|
) {
|
||||||
prefix = protocol;
|
prefix = protocol
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
if (prefix.length === 0) {
|
if (prefix.length === 0) {
|
||||||
prefix = "";
|
prefix = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const encoded = Array.from(
|
const encoded = Array.from(new TextEncoder().encode(uri.slice(prefix.length)))
|
||||||
new TextEncoder().encode(uri.slice(prefix.length)),
|
const protocolCode = protocols.indexOf(prefix)
|
||||||
);
|
|
||||||
const protocolCode = protocols.indexOf(prefix);
|
|
||||||
// prepend protocol code
|
// prepend protocol code
|
||||||
encoded.unshift(protocolCode);
|
encoded.unshift(protocolCode)
|
||||||
|
|
||||||
return encoded;
|
return encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
export function uriRecord(uri: string, id?: string | number[]): NFCRecord {
|
export function uriRecord(uri: string, id?: string | number[]): NFCRecord {
|
||||||
@@ -207,13 +205,13 @@ export function uriRecord(uri: string, id?: string | number[]): NFCRecord {
|
|||||||
NFCTypeNameFormat.NfcWellKnown,
|
NFCTypeNameFormat.NfcWellKnown,
|
||||||
RTD_URI,
|
RTD_URI,
|
||||||
id ?? [],
|
id ?? [],
|
||||||
encodeURI(uri),
|
encodeURI(uri)
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapScanKind(kind: ScanKind): Record<string, unknown> {
|
function mapScanKind(kind: ScanKind): Record<string, unknown> {
|
||||||
const { type: scanKind, ...kindOptions } = kind;
|
const { type: scanKind, ...kindOptions } = kind
|
||||||
return { [scanKind]: kindOptions };
|
return { [scanKind]: kindOptions }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,12 +230,12 @@ function mapScanKind(kind: ScanKind): Record<string, unknown> {
|
|||||||
*/
|
*/
|
||||||
export async function scan(
|
export async function scan(
|
||||||
kind: ScanKind,
|
kind: ScanKind,
|
||||||
options?: ScanOptions,
|
options?: ScanOptions
|
||||||
): Promise<Tag> {
|
): Promise<Tag> {
|
||||||
return await invoke("plugin:nfc|scan", {
|
return await invoke('plugin:nfc|scan', {
|
||||||
kind: mapScanKind(kind),
|
kind: mapScanKind(kind),
|
||||||
...options,
|
...options
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -257,19 +255,19 @@ export async function scan(
|
|||||||
*/
|
*/
|
||||||
export async function write(
|
export async function write(
|
||||||
records: NFCRecord[],
|
records: NFCRecord[],
|
||||||
options?: WriteOptions,
|
options?: WriteOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { kind, ...opts } = options ?? {};
|
const { kind, ...opts } = options ?? {}
|
||||||
if (kind) {
|
if (kind) {
|
||||||
// @ts-expect-error map the property
|
// @ts-expect-error map the property
|
||||||
opts.kind = mapScanKind(kind);
|
opts.kind = mapScanKind(kind)
|
||||||
}
|
}
|
||||||
await invoke("plugin:nfc|write", {
|
await invoke('plugin:nfc|write', {
|
||||||
records,
|
records,
|
||||||
...opts,
|
...opts
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isAvailable(): Promise<boolean> {
|
export async function isAvailable(): Promise<boolean> {
|
||||||
return await invoke("plugin:nfc|is_available");
|
return await invoke('plugin:nfc|is_available')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,4 @@ and scanning nearby tags is allowed.
|
|||||||
Writing to tags needs to be manually enabled.
|
Writing to tags needs to be manually enabled.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
permissions = [
|
permissions = ["allow-is-available", "allow-scan"]
|
||||||
"allow-is-available",
|
|
||||||
"allow-scan",
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createConfig } from "../../shared/rollup.config.js";
|
import { createConfig } from '../../shared/rollup.config.js'
|
||||||
|
|
||||||
export default createConfig();
|
export default createConfig()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/.tauri
|
|
||||||
@@ -72,24 +72,27 @@ Then you need to add the permissions to your capabilities file:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/plugin-notification';
|
import {
|
||||||
|
isPermissionGranted,
|
||||||
|
requestPermission,
|
||||||
|
sendNotification
|
||||||
|
} from '@tauri-apps/plugin-notification'
|
||||||
|
|
||||||
async function checkPermission() {
|
async function checkPermission() {
|
||||||
if (!(await isPermissionGranted())) {
|
if (!(await isPermissionGranted())) {
|
||||||
return (await requestPermission()) === 'granted';
|
return (await requestPermission()) === 'granted'
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function enqueueNotification(title, body) {
|
export async function enqueueNotification(title, body) {
|
||||||
if (!(await checkPermission())) {
|
if (!(await checkPermission())) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
sendNotification({ title, body });
|
sendNotification({ title, body })
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,10 @@
|
|||||||
import {
|
import {
|
||||||
invoke,
|
invoke,
|
||||||
type PluginListener,
|
type PluginListener,
|
||||||
addPluginListener,
|
addPluginListener
|
||||||
} from "@tauri-apps/api/core";
|
} from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export type { PermissionState } from "@tauri-apps/api/core";
|
export type { PermissionState } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options to send a notification.
|
* Options to send a notification.
|
||||||
@@ -26,54 +26,54 @@ interface Options {
|
|||||||
/**
|
/**
|
||||||
* The notification identifier to reference this object later. Must be a 32-bit integer.
|
* The notification identifier to reference this object later. Must be a 32-bit integer.
|
||||||
*/
|
*/
|
||||||
id?: number;
|
id?: number
|
||||||
/**
|
/**
|
||||||
* Identifier of the {@link Channel} that deliveres this notification.
|
* Identifier of the {@link Channel} that deliveres this notification.
|
||||||
*
|
*
|
||||||
* If the channel does not exist, the notification won't fire.
|
* If the channel does not exist, the notification won't fire.
|
||||||
* Make sure the channel exists with {@link listChannels} and {@link createChannel}.
|
* Make sure the channel exists with {@link listChannels} and {@link createChannel}.
|
||||||
*/
|
*/
|
||||||
channelId?: string;
|
channelId?: string
|
||||||
/**
|
/**
|
||||||
* Notification title.
|
* Notification title.
|
||||||
*/
|
*/
|
||||||
title: string;
|
title: string
|
||||||
/**
|
/**
|
||||||
* Optional notification body.
|
* Optional notification body.
|
||||||
* */
|
* */
|
||||||
body?: string;
|
body?: string
|
||||||
/**
|
/**
|
||||||
* Schedule this notification to fire on a later time or a fixed interval.
|
* Schedule this notification to fire on a later time or a fixed interval.
|
||||||
*/
|
*/
|
||||||
schedule?: Schedule;
|
schedule?: Schedule
|
||||||
/**
|
/**
|
||||||
* Multiline text.
|
* Multiline text.
|
||||||
* Changes the notification style to big text.
|
* Changes the notification style to big text.
|
||||||
* Cannot be used with `inboxLines`.
|
* Cannot be used with `inboxLines`.
|
||||||
*/
|
*/
|
||||||
largeBody?: string;
|
largeBody?: string
|
||||||
/**
|
/**
|
||||||
* Detail text for the notification with `largeBody`, `inboxLines` or `groupSummary`.
|
* Detail text for the notification with `largeBody`, `inboxLines` or `groupSummary`.
|
||||||
*/
|
*/
|
||||||
summary?: string;
|
summary?: string
|
||||||
/**
|
/**
|
||||||
* Defines an action type for this notification.
|
* Defines an action type for this notification.
|
||||||
*/
|
*/
|
||||||
actionTypeId?: string;
|
actionTypeId?: string
|
||||||
/**
|
/**
|
||||||
* Identifier used to group multiple notifications.
|
* Identifier used to group multiple notifications.
|
||||||
*
|
*
|
||||||
* https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier
|
* https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier
|
||||||
*/
|
*/
|
||||||
group?: string;
|
group?: string
|
||||||
/**
|
/**
|
||||||
* Instructs the system that this notification is the summary of a group on Android.
|
* Instructs the system that this notification is the summary of a group on Android.
|
||||||
*/
|
*/
|
||||||
groupSummary?: boolean;
|
groupSummary?: boolean
|
||||||
/**
|
/**
|
||||||
* The sound resource name. Only available on mobile.
|
* The sound resource name. Only available on mobile.
|
||||||
*/
|
*/
|
||||||
sound?: string;
|
sound?: string
|
||||||
/**
|
/**
|
||||||
* List of lines to add to the notification.
|
* List of lines to add to the notification.
|
||||||
* Changes the notification style to inbox.
|
* Changes the notification style to inbox.
|
||||||
@@ -81,31 +81,31 @@ interface Options {
|
|||||||
*
|
*
|
||||||
* Only supports up to 5 lines.
|
* Only supports up to 5 lines.
|
||||||
*/
|
*/
|
||||||
inboxLines?: string[];
|
inboxLines?: string[]
|
||||||
/**
|
/**
|
||||||
* Notification icon.
|
* Notification icon.
|
||||||
*
|
*
|
||||||
* On Android the icon must be placed in the app's `res/drawable` folder.
|
* On Android the icon must be placed in the app's `res/drawable` folder.
|
||||||
*/
|
*/
|
||||||
icon?: string;
|
icon?: string
|
||||||
/**
|
/**
|
||||||
* Notification large icon (Android).
|
* Notification large icon (Android).
|
||||||
*
|
*
|
||||||
* The icon must be placed in the app's `res/drawable` folder.
|
* The icon must be placed in the app's `res/drawable` folder.
|
||||||
*/
|
*/
|
||||||
largeIcon?: string;
|
largeIcon?: string
|
||||||
/**
|
/**
|
||||||
* Icon color on Android.
|
* Icon color on Android.
|
||||||
*/
|
*/
|
||||||
iconColor?: string;
|
iconColor?: string
|
||||||
/**
|
/**
|
||||||
* Notification attachments.
|
* Notification attachments.
|
||||||
*/
|
*/
|
||||||
attachments?: Attachment[];
|
attachments?: Attachment[]
|
||||||
/**
|
/**
|
||||||
* Extra payload to store in the notification.
|
* Extra payload to store in the notification.
|
||||||
*/
|
*/
|
||||||
extra?: Record<string, unknown>;
|
extra?: Record<string, unknown>
|
||||||
/**
|
/**
|
||||||
* If true, the notification cannot be dismissed by the user on Android.
|
* If true, the notification cannot be dismissed by the user on Android.
|
||||||
*
|
*
|
||||||
@@ -113,29 +113,29 @@ interface Options {
|
|||||||
* It is typically used to indicate a background task that is pending (e.g. a file download)
|
* It is typically used to indicate a background task that is pending (e.g. a file download)
|
||||||
* or the user is engaged with (e.g. playing music).
|
* or the user is engaged with (e.g. playing music).
|
||||||
*/
|
*/
|
||||||
ongoing?: boolean;
|
ongoing?: boolean
|
||||||
/**
|
/**
|
||||||
* Automatically cancel the notification when the user clicks on it.
|
* Automatically cancel the notification when the user clicks on it.
|
||||||
*/
|
*/
|
||||||
autoCancel?: boolean;
|
autoCancel?: boolean
|
||||||
/**
|
/**
|
||||||
* Changes the notification presentation to be silent on iOS (no badge, no sound, not listed).
|
* Changes the notification presentation to be silent on iOS (no badge, no sound, not listed).
|
||||||
*/
|
*/
|
||||||
silent?: boolean;
|
silent?: boolean
|
||||||
/**
|
/**
|
||||||
* Notification visibility.
|
* Notification visibility.
|
||||||
*/
|
*/
|
||||||
visibility?: Visibility;
|
visibility?: Visibility
|
||||||
/**
|
/**
|
||||||
* Sets the number of items this notification represents on Android.
|
* Sets the number of items this notification represents on Android.
|
||||||
*/
|
*/
|
||||||
number?: number;
|
number?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ScheduleInterval {
|
interface ScheduleInterval {
|
||||||
year?: number;
|
year?: number
|
||||||
month?: number;
|
month?: number
|
||||||
day?: number;
|
day?: number
|
||||||
/**
|
/**
|
||||||
* 1 - Sunday
|
* 1 - Sunday
|
||||||
* 2 - Monday
|
* 2 - Monday
|
||||||
@@ -145,79 +145,79 @@ interface ScheduleInterval {
|
|||||||
* 6 - Friday
|
* 6 - Friday
|
||||||
* 7 - Saturday
|
* 7 - Saturday
|
||||||
*/
|
*/
|
||||||
weekday?: number;
|
weekday?: number
|
||||||
hour?: number;
|
hour?: number
|
||||||
minute?: number;
|
minute?: number
|
||||||
second?: number;
|
second?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ScheduleEvery {
|
enum ScheduleEvery {
|
||||||
Year = "year",
|
Year = 'year',
|
||||||
Month = "month",
|
Month = 'month',
|
||||||
TwoWeeks = "twoWeeks",
|
TwoWeeks = 'twoWeeks',
|
||||||
Week = "week",
|
Week = 'week',
|
||||||
Day = "day",
|
Day = 'day',
|
||||||
Hour = "hour",
|
Hour = 'hour',
|
||||||
Minute = "minute",
|
Minute = 'minute',
|
||||||
/**
|
/**
|
||||||
* Not supported on iOS.
|
* Not supported on iOS.
|
||||||
*/
|
*/
|
||||||
Second = "second",
|
Second = 'second'
|
||||||
}
|
}
|
||||||
|
|
||||||
class Schedule {
|
class Schedule {
|
||||||
at:
|
at:
|
||||||
| {
|
| {
|
||||||
date: Date;
|
date: Date
|
||||||
repeating: boolean;
|
repeating: boolean
|
||||||
allowWhileIdle: boolean;
|
allowWhileIdle: boolean
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined
|
||||||
|
|
||||||
interval:
|
interval:
|
||||||
| {
|
| {
|
||||||
interval: ScheduleInterval;
|
interval: ScheduleInterval
|
||||||
allowWhileIdle: boolean;
|
allowWhileIdle: boolean
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined
|
||||||
|
|
||||||
every:
|
every:
|
||||||
| {
|
| {
|
||||||
interval: ScheduleEvery;
|
interval: ScheduleEvery
|
||||||
count: number;
|
count: number
|
||||||
allowWhileIdle: boolean;
|
allowWhileIdle: boolean
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined
|
||||||
|
|
||||||
static at(date: Date, repeating = false, allowWhileIdle = false): Schedule {
|
static at(date: Date, repeating = false, allowWhileIdle = false): Schedule {
|
||||||
return {
|
return {
|
||||||
at: { date, repeating, allowWhileIdle },
|
at: { date, repeating, allowWhileIdle },
|
||||||
interval: undefined,
|
interval: undefined,
|
||||||
every: undefined,
|
every: undefined
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static interval(
|
static interval(
|
||||||
interval: ScheduleInterval,
|
interval: ScheduleInterval,
|
||||||
allowWhileIdle = false,
|
allowWhileIdle = false
|
||||||
): Schedule {
|
): Schedule {
|
||||||
return {
|
return {
|
||||||
at: undefined,
|
at: undefined,
|
||||||
interval: { interval, allowWhileIdle },
|
interval: { interval, allowWhileIdle },
|
||||||
every: undefined,
|
every: undefined
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static every(
|
static every(
|
||||||
kind: ScheduleEvery,
|
kind: ScheduleEvery,
|
||||||
count: number,
|
count: number,
|
||||||
allowWhileIdle = false,
|
allowWhileIdle = false
|
||||||
): Schedule {
|
): Schedule {
|
||||||
return {
|
return {
|
||||||
at: undefined,
|
at: undefined,
|
||||||
interval: undefined,
|
interval: undefined,
|
||||||
every: { interval: kind, count, allowWhileIdle },
|
every: { interval: kind, count, allowWhileIdle }
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,58 +226,58 @@ class Schedule {
|
|||||||
*/
|
*/
|
||||||
interface Attachment {
|
interface Attachment {
|
||||||
/** Attachment identifier. */
|
/** Attachment identifier. */
|
||||||
id: string;
|
id: string
|
||||||
/** Attachment URL. Accepts the `asset` and `file` protocols. */
|
/** Attachment URL. Accepts the `asset` and `file` protocols. */
|
||||||
url: string;
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Action {
|
interface Action {
|
||||||
id: string;
|
id: string
|
||||||
title: string;
|
title: string
|
||||||
requiresAuthentication?: boolean;
|
requiresAuthentication?: boolean
|
||||||
foreground?: boolean;
|
foreground?: boolean
|
||||||
destructive?: boolean;
|
destructive?: boolean
|
||||||
input?: boolean;
|
input?: boolean
|
||||||
inputButtonTitle?: string;
|
inputButtonTitle?: string
|
||||||
inputPlaceholder?: string;
|
inputPlaceholder?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActionType {
|
interface ActionType {
|
||||||
/**
|
/**
|
||||||
* The identifier of this action type
|
* The identifier of this action type
|
||||||
*/
|
*/
|
||||||
id: string;
|
id: string
|
||||||
/**
|
/**
|
||||||
* The list of associated actions
|
* The list of associated actions
|
||||||
*/
|
*/
|
||||||
actions: Action[];
|
actions: Action[]
|
||||||
hiddenPreviewsBodyPlaceholder?: string;
|
hiddenPreviewsBodyPlaceholder?: string
|
||||||
customDismissAction?: boolean;
|
customDismissAction?: boolean
|
||||||
allowInCarPlay?: boolean;
|
allowInCarPlay?: boolean
|
||||||
hiddenPreviewsShowTitle?: boolean;
|
hiddenPreviewsShowTitle?: boolean
|
||||||
hiddenPreviewsShowSubtitle?: boolean;
|
hiddenPreviewsShowSubtitle?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PendingNotification {
|
interface PendingNotification {
|
||||||
id: number;
|
id: number
|
||||||
title?: string;
|
title?: string
|
||||||
body?: string;
|
body?: string
|
||||||
schedule: Schedule;
|
schedule: Schedule
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActiveNotification {
|
interface ActiveNotification {
|
||||||
id: number;
|
id: number
|
||||||
tag?: string;
|
tag?: string
|
||||||
title?: string;
|
title?: string
|
||||||
body?: string;
|
body?: string
|
||||||
group?: string;
|
group?: string
|
||||||
groupSummary: boolean;
|
groupSummary: boolean
|
||||||
data: Record<string, string>;
|
data: Record<string, string>
|
||||||
extra: Record<string, unknown>;
|
extra: Record<string, unknown>
|
||||||
attachments: Attachment[];
|
attachments: Attachment[]
|
||||||
actionTypeId?: string;
|
actionTypeId?: string
|
||||||
schedule?: Schedule;
|
schedule?: Schedule
|
||||||
sound?: string;
|
sound?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Importance {
|
enum Importance {
|
||||||
@@ -285,25 +285,25 @@ enum Importance {
|
|||||||
Min,
|
Min,
|
||||||
Low,
|
Low,
|
||||||
Default,
|
Default,
|
||||||
High,
|
High
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Visibility {
|
enum Visibility {
|
||||||
Secret = -1,
|
Secret = -1,
|
||||||
Private,
|
Private,
|
||||||
Public,
|
Public
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Channel {
|
interface Channel {
|
||||||
id: string;
|
id: string
|
||||||
name: string;
|
name: string
|
||||||
description?: string;
|
description?: string
|
||||||
sound?: string;
|
sound?: string
|
||||||
lights?: boolean;
|
lights?: boolean
|
||||||
lightColor?: string;
|
lightColor?: string
|
||||||
vibration?: boolean;
|
vibration?: boolean
|
||||||
importance?: Importance;
|
importance?: Importance
|
||||||
visibility?: Visibility;
|
visibility?: Visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -317,10 +317,10 @@ interface Channel {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function isPermissionGranted(): Promise<boolean> {
|
async function isPermissionGranted(): Promise<boolean> {
|
||||||
if (window.Notification.permission !== "default") {
|
if (window.Notification.permission !== 'default') {
|
||||||
return await Promise.resolve(window.Notification.permission === "granted");
|
return await Promise.resolve(window.Notification.permission === 'granted')
|
||||||
}
|
}
|
||||||
return await invoke("plugin:notification|is_permission_granted");
|
return await invoke('plugin:notification|is_permission_granted')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -340,7 +340,7 @@ async function isPermissionGranted(): Promise<boolean> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function requestPermission(): Promise<NotificationPermission> {
|
async function requestPermission(): Promise<NotificationPermission> {
|
||||||
return await window.Notification.requestPermission();
|
return await window.Notification.requestPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,10 +362,10 @@ async function requestPermission(): Promise<NotificationPermission> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
function sendNotification(options: Options | string): void {
|
function sendNotification(options: Options | string): void {
|
||||||
if (typeof options === "string") {
|
if (typeof options === 'string') {
|
||||||
new window.Notification(options);
|
new window.Notification(options)
|
||||||
} else {
|
} else {
|
||||||
new window.Notification(options.title, options);
|
new window.Notification(options.title, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,7 +389,7 @@ function sendNotification(options: Options | string): void {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function registerActionTypes(types: ActionType[]): Promise<void> {
|
async function registerActionTypes(types: ActionType[]): Promise<void> {
|
||||||
await invoke("plugin:notification|register_action_types", { types });
|
await invoke('plugin:notification|register_action_types', { types })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -406,7 +406,7 @@ async function registerActionTypes(types: ActionType[]): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function pending(): Promise<PendingNotification[]> {
|
async function pending(): Promise<PendingNotification[]> {
|
||||||
return await invoke("plugin:notification|get_pending");
|
return await invoke('plugin:notification|get_pending')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -423,7 +423,7 @@ async function pending(): Promise<PendingNotification[]> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function cancel(notifications: number[]): Promise<void> {
|
async function cancel(notifications: number[]): Promise<void> {
|
||||||
await invoke("plugin:notification|cancel", { notifications });
|
await invoke('plugin:notification|cancel', { notifications })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -440,7 +440,7 @@ async function cancel(notifications: number[]): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function cancelAll(): Promise<void> {
|
async function cancelAll(): Promise<void> {
|
||||||
await invoke("plugin:notification|cancel");
|
await invoke('plugin:notification|cancel')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -457,7 +457,7 @@ async function cancelAll(): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function active(): Promise<ActiveNotification[]> {
|
async function active(): Promise<ActiveNotification[]> {
|
||||||
return await invoke("plugin:notification|get_active");
|
return await invoke('plugin:notification|get_active')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -474,9 +474,9 @@ async function active(): Promise<ActiveNotification[]> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function removeActive(
|
async function removeActive(
|
||||||
notifications: Array<{ id: number; tag?: string }>,
|
notifications: Array<{ id: number; tag?: string }>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await invoke("plugin:notification|remove_active", { notifications });
|
await invoke('plugin:notification|remove_active', { notifications })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -493,7 +493,7 @@ async function removeActive(
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function removeAllActive(): Promise<void> {
|
async function removeAllActive(): Promise<void> {
|
||||||
await invoke("plugin:notification|remove_active");
|
await invoke('plugin:notification|remove_active')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -517,7 +517,7 @@ async function removeAllActive(): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function createChannel(channel: Channel): Promise<void> {
|
async function createChannel(channel: Channel): Promise<void> {
|
||||||
await invoke("plugin:notification|create_channel", { ...channel });
|
await invoke('plugin:notification|create_channel', { ...channel })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -534,7 +534,7 @@ async function createChannel(channel: Channel): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function removeChannel(id: string): Promise<void> {
|
async function removeChannel(id: string): Promise<void> {
|
||||||
await invoke("plugin:notification|delete_channel", { id });
|
await invoke('plugin:notification|delete_channel', { id })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -551,19 +551,19 @@ async function removeChannel(id: string): Promise<void> {
|
|||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
async function channels(): Promise<Channel[]> {
|
async function channels(): Promise<Channel[]> {
|
||||||
return await invoke("plugin:notification|listChannels");
|
return await invoke('plugin:notification|listChannels')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onNotificationReceived(
|
async function onNotificationReceived(
|
||||||
cb: (notification: Options) => void,
|
cb: (notification: Options) => void
|
||||||
): Promise<PluginListener> {
|
): Promise<PluginListener> {
|
||||||
return await addPluginListener("notification", "notification", cb);
|
return await addPluginListener('notification', 'notification', cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onAction(
|
async function onAction(
|
||||||
cb: (notification: Options) => void,
|
cb: (notification: Options) => void
|
||||||
): Promise<PluginListener> {
|
): Promise<PluginListener> {
|
||||||
return await addPluginListener("notification", "actionPerformed", cb);
|
return await addPluginListener('notification', 'actionPerformed', cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
@@ -574,8 +574,8 @@ export type {
|
|||||||
PendingNotification,
|
PendingNotification,
|
||||||
ActiveNotification,
|
ActiveNotification,
|
||||||
Channel,
|
Channel,
|
||||||
ScheduleInterval,
|
ScheduleInterval
|
||||||
};
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Importance,
|
Importance,
|
||||||
@@ -596,5 +596,5 @@ export {
|
|||||||
onNotificationReceived,
|
onNotificationReceived,
|
||||||
onAction,
|
onAction,
|
||||||
Schedule,
|
Schedule,
|
||||||
ScheduleEvery,
|
ScheduleEvery
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -2,92 +2,89 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import type { PermissionState } from "@tauri-apps/api/core";
|
import type { PermissionState } from '@tauri-apps/api/core'
|
||||||
import type { Options } from "./index";
|
import type { Options } from './index'
|
||||||
|
;(function () {
|
||||||
(function () {
|
let permissionSettable = false
|
||||||
let permissionSettable = false;
|
let permissionValue = 'default'
|
||||||
let permissionValue = "default";
|
|
||||||
|
|
||||||
async function isPermissionGranted(): Promise<boolean> {
|
async function isPermissionGranted(): Promise<boolean> {
|
||||||
// @ts-expect-error __TEMPLATE_windows__ will be replaced in rust before it's injected.
|
// @ts-expect-error __TEMPLATE_windows__ will be replaced in rust before it's injected.
|
||||||
if (window.Notification.permission !== "default" || __TEMPLATE_windows__) {
|
if (window.Notification.permission !== 'default' || __TEMPLATE_windows__) {
|
||||||
return await Promise.resolve(
|
return await Promise.resolve(window.Notification.permission === 'granted')
|
||||||
window.Notification.permission === "granted",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return await invoke("plugin:notification|is_permission_granted");
|
return await invoke('plugin:notification|is_permission_granted')
|
||||||
}
|
}
|
||||||
|
|
||||||
function setNotificationPermission(value: NotificationPermission): void {
|
function setNotificationPermission(value: NotificationPermission): void {
|
||||||
permissionSettable = true;
|
permissionSettable = true
|
||||||
// @ts-expect-error we can actually set this value on the webview
|
// @ts-expect-error we can actually set this value on the webview
|
||||||
window.Notification.permission = value;
|
window.Notification.permission = value
|
||||||
permissionSettable = false;
|
permissionSettable = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function requestPermission(): Promise<PermissionState> {
|
async function requestPermission(): Promise<PermissionState> {
|
||||||
return await invoke<PermissionState>(
|
return await invoke<PermissionState>(
|
||||||
"plugin:notification|request_permission",
|
'plugin:notification|request_permission'
|
||||||
).then((permission) => {
|
).then((permission) => {
|
||||||
setNotificationPermission(
|
setNotificationPermission(
|
||||||
permission === "prompt" || permission === "prompt-with-rationale"
|
permission === 'prompt' || permission === 'prompt-with-rationale'
|
||||||
? "default"
|
? 'default'
|
||||||
: permission,
|
: permission
|
||||||
);
|
)
|
||||||
return permission;
|
return permission
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendNotification(options: string | Options): Promise<void> {
|
async function sendNotification(options: string | Options): Promise<void> {
|
||||||
if (typeof options === "object") {
|
if (typeof options === 'object') {
|
||||||
Object.freeze(options);
|
Object.freeze(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
await invoke("plugin:notification|notify", {
|
await invoke('plugin:notification|notify', {
|
||||||
options:
|
options:
|
||||||
typeof options === "string"
|
typeof options === 'string'
|
||||||
? {
|
? {
|
||||||
title: options,
|
title: options
|
||||||
}
|
}
|
||||||
: options,
|
: options
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error unfortunately we can't implement the whole type, so we overwrite it with our own version
|
// @ts-expect-error unfortunately we can't implement the whole type, so we overwrite it with our own version
|
||||||
window.Notification = function (title, options) {
|
window.Notification = function (title, options) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
const opts = options || {};
|
const opts = options || {}
|
||||||
void sendNotification(
|
void sendNotification(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||||
Object.assign(opts, {
|
Object.assign(opts, {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
title,
|
title
|
||||||
}),
|
})
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
// @ts-expect-error tauri does not have sync IPC :(
|
// @ts-expect-error tauri does not have sync IPC :(
|
||||||
window.Notification.requestPermission = requestPermission;
|
window.Notification.requestPermission = requestPermission
|
||||||
|
|
||||||
Object.defineProperty(window.Notification, "permission", {
|
Object.defineProperty(window.Notification, 'permission', {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: () => permissionValue,
|
get: () => permissionValue,
|
||||||
set: (v) => {
|
set: (v) => {
|
||||||
if (!permissionSettable) {
|
if (!permissionSettable) {
|
||||||
throw new Error("Readonly property");
|
throw new Error('Readonly property')
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
permissionValue = v;
|
permissionValue = v
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
void isPermissionGranted().then(function (response) {
|
void isPermissionGranted().then(function (response) {
|
||||||
if (response === null) {
|
if (response === null) {
|
||||||
setNotificationPermission("default");
|
setNotificationPermission('default')
|
||||||
} else {
|
} else {
|
||||||
setNotificationPermission(response ? "granted" : "denied");
|
setNotificationPermission(response ? 'granted' : 'denied')
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
})();
|
})()
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user