Compare commits

...

20 Commits

Author SHA1 Message Date
zhom 63b890d47f docs: add responsible desclosure guidelines 2025-06-03 17:01:47 +04:00
zhom aeb6a08fc8 build: automatically merge dependendabot changes if they pass ci 2025-06-03 16:54:14 +04:00
zhom c698fff101 build: manage nodecar dependencies via workspace 2025-06-03 16:53:27 +04:00
zhom ccfd1f81f6 build: fail build if security scan fails 2025-06-03 16:30:34 +04:00
zhom 4c42099661 fix: osv permissions 2025-06-03 15:33:45 +04:00
zhom 4c4aa10d8c fix: reset lock files after bad dependabot merge 2025-06-03 15:33:03 +04:00
zhom a1a6ef63e4 Merge pull request #11 from zhom/dependabot/npm_and_yarn/frontend-dependencies-852ce57221
deps(deps): bump the frontend-dependencies group across 1 directory with 12 updates
2025-06-03 15:26:21 +04:00
dependabot[bot] bd7b9f1d9f deps(deps): bump the frontend-dependencies group across 1 directory with 12 updates
Bumps the frontend-dependencies group with 1 update in the / directory: [@jridgewell/trace-mapping](https://github.com/jridgewell/trace-mapping).


Updates `@jridgewell/trace-mapping` from 0.3.9 to 0.3.25
- [Release notes](https://github.com/jridgewell/trace-mapping/releases)
- [Commits](https://github.com/jridgewell/trace-mapping/compare/v0.3.9...v0.3.25)

Updates `ansi-regex` from 5.0.1 to 6.1.0
- [Release notes](https://github.com/chalk/ansi-regex/releases)
- [Commits](https://github.com/chalk/ansi-regex/compare/v5.0.1...v6.1.0)

Updates `chownr` from 1.1.4 to 3.0.0
- [Commits](https://github.com/isaacs/chownr/compare/v1.1.4...v3.0.0)

Updates `emoji-regex` from 8.0.0 to 9.2.2
- [Commits](https://github.com/mathiasbynens/emoji-regex/compare/v8.0.0...v9.2.2)

Updates `has-flag` from 3.0.0 to 4.0.0
- [Release notes](https://github.com/sindresorhus/has-flag/releases)
- [Commits](https://github.com/sindresorhus/has-flag/compare/v3.0.0...v4.0.0)

Updates `is-fullwidth-code-point` from 3.0.0 to 4.0.0
- [Release notes](https://github.com/sindresorhus/is-fullwidth-code-point/releases)
- [Commits](https://github.com/sindresorhus/is-fullwidth-code-point/compare/v3.0.0...v4.0.0)

Updates `isarray` from 1.0.0 to 2.0.5
- [Release notes](https://github.com/juliangruber/isarray/releases)
- [Commits](https://github.com/juliangruber/isarray/compare/v1.0.0...v2.0.5)

Updates `string-width` from 4.2.3 to 7.2.0
- [Release notes](https://github.com/sindresorhus/string-width/releases)
- [Commits](https://github.com/sindresorhus/string-width/compare/v4.2.3...v7.2.0)

Updates `strip-ansi` from 6.0.1 to 7.1.0
- [Release notes](https://github.com/chalk/strip-ansi/releases)
- [Commits](https://github.com/chalk/strip-ansi/compare/v6.0.1...v7.1.0)

Updates `strip-json-comments` from 2.0.1 to 3.1.1
- [Release notes](https://github.com/sindresorhus/strip-json-comments/releases)
- [Commits](https://github.com/sindresorhus/strip-json-comments/compare/v2.0.1...v3.1.1)

Updates `supports-color` from 5.5.0 to 7.2.0
- [Release notes](https://github.com/chalk/supports-color/releases)
- [Commits](https://github.com/chalk/supports-color/compare/v5.5.0...v7.2.0)

Updates `wrap-ansi` from 7.0.0 to 9.0.0
- [Release notes](https://github.com/chalk/wrap-ansi/releases)
- [Commits](https://github.com/chalk/wrap-ansi/compare/v7.0.0...v9.0.0)

---
updated-dependencies:
- dependency-name: "@jridgewell/trace-mapping"
  dependency-version: 0.3.25
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: frontend-dependencies
- dependency-name: ansi-regex
  dependency-version: 6.1.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: chownr
  dependency-version: 3.0.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: emoji-regex
  dependency-version: 9.2.2
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: has-flag
  dependency-version: 4.0.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: is-fullwidth-code-point
  dependency-version: 4.0.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: isarray
  dependency-version: 2.0.5
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: string-width
  dependency-version: 7.2.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: strip-ansi
  dependency-version: 7.1.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: strip-json-comments
  dependency-version: 3.1.1
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: supports-color
  dependency-version: 7.2.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
- dependency-name: wrap-ansi
  dependency-version: 9.0.0
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: frontend-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 11:24:36 +00:00
zhom f93b5daa9b Merge pull request #8 from zhom/dependabot/npm_and_yarn/nodecar/nodecar-dependencies-a69e916d1e
deps(nodecar)(deps): bump the nodecar-dependencies group in /nodecar with 4 updates
2025-06-03 15:10:21 +04:00
zhom f7f45bdc90 Merge pull request #10 from zhom/dependabot/cargo/src-tauri/rust-dependencies-04ecd6b2d6
deps(rust)(deps): bump the rust-dependencies group in /src-tauri with 3 updates
2025-06-03 15:09:36 +04:00
dependabot[bot] 48067ee3a7 deps(rust)(deps): bump the rust-dependencies group
Bumps the rust-dependencies group in /src-tauri with 3 updates: [reqwest](https://github.com/seanmonstar/reqwest), [camino](https://github.com/camino-rs/camino) and [tower-http](https://github.com/tower-rs/tower-http).


Updates `reqwest` from 0.12.18 to 0.12.19
- [Release notes](https://github.com/seanmonstar/reqwest/releases)
- [Changelog](https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/reqwest/compare/v0.12.18...v0.12.19)

Updates `camino` from 1.1.9 to 1.1.10
- [Release notes](https://github.com/camino-rs/camino/releases)
- [Changelog](https://github.com/camino-rs/camino/blob/main/CHANGELOG.md)
- [Commits](https://github.com/camino-rs/camino/compare/camino-1.1.9...camino-1.1.10)

Updates `tower-http` from 0.6.4 to 0.6.5
- [Release notes](https://github.com/tower-rs/tower-http/releases)
- [Commits](https://github.com/tower-rs/tower-http/compare/tower-http-0.6.4...tower-http-0.6.5)

---
updated-dependencies:
- dependency-name: reqwest
  dependency-version: 0.12.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: camino
  dependency-version: 1.1.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: tower-http
  dependency-version: 0.6.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 11:07:37 +00:00
zhom 87bd75aa21 chore: pnpm update && pnpm install --ignore-workspace 2025-06-03 15:07:13 +04:00
zhom cf443061b6 chore: pnpm install 2025-06-03 15:02:46 +04:00
zhom ca662d91a1 Merge pull request #7 from zhom/dependabot/github_actions/github-actions-0c45e47a22
ci(deps): bump google/osv-scanner-action from 1.7.1 to 2.0.2 in the github-actions group
2025-06-03 14:58:38 +04:00
dependabot[bot] 2963dbc0f9 deps(nodecar)(deps): bump the nodecar-dependencies group
Bumps the nodecar-dependencies group in /nodecar with 4 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@yao-pkg/pkg](https://github.com/yao-pkg/pkg), [commander](https://github.com/tj/commander.js) and [proxy-chain](https://github.com/apify/proxy-chain).


Updates `@types/node` from 22.15.17 to 22.15.29
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@yao-pkg/pkg` from 6.4.1 to 6.5.1
- [Release notes](https://github.com/yao-pkg/pkg/releases)
- [Changelog](https://github.com/yao-pkg/pkg/blob/main/CHANGELOG.md)
- [Commits](https://github.com/yao-pkg/pkg/compare/v6.4.1...v6.5.1)

Updates `commander` from 13.1.0 to 14.0.0
- [Release notes](https://github.com/tj/commander.js/releases)
- [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tj/commander.js/compare/v13.1.0...v14.0.0)

Updates `proxy-chain` from 2.5.8 to 2.5.9
- [Release notes](https://github.com/apify/proxy-chain/releases)
- [Changelog](https://github.com/apify/proxy-chain/blob/master/CHANGELOG.md)
- [Commits](https://github.com/apify/proxy-chain/compare/v2.5.8...v2.5.9)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.29
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nodecar-dependencies
- dependency-name: "@yao-pkg/pkg"
  dependency-version: 6.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nodecar-dependencies
- dependency-name: commander
  dependency-version: 14.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: nodecar-dependencies
- dependency-name: proxy-chain
  dependency-version: 2.5.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nodecar-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 10:51:44 +00:00
dependabot[bot] 225ed05d08 ci(deps): bump google/osv-scanner-action in the github-actions group
Bumps the github-actions group with 1 update: [google/osv-scanner-action](https://github.com/google/osv-scanner-action).


Updates `google/osv-scanner-action` from 1.7.1 to 2.0.2
- [Release notes](https://github.com/google/osv-scanner-action/releases)
- [Commits](https://github.com/google/osv-scanner-action/compare/1f1242919d8a60496dd1874b24b62b2370ed4c78...e69cc6c86b31f1e7e23935bbe7031b50e51082de)

---
updated-dependencies:
- dependency-name: google/osv-scanner-action
  dependency-version: 2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 10:48:03 +00:00
zhom 97de246ac6 feat: use osv, add pr checks, extend dependabot 2025-06-03 14:46:58 +04:00
zhom b00f62ebec fix: improve toast and dialog interations 2025-06-03 13:56:58 +04:00
zhom 2025a2a690 feat: better integrate with macos titlebar 2025-06-03 13:11:17 +04:00
zhom 2f1faa02e4 chore: version bump 2025-06-02 18:30:50 +04:00
38 changed files with 1769 additions and 1637 deletions
+46 -4
View File
@@ -1,28 +1,70 @@
version: 2
updates:
# Enable version updates for Node.js dependencies
# Frontend dependencies (root package.json)
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
allow:
- dependency-type: "all"
groups:
all:
frontend-dependencies:
patterns:
- "*"
ignore:
- dependency-name: "eslint"
versions: ">= 9"
commit-message:
prefix: "deps"
include: "scope"
# Enable version updates for rust
# Nodecar dependencies
- package-ecosystem: "npm"
directory: "/nodecar"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
allow:
- dependency-type: "all"
groups:
nodecar-dependencies:
patterns:
- "*"
commit-message:
prefix: "deps(nodecar)"
include: "scope"
# Rust dependencies
- package-ecosystem: "cargo"
directory: "/src-tauri"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
allow:
- dependency-type: "all"
groups:
all:
rust-dependencies:
patterns:
- "*"
commit-message:
prefix: "deps(rust)"
include: "scope"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
groups:
github-actions:
patterns:
- "*"
commit-message:
prefix: "ci"
include: "scope"
+48 -9
View File
@@ -1,21 +1,60 @@
# Automatically squashes and merges Dependabot dependency upgrades if tests pass
name: Dependabot Automerge
name: Dependabot Auto-merge
on: pull_request_target
on:
pull_request_target:
types: [opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
checks: read
jobs:
dependabot:
runs-on: ubuntu-latest
security-scan:
name: Security Vulnerability Scan
if: ${{ github.actor == 'dependabot[bot]' }}
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@e69cc6c86b31f1e7e23935bbe7031b50e51082de" # v2.0.2
with:
scan-args: |-
-r
--skip-git
--lockfile=pnpm-lock.yaml
--lockfile=src-tauri/Cargo.lock
--lockfile=nodecar/pnpm-lock.yaml
./
permissions:
security-events: write
contents: read
actions: read
lint-js:
name: Lint JavaScript/TypeScript
if: ${{ github.actor == 'dependabot[bot]' }}
uses: ./.github/workflows/lint-js.yml
secrets: inherit
lint-rust:
name: Lint Rust
if: ${{ github.actor == 'dependabot[bot]' }}
uses: ./.github/workflows/lint-rs.yml
secrets: inherit
dependabot-automerge:
name: Dependabot Automerge
if: ${{ github.actor == 'dependabot[bot]' }}
needs: [security-scan, lint-js, lint-rust]
runs-on: ubuntu-latest
steps:
- name: Fetch Dependabot metadata
id: dependabot-metadata
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Auto-merge minor and patch updates
uses: ridedott/merge-me-action@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PRESET: DEPENDABOT_MINOR
MERGE_METHOD: SQUASH
timeout-minutes: 10
+2
View File
@@ -13,6 +13,8 @@ on:
paths-ignore:
- "src-tauri/**"
- "README.md"
- ".github/workflows/lint-rs.yml"
- ".github/workflows/osv.yml"
jobs:
build:
+9 -3
View File
@@ -12,11 +12,17 @@ on:
pull_request:
paths-ignore:
- "src/**"
- "nodecar/**"
- "package.json"
- "package-lock.json"
- "yarn.lock"
- "pnpm-lock.yaml"
- "yarn.lock"
- "README.md"
- ".github/workflows/lint-js.yml"
- ".github/workflows/osv.yml"
- "next.config.js"
- "tailwind.config.js"
- "tsconfig.json"
- "biome.json"
jobs:
build:
@@ -61,7 +67,7 @@ jobs:
- name: Install nodecar dependencies
working-directory: ./nodecar
run: |
pnpm install --ignore-workspace --frozen-lockfile
pnpm install --frozen-lockfile
- name: Build nodecar binary
shell: bash
+74
View File
@@ -0,0 +1,74 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# A sample workflow which sets up periodic OSV-Scanner scanning for vulnerabilities,
# in addition to a PR check which fails if new vulnerabilities are introduced.
#
# For more examples and options, including how to ignore specific vulnerabilities,
# see https://google.github.io/osv-scanner/github-action/
# Security vulnerability scanning for Donut Browser
# Scans dependencies in package managers (npm/pnpm, Cargo) for known vulnerabilities
# Runs on schedule and when dependencies change
name: Security Vulnerability Scan
on:
pull_request:
branches: ["main"]
paths:
- "package.json"
- "pnpm-lock.yaml"
- "src-tauri/Cargo.toml"
- "src-tauri/Cargo.lock"
- "nodecar/package.json"
- "nodecar/pnpm-lock.yaml"
- ".github/workflows/osv.yml"
merge_group:
branches: ["main"]
schedule:
# Run weekly on Tuesdays at 2:20 PM UTC
- cron: "20 14 * * 2"
push:
branches: ["main"]
paths:
- "package.json"
- "pnpm-lock.yaml"
- "src-tauri/Cargo.toml"
- "src-tauri/Cargo.lock"
- "nodecar/package.json"
- "nodecar/pnpm-lock.yaml"
permissions:
security-events: write
contents: read
actions: read
jobs:
scan-scheduled:
name: Scheduled Security Scan
if: ${{ github.event_name == 'push' || github.event_name == 'schedule' }}
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@e69cc6c86b31f1e7e23935bbe7031b50e51082de" # v2.0.2
with:
scan-args: |-
-r
--skip-git
--lockfile=pnpm-lock.yaml
--lockfile=src-tauri/Cargo.lock
--lockfile=nodecar/pnpm-lock.yaml
./
scan-pr:
name: PR Security Scan
if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@e69cc6c86b31f1e7e23935bbe7031b50e51082de" # v2.0.2
with:
scan-args: |-
-r
--skip-git
--lockfile=pnpm-lock.yaml
--lockfile=src-tauri/Cargo.lock
--lockfile=nodecar/pnpm-lock.yaml
./
+50
View File
@@ -0,0 +1,50 @@
name: Pull Request Checks
on:
pull_request:
branches: ["main"]
merge_group:
branches: ["main"]
permissions:
security-events: write
contents: read
actions: read
jobs:
lint-js:
name: Lint JavaScript/TypeScript
uses: ./.github/workflows/lint-js.yml
secrets: inherit
lint-rust:
name: Lint Rust
uses: ./.github/workflows/lint-rs.yml
secrets: inherit
security-scan:
name: Security Vulnerability Scan
if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@e69cc6c86b31f1e7e23935bbe7031b50e51082de" # v2.0.2
with:
scan-args: |-
-r
--skip-git
--lockfile=pnpm-lock.yaml
--lockfile=nodecar/pnpm-lock.yaml
--lockfile=src-tauri/Cargo.lock
./
pr-status:
name: PR Status Check
runs-on: ubuntu-latest
needs: [lint-js, lint-rust, security-scan]
if: always()
steps:
- name: Check all jobs succeeded
run: |
if [[ "${{ needs.lint-js.result }}" != "success" || "${{ needs.lint-rust.result }}" != "success" || "${{ needs.security-scan.result }}" != "success" ]]; then
echo "One or more checks failed"
exit 1
fi
echo "All checks passed!"
+18 -2
View File
@@ -11,6 +11,22 @@ env:
STABLE_RELEASE: "true"
jobs:
security-scan:
name: Security Vulnerability Scan
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@e69cc6c86b31f1e7e23935bbe7031b50e51082de" # v2.0.2
with:
scan-args: |-
-r
--skip-git
--lockfile=pnpm-lock.yaml
--lockfile=src-tauri/Cargo.lock
--lockfile=nodecar/pnpm-lock.yaml
./
permissions:
security-events: write
contents: read
actions: read
lint-js:
name: Lint JavaScript/TypeScript
uses: ./.github/workflows/lint-js.yml
@@ -22,7 +38,7 @@ jobs:
secrets: inherit
release:
needs: [lint-js, lint-rust]
needs: [security-scan, lint-js, lint-rust]
permissions:
contents: write
strategy:
@@ -101,7 +117,7 @@ jobs:
- name: Install nodecar dependencies
working-directory: ./nodecar
run: |
pnpm install --ignore-workspace --frozen-lockfile
pnpm install --frozen-lockfile
- name: Build nodecar sidecar
shell: bash
+18 -2
View File
@@ -10,6 +10,22 @@ env:
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
jobs:
security-scan:
name: Security Vulnerability Scan
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@e69cc6c86b31f1e7e23935bbe7031b50e51082de" # v2.0.2
with:
scan-args: |-
-r
--skip-git
--lockfile=pnpm-lock.yaml
--lockfile=src-tauri/Cargo.lock
--lockfile=nodecar/pnpm-lock.yaml
./
permissions:
security-events: write
contents: read
actions: read
lint-js:
name: Lint JavaScript/TypeScript
uses: ./.github/workflows/lint-js.yml
@@ -21,7 +37,7 @@ jobs:
secrets: inherit
rolling-release:
needs: [lint-js, lint-rust]
needs: [security-scan, lint-js, lint-rust]
permissions:
contents: write
strategy:
@@ -69,7 +85,7 @@ jobs:
- name: Install nodecar dependencies
working-directory: ./nodecar
run: |
pnpm install --ignore-workspace --frozen-lockfile
pnpm install --frozen-lockfile
- name: Build nodecar sidecar
shell: bash
+4
View File
@@ -5,6 +5,10 @@
/.pnp
.pnp.js
# npm/yarn lock files (project uses pnpm only)
**/package-lock.json
**/yarn.lock
# testing
/coverage
+27 -1
View File
@@ -1,23 +1,49 @@
{
"cSpell.words": [
"applescript",
"autoconfig",
"autologin",
"biomejs",
"cdylib",
"CFURL",
"checkin",
"clippy",
"codegen",
"donutbrowser",
"dtolnay",
"elif",
"esbuild",
"gifs",
"launchservices",
"mountpoint",
"Mullvad",
"nodecar",
"ntlm",
"objc",
"osascript",
"plasmohq",
"propertylist",
"reqwest",
"rlib",
"rustc",
"SARIF",
"serde",
"shadcn",
"signon",
"sonner",
"sspi",
"staticlib",
"swatinem",
"sysinfo",
"systempreferences",
"turbopack"
"tauri",
"titlebar",
"Torbrowser",
"turbopack",
"unlisten",
"unrs",
"wiremock",
"xattr",
"zhom"
]
}
+1 -1
View File
@@ -50,7 +50,7 @@ After having the above dependencies installed, proceed through the following ste
```bash
cd nodecar
pnpm install --ignore-workspace --frozen-lockfile
pnpm install --frozen-lockfile
cd ..
```
+40
View File
@@ -0,0 +1,40 @@
# Security Policy
## Reporting Security Issues
Thanks for helping make Donut Browser safe for everyone! ❤️
We take the security of Donut Browser seriously. If you believe you have found a security vulnerability in Donut Browser, please report it to us through coordinated disclosure.
**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**
Instead, please send an email to **contact at donutbrowser dot com** with the subject line "Security Vulnerability Report".
Please include as much of the information listed below as you can to help us better understand and resolve the issue:
- The type of issue (e.g., buffer overflow, injection attack, privilege escalation, or cross-site scripting)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue
- Your assessment of the severity level
This information will help us triage your report more quickly.
## What to Expect
- **Response Time**: We will acknowledge receipt of your vulnerability report within 72 hours.
- **Investigation**: We will investigate the issue and provide you with updates on our progress.
- **Resolution**: We aim to resolve critical security issues as fast as possible, but no longer than in 30 days after the initial report.
- **Disclosure**: We will coordinate with you on the timing of any public disclosure.
## Contact
For urgent security matters, please contact us at **contact at donutbrowser dot com**.
For general questions about this security policy, you can also reach out through:
- [GitHub Issues](https://github.com/zhom/donutbrowser/issues) (for non-security questions only)
- [GitHub Discussions](https://github.com/zhom/donutbrowser/discussions)
+2 -2
View File
@@ -4,7 +4,7 @@
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"config": "tailwind.config.js",
"css": "src/styles/globals.css",
"baseColor": "zinc",
"cssVariables": true,
@@ -18,4 +18,4 @@
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
}
+5 -5
View File
@@ -18,15 +18,15 @@
"keywords": [],
"author": "",
"license": "AGPL-3.0",
"packageManager": "pnpm@10.6.1",
"packageManager": "pnpm@10.11.1+sha512.e519b9f7639869dc8d5c3c5dfef73b3f091094b0a006d7317353c72b124e80e1afd429732e28705ad6bfa1ee879c1fce46c128ccebd3192101f43dd67c667912",
"dependencies": {
"@types/node": "^22.15.17",
"@yao-pkg/pkg": "^6.4.1",
"commander": "^13.1.0",
"@types/node": "^22.15.29",
"@yao-pkg/pkg": "^6.5.1",
"commander": "^14.0.0",
"dotenv": "^16.5.0",
"get-port": "^7.1.0",
"nodemon": "^3.1.10",
"proxy-chain": "^2.5.8",
"proxy-chain": "^2.5.9",
"ts-node": "^10.9.2",
"typescript": "^5.8.3"
}
-1304
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -48,8 +48,8 @@ program
ignoreProxyCertificate: options.ignoreCertificate,
});
console.log(JSON.stringify(config));
} catch (error: any) {
console.error(`Failed to start proxy: ${error.message}`);
} catch (error: unknown) {
console.error(`Failed to start proxy: ${JSON.stringify(error)}`);
}
} else if (action === "stop") {
if (options.id) {
+2 -2
View File
@@ -1,5 +1,5 @@
import { spawn } from "child_process";
import path from "path";
import { spawn } from "node:child_process";
import path from "node:path";
import getPort from "get-port";
import {
type ProxyConfig,
+3 -3
View File
@@ -1,6 +1,6 @@
import fs from "fs";
import path from "path";
import os from "os";
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
// Define the proxy configuration type
export interface ProxyConfig {
+15 -15
View File
@@ -2,7 +2,7 @@
"name": "donutbrowser",
"private": true,
"license": "AGPL-3.0",
"version": "0.2.4",
"version": "0.2.5",
"type": "module",
"scripts": {
"dev": "next dev --turbopack",
@@ -42,31 +42,31 @@
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
"sonner": "^2.0.3",
"sonner": "^2.0.5",
"tailwind-merge": "^3.3.0"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.27.0",
"@next/eslint-plugin-next": "^15.3.2",
"@tailwindcss/postcss": "^4.1.7",
"@eslint/js": "^9.28.0",
"@next/eslint-plugin-next": "^15.3.3",
"@tailwindcss/postcss": "^4.1.8",
"@tauri-apps/cli": "^2.5.0",
"@types/node": "^22.15.21",
"@types/react": "^19.1.5",
"@types/node": "^22.15.29",
"@types/react": "^19.1.6",
"@types/react-dom": "^19.1.5",
"@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.1",
"@vitejs/plugin-react": "^4.5.0",
"eslint": "^9.27.0",
"eslint-config-next": "^15.3.2",
"@typescript-eslint/eslint-plugin": "^8.33.1",
"@typescript-eslint/parser": "^8.33.1",
"@vitejs/plugin-react": "^4.5.1",
"eslint": "^9.28.0",
"eslint-config-next": "^15.3.3",
"eslint-plugin-react-hooks": "^5.2.0",
"husky": "^9.1.7",
"lint-staged": "^16.1.0",
"tailwindcss": "^4.1.7",
"tw-animate-css": "^1.3.0",
"tailwindcss": "^4.1.8",
"tw-animate-css": "^1.3.3",
"typescript": "~5.8.3",
"typescript-eslint": "^8.32.1"
"typescript-eslint": "^8.33.1"
},
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977",
"lint-staged": {
+1117 -239
View File
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -1,5 +1,9 @@
packages:
- "nodecar"
onlyBuiltDependencies:
- '@biomejs/biome'
- '@tailwindcss/oxide'
- "@biomejs/biome"
- "@tailwindcss/oxide"
- esbuild
- sharp
- unrs-resolver
+9 -7
View File
@@ -458,9 +458,9 @@ dependencies = [
[[package]]
name = "camino"
version = "1.1.9"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab"
dependencies = [
"serde",
]
@@ -963,7 +963,7 @@ dependencies = [
[[package]]
name = "donutbrowser"
version = "0.2.4"
version = "0.2.5"
dependencies = [
"async-trait",
"base64 0.22.1",
@@ -971,6 +971,8 @@ dependencies = [
"directories",
"futures-util",
"lazy_static",
"objc2 0.6.1",
"objc2-app-kit",
"reqwest",
"serde",
"serde_json",
@@ -3393,9 +3395,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "reqwest"
version = "0.12.18"
version = "0.12.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e98ff6b0dbbe4d5a37318f433d4fc82babd21631f194d370409ceb2e40b2f0b5"
checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119"
dependencies = [
"base64 0.22.1",
"bytes",
@@ -4729,9 +4731,9 @@ dependencies = [
[[package]]
name = "tower-http"
version = "0.6.4"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e"
checksum = "5cc2d9e086a412a451384326f521c8123a99a466b329941a9403696bff9b0da2"
dependencies = [
"bitflags 2.9.1",
"bytes",
+3 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "donutbrowser"
version = "0.2.4"
version = "0.2.5"
description = "Browser Orchestrator"
authors = ["zhom@github"]
edition = "2021"
@@ -37,6 +37,8 @@ futures-util = "0.3"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation="0.10"
objc2 = "0.6.1"
objc2-app-kit = { version = "0.3.1", features = ["NSWindow"] }
[dev-dependencies]
tempfile = "3.13.0"
+1 -1
View File
@@ -13,7 +13,7 @@
<key>CFBundleVersion</key>
<string>1</string>
<key>CFBundleShortVersionString</key>
<string>0.2.4</string>
<string>0.2.5</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
+5
View File
@@ -6,6 +6,11 @@
"permissions": [
"core:default",
"core:event:default",
"core:window:default",
"core:window:allow-start-dragging",
"core:window:allow-close",
"core:window:allow-minimize",
"core:window:allow-toggle-maximize",
"opener:default",
"fs:default",
"shell:allow-execute",
+119 -1
View File
@@ -1,7 +1,7 @@
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
use tauri::{Emitter, Manager};
use tauri::{Emitter, Manager, Runtime, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
use tauri_plugin_deep_link::DeepLinkExt;
// Store pending URLs that need to be handled when the window is ready
@@ -58,6 +58,51 @@ use app_auto_updater::{
get_app_version_info,
};
// Trait to extend WebviewWindow with transparent titlebar functionality
pub trait WindowExt {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, transparent: bool) -> Result<(), String>;
}
impl<R: Runtime> WindowExt for WebviewWindow<R> {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, transparent: bool) -> Result<(), String> {
use objc2::rc::Retained;
use objc2_app_kit::{NSWindow, NSWindowStyleMask, NSWindowTitleVisibility};
unsafe {
let ns_window: Retained<NSWindow> =
Retained::retain(self.ns_window().unwrap().cast()).unwrap();
if transparent {
// Hide the title text
ns_window.setTitleVisibility(NSWindowTitleVisibility(2)); // NSWindowTitleHidden
// Make titlebar transparent
ns_window.setTitlebarAppearsTransparent(true);
// Set full size content view
let current_mask = ns_window.styleMask();
let new_mask = NSWindowStyleMask(current_mask.0 | (1 << 15)); // NSFullSizeContentViewWindowMask
ns_window.setStyleMask(new_mask);
} else {
// Show the title text
ns_window.setTitleVisibility(NSWindowTitleVisibility(0)); // NSWindowTitleVisible
// Make titlebar opaque
ns_window.setTitlebarAppearsTransparent(false);
// Remove full size content view
let current_mask = ns_window.styleMask();
let new_mask = NSWindowStyleMask(current_mask.0 & !(1 << 15));
ns_window.setStyleMask(new_mask);
}
}
Ok(())
}
}
#[tauri::command]
fn greet() -> String {
let now = SystemTime::now();
@@ -124,6 +169,61 @@ async fn check_and_handle_startup_url(app_handle: tauri::AppHandle) -> Result<bo
Ok(false)
}
#[tauri::command]
async fn set_window_background_color(
app_handle: tauri::AppHandle,
is_dark_mode: bool,
) -> Result<(), String> {
#[cfg(target_os = "macos")]
{
if let Some(window) = app_handle.get_webview_window("main") {
use objc2::rc::Retained;
use objc2_app_kit::{NSColor, NSWindow};
let ns_window: Retained<NSWindow> =
unsafe { Retained::retain(window.ns_window().unwrap().cast()).unwrap() };
let bg_color = if is_dark_mode {
// Dark mode - pure black background
unsafe { NSColor::colorWithRed_green_blue_alpha(0.0, 0.0, 0.0, 1.0) }
} else {
// Light mode - pure white background
unsafe { NSColor::colorWithRed_green_blue_alpha(1.0, 1.0, 1.0, 1.0) }
};
// Ensure this runs on the main thread for immediate visual update
unsafe {
// Set the window background color
ns_window.setBackgroundColor(Some(&bg_color));
// Force immediate visual updates using multiple refresh methods
ns_window.invalidateShadow();
ns_window.display();
// Ensure the window content is redrawn
if let Some(content_view) = ns_window.contentView() {
content_view.setNeedsDisplay(true);
content_view.displayIfNeeded();
}
// Trigger a window update
ns_window.update();
}
// Also emit an event to the frontend to ensure synchronization
let _ = app_handle.emit("window-background-updated", is_dark_mode);
}
}
#[cfg(not(target_os = "macos"))]
{
// For non-macOS platforms, we can't change the native window background
let _ = (app_handle, is_dark_mode); // Suppress unused variable warnings
}
Ok(())
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
@@ -132,6 +232,23 @@ pub fn run() {
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_deep_link::init())
.setup(|app| {
// Create the main window programmatically
let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
.title("Donut Browser")
.inner_size(900.0, 600.0)
.resizable(false)
.fullscreen(false);
let window = win_builder.build().unwrap();
// Set transparent titlebar for macOS
#[cfg(target_os = "macos")]
{
if let Err(e) = window.set_transparent_titlebar(true) {
eprintln!("Failed to set transparent titlebar: {e}");
}
}
// Set up deep link handler
let handle = app.handle().clone();
@@ -264,6 +381,7 @@ pub fn run() {
check_for_app_updates_manual,
download_and_install_app_update,
get_app_version_info,
set_window_background_color,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
+2 -10
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Donut Browser",
"version": "0.2.4",
"version": "0.2.5",
"identifier": "com.donutbrowser",
"build": {
"beforeDevCommand": "pnpm dev",
@@ -10,15 +10,7 @@
"frontendDist": "../dist"
},
"app": {
"windows": [
{
"title": "Donut Browser",
"width": 900,
"height": 600,
"resizable": false,
"fullscreen": false
}
],
"windows": [],
"security": {
"csp": null
}
+2
View File
@@ -4,6 +4,7 @@ import "@/styles/globals.css";
import { CustomThemeProvider } from "@/components/theme-provider";
import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { WindowDragArea } from "@/components/window-drag-area";
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -26,6 +27,7 @@ export default function RootLayout({
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<CustomThemeProvider>
<WindowDragArea />
<TooltipProvider>{children}</TooltipProvider>
<Toaster />
</CustomThemeProvider>
+14 -8
View File
@@ -48,6 +48,7 @@ export default function Home() {
useState<BrowserProfile | null>(null);
const [currentProfileForVersionChange, setCurrentProfileForVersionChange] =
useState<BrowserProfile | null>(null);
const [hasCheckedStartupPrompt, setHasCheckedStartupPrompt] = useState(false);
// Simple profiles loader without updates check (for use as callback)
const loadProfiles = useCallback(async () => {
@@ -110,6 +111,9 @@ export default function Home() {
}, [loadProfilesWithUpdateCheck, checkForUpdates]);
const checkStartupPrompt = async () => {
// Only check once during app startup to prevent reopening after dismissing notifications
if (hasCheckedStartupPrompt) return;
try {
const shouldShow = await invoke<boolean>(
"should_show_settings_on_startup",
@@ -117,8 +121,10 @@ export default function Home() {
if (shouldShow) {
setSettingsDialogOpen(true);
}
setHasCheckedStartupPrompt(true);
} catch (error) {
console.error("Failed to check startup prompt:", error);
setHasCheckedStartupPrompt(true);
}
};
@@ -394,13 +400,13 @@ export default function Home() {
);
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 gap-8 sm:p-12 font-[family-name:var(--font-geist-sans)]">
<main className="flex flex-col gap-8 row-start-2 items-center w-full max-w-3xl">
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 gap-8 sm:p-12 font-[family-name:var(--font-geist-sans)] bg-white dark:bg-black">
<main className="flex flex-col row-start-2 gap-8 items-center w-full max-w-3xl">
<Card className="w-full">
<CardHeader>
<div className="flex items-center justify-between">
<div className="flex justify-between items-center">
<CardTitle>Profiles</CardTitle>
<div className="flex items-center gap-2">
<div className="flex gap-2 items-center">
<Tooltip>
<TooltipTrigger asChild>
<Button
@@ -409,9 +415,9 @@ export default function Home() {
onClick={() => {
setSettingsDialogOpen(true);
}}
className="flex items-center gap-2"
className="flex gap-2 items-center"
>
<GoGear className="h-4 w-4" />
<GoGear className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Settings</TooltipContent>
@@ -423,9 +429,9 @@ export default function Home() {
onClick={() => {
setCreateProfileDialogOpen(true);
}}
className="flex items-center gap-2"
className="flex gap-2 items-center"
>
<GoPlus className="h-4 w-4" />
<GoPlus className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Create a new profile</TooltipContent>
+2 -2
View File
@@ -139,7 +139,7 @@ export function SettingsDialog({ isOpen, onClose }: SettingsDialogProps) {
<DialogTitle>Settings</DialogTitle>
</DialogHeader>
<div className="grid gap-6 py-4 overflow-y-auto flex-1 min-h-0">
<div className="grid overflow-y-auto flex-1 gap-6 py-4 min-h-0">
{/* Appearance Section */}
<div className="space-y-4">
<Label className="text-base font-medium">Appearance</Label>
@@ -172,7 +172,7 @@ export function SettingsDialog({ isOpen, onClose }: SettingsDialogProps) {
{/* Default Browser Section */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<div className="flex justify-between items-center">
<Label className="text-base font-medium">Default Browser</Label>
<Badge variant={isDefaultBrowser ? "default" : "secondary"}>
{isDefaultBrowser ? "Active" : "Inactive"}
+7
View File
@@ -15,8 +15,15 @@ const Toaster = ({ ...props }: ToasterProps) => {
"--normal-bg": "var(--popover)",
"--normal-text": "var(--popover-foreground)",
"--normal-border": "var(--border)",
zIndex: 99999,
} as React.CSSProperties
}
toastOptions={{
style: {
zIndex: 99999,
pointerEvents: "auto",
},
}}
{...props}
/>
);
+9 -9
View File
@@ -47,17 +47,17 @@ export function UpdateNotificationComponent({
};
return (
<div className="flex flex-col gap-3 p-4 max-w-md bg-background border border-border rounded-lg shadow-lg">
<div className="flex items-start justify-between gap-2">
<div className="flex flex-col gap-3 p-4 max-w-md rounded-lg border shadow-lg bg-background border-border">
<div className="flex gap-2 justify-between items-start">
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2">
<div className="flex gap-2 items-center">
<span className="font-semibold text-foreground">
{browserDisplayName} Update Available
</span>
<Badge
variant={notification.is_stable_update ? "default" : "secondary"}
>
{notification.is_stable_update ? "Stable" : "Beta"}
{notification.is_stable_update ? "Stable" : "Nightly"}
</Badge>
</div>
<div className="text-sm text-muted-foreground">
@@ -71,20 +71,20 @@ export function UpdateNotificationComponent({
onClick={async () => {
await onDismiss(notification.id);
}}
className="h-6 w-6 p-0 shrink-0"
className="p-0 w-6 h-6 shrink-0"
>
<FaTimes className="h-3 w-3" />
<FaTimes className="w-3 h-3" />
</Button>
</div>
<div className="flex items-center gap-2">
<div className="flex gap-2 items-center">
<Button
onClick={handleUpdateClick}
disabled={isUpdating}
size="sm"
className="flex items-center gap-2"
className="flex gap-2 items-center"
>
<FaDownload className="h-3 w-3" />
<FaDownload className="w-3 h-3" />
Update
</Button>
<Button
+60
View File
@@ -0,0 +1,60 @@
"use client";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { useEffect, useState } from "react";
export function WindowDragArea() {
const [isMacOS, setIsMacOS] = useState(false);
useEffect(() => {
// Check if we're on macOS using user agent detection
const checkPlatform = () => {
const userAgent = navigator.userAgent.toLowerCase();
setIsMacOS(userAgent.includes("mac"));
};
checkPlatform();
}, []);
const handleMouseDown = (e: React.MouseEvent) => {
// Only handle left mouse button
if (e.button !== 0) return;
// Start dragging asynchronously
const startDrag = async () => {
try {
const window = getCurrentWindow();
await window.startDragging();
} catch (error) {
console.error("Failed to start window dragging:", error);
}
};
void startDrag();
};
// Only render on macOS
if (!isMacOS) {
return null;
}
return (
<div
className="fixed top-0 right-0 left-0 z-50 h-8 cursor-move"
style={{
// Ensure it's above all other content
zIndex: 9999,
// Make it transparent but still capture mouse events
backgroundColor: "transparent",
// Prevent text selection during drag
userSelect: "none",
WebkitUserSelect: "none",
}}
onMouseDown={handleMouseDown}
// Prevent context menu
onContextMenu={(e) => {
e.preventDefault();
}}
/>
);
}
@@ -135,6 +135,10 @@ export function useAppUpdateNotifications() {
id: "app-update",
duration: Number.POSITIVE_INFINITY, // Persistent until user action
position: "top-left",
style: {
zIndex: 99999, // Ensure app updates appear above dialogs
pointerEvents: "auto", // Ensure app updates remain interactive
},
},
);
}, [
+4 -2
View File
@@ -232,8 +232,10 @@ export function useUpdateNotifications(
id: notification.id,
duration: Number.POSITIVE_INFINITY, // Persistent until user action
position: "top-right",
// Remove transparent styling to fix background issue
style: undefined,
style: {
zIndex: 99999, // Ensure notifications appear above dialogs
pointerEvents: "auto", // Ensure notifications remain interactive
},
},
);
}
+6
View File
@@ -116,6 +116,8 @@ export function showToast(props: ToastProps & { id?: string }) {
border: "none",
boxShadow: "none",
padding: 0,
zIndex: 99999,
pointerEvents: "auto",
},
});
} else if (props.type === "error") {
@@ -127,6 +129,8 @@ export function showToast(props: ToastProps & { id?: string }) {
border: "none",
boxShadow: "none",
padding: 0,
zIndex: 99999,
pointerEvents: "auto",
},
});
} else {
@@ -138,6 +142,8 @@ export function showToast(props: ToastProps & { id?: string }) {
border: "none",
boxShadow: "none",
padding: 0,
zIndex: 99999,
pointerEvents: "auto",
},
});
}
+20
View File
@@ -123,3 +123,23 @@
@apply bg-background text-foreground;
}
}
/* Ensure Sonner toasts appear above all dialogs and remain interactive */
.toaster,
[data-sonner-toaster] {
z-index: 99999 !important;
pointer-events: auto !important;
}
[data-sonner-toast] {
z-index: 99999 !important;
pointer-events: auto !important;
}
/* Ensure toast buttons and interactive elements work */
[data-sonner-toast] button,
[data-sonner-toast] [role="button"],
[data-sonner-toast] input,
[data-sonner-toast] select {
pointer-events: auto !important;
}
+13
View File
@@ -0,0 +1,13 @@
module.exports = {
darkMode: "class",
theme: {
extend: {
colors: {
black: "#000000",
},
backgroundColor: {
dark: "#000000",
},
},
},
};