experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(mobile): enable HMR by removing default custom-protocol feature + update docs

Remove custom-protocol from default Cargo.toml tauri dependency — dev builds
now respect devUrl for HMR, release builds explicitly add --features custom-protocol.
Rewrite DEVELOPMENT.md iOS section with accurate two-pathway documentation.
Fix dev-setup.sh to auto-build libraries if missing. Clean stale devUrl from
tauri.conf.json.

+136 -181
+69 -151
DEVELOPMENT.md
··· 412 412 413 413 Mobile development uses the separate `peek-save` app in `backend/tauri-mobile/`. 414 414 415 - **CRITICAL - Build with Xcode GUI for iOS:** 416 - - NEVER run `xcodebuild` commands from terminal for final builds 417 - - Use Xcode GUI (Product → Build, Product → Run) for reliable builds 418 - 419 415 **CRITICAL - Do NOT run `xcodegen generate`:** 420 416 - The Xcode project has custom settings that xcodegen overwrites 421 417 422 - ### Quick Start (One Command) 418 + ### Two Build Pathways 423 419 424 - The easiest way to set up mobile development with sync testing: 420 + There are exactly two ways to build and deploy the iOS app. Always use these — never ad-hoc commands. 425 421 426 - ```bash 427 - cd backend/tauri-mobile 422 + #### Pathway 1: Simulator + HMR (frontend development) 428 423 429 - # First time: build both debug and release Rust libraries 430 - npm run build # Build frontend 431 - cd src-tauri 432 - cargo build --target aarch64-apple-ios-sim # Debug (simulator) 433 - cargo build --target aarch64-apple-ios --release # Release (device) 434 - cd .. 424 + For CSS/TSX changes that hot-reload instantly without rebuilding: 435 425 436 - # Start everything (servers, configure iOS, seed test data, open Xcode) 437 - npm run dev:ios 426 + ```bash 427 + # From repo root: 428 + yarn mobile:ios:dev 438 429 ``` 439 430 440 - `npm run dev:ios` does all of this automatically: 441 - 1. Resets server data for a clean slate 442 - 2. Starts backend server on a random port (10000-19999) 443 - 3. Starts frontend dev server on port 1420 444 - 4. Configures iOS simulator with server URL and API key 445 - 5. Copies both debug and release Rust libraries 446 - 6. Opens Xcode 447 - 7. Seeds test data (3 items on server, 3 on iOS) 431 + This runs `dev-ios-sim.sh` which: 432 + 1. Patches `tauri.conf.json` with a random-port `devUrl` (restores on exit) 433 + 2. Bumps `BUILD_NUMBER` (displayed as `vNNNN` in app footer) 434 + 3. Rebuilds Rust library WITHOUT `custom-protocol` feature (so app loads from devUrl) 435 + 4. Runs `xcodebuild` for simulator 436 + 5. Installs and launches on simulator 437 + 6. Starts vite HMR server — CSS/TSX changes appear instantly 448 438 449 - ### Available npm Scripts 439 + After the initial build, edit frontend files and changes appear live. Stop with Ctrl+C. 450 440 451 - ```bash 452 - # Development 453 - npm run dev:ios:sim # Hot reload dev - clears libapp.a, starts vite, opens Xcode 454 - npm run dev:ios # Full dev setup (servers + config + seed + Xcode) 455 - npm run xcode # Just copy libraries and open Xcode 456 - npm run seed # Seed test data (needs SERVER_URL and API_KEY env vars) 457 - npm run reset:server # Delete server data directory 441 + #### Pathway 2: Device release (testing on physical device) 458 442 459 - # Building 460 - npm run build # Build frontend (tsc + vite) 461 - npm run build:ios # Build frontend + debug Rust library (simulator) 462 - npm run build:ios:sim:release # Build frontend + release Rust library (simulator) 463 - npm run build:ios:release # Build frontend + release Rust library (device) 443 + For testing on a connected USB device: 464 444 465 - # Testing 466 - npm run test # Run integration tests 467 - npm run test:verbose # Run tests with verbose output 445 + ```bash 446 + # From repo root: 447 + yarn mobile:ios:xcodebuild:device:full # build + xcodebuild + install 448 + yarn mobile:ios:device:launch # launch on device 468 449 ``` 469 450 470 - ### iOS Build Process (Manual) 451 + This builds with `--features custom-protocol` so the app uses bundled assets (no dev server needed). 471 452 472 - If you need to build manually instead of using `npm run dev:ios`: 453 + ### Why `custom-protocol` Matters 473 454 474 - ```bash 475 - # 1. Build frontend 476 - cd backend/tauri-mobile && npm install && npm run build 455 + The `custom-protocol` Cargo feature controls whether the app loads from bundled assets or a dev server URL: 477 456 478 - # 2. Build debug library (for simulator) 479 - cd src-tauri 480 - cargo tauri build --target aarch64-apple-ios-sim --debug 481 - mkdir -p gen/apple/Externals/arm64/Debug 482 - cp target/aarch64-apple-ios-sim/debug/deps/libpeek_save_lib.a gen/apple/Externals/arm64/Debug/libapp.a 457 + - **Without** `custom-protocol` (simulator/HMR): app loads from `devUrl` in `tauri.conf.json` → connects to vite HMR server 458 + - **With** `custom-protocol` (device/release): app uses bundled assets from `frontendDist` → standalone, no server needed 483 459 484 - # 3. Build release library (for device) 485 - cargo tauri build --target aarch64-apple-ios 486 - mkdir -p gen/apple/Externals/arm64/Release 487 - cp target/aarch64-apple-ios/release/deps/libpeek_save_lib.a gen/apple/Externals/arm64/Release/libapp.a 460 + The default `Cargo.toml` has NO features enabled. `build-release.sh` explicitly adds `--features custom-protocol`. This separation is critical — do not add `custom-protocol` to the default dependency features or HMR will break. 461 + 462 + ### Build Commands (from repo root) 463 + 464 + ```bash 465 + # Simulator + HMR (preferred for frontend work) 466 + yarn mobile:ios:dev # Full HMR dev session (recommended) 488 467 489 - # 4. Create assets symlink (if missing) 490 - ln -s ../../../dist gen/apple/assets 468 + # Simulator without HMR (one-off testing) 469 + yarn mobile:ios:build [--force] # Build Rust library (debug, simulator) 470 + yarn mobile:ios:xcodebuild # Build Xcode project 471 + yarn mobile:ios:xcodebuild:install # Install on simulator 472 + yarn mobile:ios:sim:launch # Launch app 473 + yarn mobile:ios:xcodebuild:full # All of the above in one command 491 474 492 - # 5. Open Xcode and build from GUI 493 - open gen/apple/peek-save.xcodeproj 475 + # Device release 476 + yarn mobile:ios:build:release [--force] # Build Rust library (release, device) 477 + yarn mobile:ios:xcodebuild:device # Build Xcode project for device 478 + yarn mobile:ios:device:run # Install and launch on device 479 + yarn mobile:ios:xcodebuild:device:full # All of the above in one command 480 + yarn mobile:ios:device:launch # Launch (if already installed) 494 481 ``` 495 482 496 483 ### Testing Bidirectional Sync ··· 515 502 5. After sync, both server and iOS should have 6 items 516 503 517 504 **Gotchas:** 518 - - The `gen/apple/assets` symlink must exist or Xcode fails with "No such file or directory" 519 - - Debug scheme = simulator, Release scheme = device 520 - - If Rust code changes, rebuild the library and copy again 521 - - The "Build Rust Code" pre-build script in Xcode can hang indefinitely - pre-building avoids this 522 - - iOS simulator can't reach `localhost` - use Mac's IP address (dev:ios handles this automatically) 523 - 524 - **Critical Build Pipeline Issues:** 525 - - **Hot reload requires `dev:ios:sim`** - Use `npm run dev:ios:sim` for hot reload development. This clears `libapp.a` so Xcode rebuilds in dev mode, connecting to the vite server at `localhost:1420`. Without this, the app uses bundled assets. 526 - - **Xcode rebuild alone doesn't recompile Tauri** - When `tauri.conf.json` changes, you MUST run `npm run build:ios` to rebuild the Rust code. Just rebuilding in Xcode uses stale `libapp.a`. 527 - - **Invalid tauri.conf.json causes silent failures** - If the config has invalid properties, Tauri build fails but Xcode may still "succeed" using old artifacts. Always check `npm run build:ios` output for errors like "Additional properties are not allowed". 528 - - **Multiple xcodeproj files exist** - With agent workspaces, there may be many copies at `~/misc/mpeek/*/backend/tauri-mobile/src-tauri/gen/apple/peek-save.xcodeproj`. Verify you're opening the correct one (check Xcode window title or File → Project Settings). 529 - - **disableInputAccessoryView not in Tauri 2.9.x** - The config option to hide iOS keyboard accessory bar is documented in the schema but not implemented in stable Tauri 2.9. Requires newer version or native Swift workaround. 505 + - Xcode scheme is `peek-save_iOS` — all xcodebuild commands use this 506 + - All xcodebuild outputs go to `/tmp/peek-xcodebuild` (derivedDataPath) 507 + - `tauri.conf.json` should NOT have `devUrl` or `beforeDevCommand` checked in — `dev-ios-sim.sh` patches these temporarily and restores on exit 508 + - If Rust code changes during HMR, stop vite (Ctrl+C), restart `yarn mobile:ios:dev` 509 + - `cargo tauri ios dev` is broken on Apple Silicon (passes `ARCHS=x86_64`) — use `yarn mobile:ios:dev` instead which bypasses it 530 510 531 511 ### iOS Build System Architecture 532 512 533 - **⚠️ CRITICAL: The `custom-protocol` Cargo feature is REQUIRED for production builds.** 534 - 535 - Without this feature, the app tries to connect to `localhost` instead of using bundled assets, causing a "failed to request tauri://localhost" error and iOS local network permission prompts. 513 + #### Why `cargo build --lib` Instead of `cargo tauri build` 536 514 537 - ```toml 538 - # backend/tauri-mobile/src-tauri/Cargo.toml 539 - tauri = { version = "2", features = ["custom-protocol"] } 540 - ``` 515 + `cargo tauri build` fails on iOS because Swift FFI symbols (`webview_plugin_open`, `webview_plugin_close`) are only available at Xcode's final link stage. Our workaround: 541 516 542 - **Why this happens:** Tauri's build system sets `cargo:dev=true` or `cargo:dev=false` based on the `custom-protocol` feature: 543 - - **With** `custom-protocol` → `dev=false` → uses bundled assets (production) 544 - - **Without** `custom-protocol` → `dev=true` → tries to connect to localhost (dev mode) 517 + 1. `cargo build --lib` — build only the Rust library 518 + 2. Copy `libapp.a` to Xcode's expected location 519 + 3. Copy frontend assets to `gen/apple/assets/` 520 + 4. Let xcodebuild do the final linking with Swift code 545 521 546 - When using `cargo build` directly (instead of `cargo tauri build`), you MUST have this feature enabled, otherwise the app defaults to dev mode. 547 - 548 - ### Debug vs Release Build Separation 549 - 550 - The build system maintains strict separation between debug (simulator) and release (device) builds: 522 + #### Debug vs Release Build Separation 551 523 552 524 | Aspect | Debug (Simulator) | Release (Device) | 553 525 |--------|-------------------|------------------| 554 526 | Target | `aarch64-apple-ios-sim` | `aarch64-apple-ios` | 555 527 | Profile | `dev` (unoptimized) | `release` (optimized) | 528 + | Features | none (uses devUrl) | `custom-protocol` (uses bundled assets) | 556 529 | Cache | `ios-cache/debug/` | `ios-cache/release/` | 557 530 | Xcode Externals | `Externals/arm64/Debug/` | `Externals/arm64/Release/` | 558 531 | Build script | `build-ios.sh` | `build-release.sh` | 559 532 | yarn command | `yarn mobile:ios:build` | `yarn mobile:ios:build:release` | 560 533 561 - **Cache location:** Caches are stored at the git repo root level (`~/misc/mpeek/tmp/ios-cache/`) and shared across agent workspaces. Each cache contains: 562 - - `libapp.a` - The compiled Rust library 563 - - `checksum.txt` - Hash of source files for cache invalidation 564 - 565 - **Cache invalidation:** The cache hash includes: 566 - - `Cargo.toml`, `Cargo.lock` - Dependencies 567 - - `tauri.conf.json` - Tauri configuration 568 - - `build.rs` - Build script 569 - - `src/*.rs` - All Rust source files 570 - 571 - ### Build Commands (from repo root) 572 - 573 - ```bash 574 - # Debug for simulator 575 - yarn mobile:ios:build # Build Rust library 576 - yarn mobile:ios:xcodebuild # Build Xcode project 577 - yarn mobile:ios:xcodebuild:install # Install on simulator 578 - yarn mobile:ios:sim:launch # Launch app 579 - 580 - # Release for device 581 - yarn mobile:ios:build:release # Build Rust library 582 - yarn mobile:ios:xcodebuild:device # Build Xcode project 583 - yarn mobile:ios:device:run # Install and launch on device 534 + #### Build Number 584 535 585 - # Full flows 586 - yarn mobile:ios:xcodebuild:full # Debug: build + xcode + install 587 - yarn mobile:ios:xcodebuild:device:full # Release: build + xcode + install 588 - ``` 536 + `backend/tauri-mobile/BUILD_NUMBER` is a plain integer. `vite.config.ts` reads it as `__BUILD_NUMBER__` and displays `vNNNN` in the app footer. `dev-ios-sim.sh` auto-increments it on every HMR session start. Always check the build number in the app footer to confirm your changes deployed. 589 537 590 - ### Troubleshooting: "localhost" Error on Device 538 + #### Cache 591 539 592 - If the app shows "failed to request tauri://localhost" or asks for local network permissions: 540 + Caches are at the repo root level (`tmp/ios-cache/`) and shared across agent workspaces. The cache hash includes `Cargo.toml`, `Cargo.lock`, `tauri.conf.json`, `build.rs`, and `src/*.rs`. Use `--force` to bypass cache. 593 541 594 - 1. **Verify `custom-protocol` feature** is in `Cargo.toml`: 595 - ```bash 596 - grep custom-protocol backend/tauri-mobile/src-tauri/Cargo.toml 597 - ``` 542 + #### Troubleshooting: "localhost" Error on Device 598 543 599 - 2. **Clear ALL caches** (shared cache is at repo root, not workspace): 600 - ```bash 601 - rm -rf ~/misc/mpeek/tmp/ios-cache/release 602 - rm -rf backend/tauri-mobile/src-tauri/target/aarch64-apple-ios/release 603 - ``` 544 + If the app shows "failed to request tauri://localhost" on device, the `custom-protocol` feature is missing from the build. Verify `build-release.sh` passes `--features custom-protocol` and rebuild: 604 545 605 - 3. **Rebuild from scratch:** 606 - ```bash 607 - yarn mobile:ios:build:release 608 - ``` 609 - 610 - 4. **Copy to Debug location** (Xcode looks in Debug/ even for release builds): 611 - ```bash 612 - cp backend/tauri-mobile/src-tauri/gen/apple/Externals/arm64/Release/libapp.a \ 613 - backend/tauri-mobile/src-tauri/gen/apple/Externals/arm64/Debug/libapp.a 614 - ``` 615 - 616 - 5. **Rebuild Xcode and install:** 617 - ```bash 618 - yarn mobile:ios:xcodebuild:device 619 - yarn mobile:ios:device:run 620 - ``` 621 - 622 - ### Why We Use `cargo build --lib` Instead of `cargo tauri build` 623 - 624 - The standard `cargo tauri build` command fails on iOS because of Swift FFI symbols (`webview_plugin_open`, `webview_plugin_close`) that are defined in Swift code and only available at Xcode's final link stage. 625 - 626 - Our workaround: 627 - 1. Build only the lib target: `cargo build --lib --target aarch64-apple-ios` 628 - 2. Copy the library to Xcode's expected location 629 - 3. Copy frontend assets manually (normally done by `cargo tauri build`) 630 - 4. Let Xcode do the final linking with Swift code 631 - 632 - This requires the `custom-protocol` feature since we're bypassing Tauri's build orchestration. 546 + ```bash 547 + yarn mobile:ios:build:release --force 548 + yarn mobile:ios:xcodebuild:device 549 + yarn mobile:ios:device:run 550 + ``` 633 551 634 552 ## Server Backend (Webhook API) 635 553
+1 -1
backend/tauri-mobile/BUILD_NUMBER
··· 1 - 1034 1 + 1037
+47 -22
backend/tauri-mobile/dev-ios-sim.sh
··· 1 1 #!/bin/bash 2 - # Start iOS simulator dev environment with a random available port. 2 + # Start iOS simulator dev environment with HMR. 3 3 # Usage: ./dev-ios-sim.sh 4 4 # 5 - # This avoids port conflicts by picking a fresh port each run, 6 - # patching tauri.conf.json temporarily, and restoring on exit. 5 + # Patches tauri.conf.json with devUrl, rebuilds Rust + frontend, 6 + # deploys to simulator, then starts vite for hot module replacement. 7 + # First run is slow (Rust rebuild), subsequent runs reuse cache. 7 8 8 9 set -e 9 - cd "$(dirname "$0")" 10 + SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 11 + CONF="$SCRIPT_DIR/src-tauri/tauri.conf.json" 10 12 11 13 # Pick a random available port 12 14 PORT=$(python3 -c "import socket; s=socket.socket(); s.bind(('',0)); print(s.getsockname()[1]); s.close()") 13 15 echo "[dev] Using port $PORT" 14 16 15 - # Patch tauri.conf.json: add devUrl and beforeDevCommand 16 - CONF=src-tauri/tauri.conf.json 17 + # Save original tauri.conf.json for restoration 18 + cp "$CONF" "$CONF.bak" 17 19 18 - # Save original for restoration 19 - cp "$CONF" "$CONF.bak" 20 + cleanup() { 21 + echo "" 22 + echo "[dev] Restoring tauri.conf.json..." 23 + mv "$CONF.bak" "$CONF" 24 + echo "[dev] Done." 25 + } 26 + trap cleanup EXIT 20 27 21 - # Add devUrl and beforeDevCommand to the build section 28 + # Patch tauri.conf.json with devUrl 22 29 python3 -c " 23 - import json, sys 30 + import json 24 31 with open('$CONF') as f: 25 32 c = json.load(f) 26 33 c['build']['devUrl'] = 'http://localhost:$PORT' 27 - c['build']['beforeDevCommand'] = 'DEV_PORT=$PORT npm run dev' 28 34 with open('$CONF', 'w') as f: 29 35 json.dump(c, f, indent=2) 30 36 f.write('\n') 31 37 " 38 + echo "[dev] Patched tauri.conf.json with devUrl=http://localhost:$PORT" 39 + 40 + # Bump build number 41 + BUILD_FILE="$SCRIPT_DIR/BUILD_NUMBER" 42 + BUILD_NUM=$(($(cat "$BUILD_FILE") + 1)) 43 + echo "$BUILD_NUM" > "$BUILD_FILE" 44 + echo "[dev] Build number: v$BUILD_NUM" 32 45 33 - echo "[dev] Patched tauri.conf.json with devUrl=http://localhost:$PORT" 46 + # Rebuild Rust library (picks up devUrl from tauri.conf.json) 47 + # Uses --force to ensure config change is picked up 48 + echo "[dev] Building Rust library with devUrl..." 49 + cd "$SCRIPT_DIR" && ./build-ios.sh --force 34 50 35 - # Restore tauri.conf.json on exit (any signal) 36 - cleanup() { 37 - echo "" 38 - echo "[dev] Restoring tauri.conf.json..." 39 - mv "$CONF.bak" "$CONF" 40 - echo "[dev] Done." 41 - } 42 - trap cleanup EXIT 51 + # Build with xcodebuild 52 + echo "[dev] Running xcodebuild..." 53 + rm -rf /tmp/peek-xcodebuild 54 + cd "$SCRIPT_DIR/src-tauri/gen/apple" && xcodebuild \ 55 + -scheme peek-save_iOS \ 56 + -configuration Debug \ 57 + -sdk iphonesimulator \ 58 + -derivedDataPath /tmp/peek-xcodebuild \ 59 + -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \ 60 + clean build 2>&1 | tail -5 43 61 44 - # Run cargo tauri ios dev (builds Rust in dev mode pointing to devUrl, starts vite, opens Xcode) 45 - cd src-tauri && cargo tauri ios dev "iPhone 17 Pro" 62 + # Install and launch 63 + echo "[dev] Installing to simulator..." 64 + xcrun simctl install booted '/tmp/peek-xcodebuild/Build/Products/debug-iphonesimulator/Peek Save.app' 65 + xcrun simctl terminate booted com.dietrich.peek-mobile 2>/dev/null || true 66 + xcrun simctl launch booted com.dietrich.peek-mobile 67 + echo "[dev] App launched, starting HMR dev server on port $PORT..." 68 + 69 + # Start vite dev server (blocks — HMR active until Ctrl+C) 70 + cd "$SCRIPT_DIR" && DEV_PORT=$PORT npx vite --port $PORT
+14 -4
backend/tauri-mobile/dev-setup.sh
··· 58 58 echo " App not installed yet - settings will need manual config on first run" 59 59 fi 60 60 61 - # Copy libraries and open Xcode 61 + # Build and copy libraries 62 62 echo "" 63 - echo "Copying libraries..." 64 - cp src-tauri/target/aarch64-apple-ios-sim/debug/deps/libpeek_save_lib.a src-tauri/gen/apple/Externals/arm64/Debug/libapp.a 65 - cp src-tauri/target/aarch64-apple-ios/release/deps/libpeek_save_lib.a src-tauri/gen/apple/Externals/arm64/Release/libapp.a 63 + echo "Building Rust libraries..." 64 + if [ ! -f src-tauri/target/aarch64-apple-ios-sim/debug/libpeek_save_lib.a ]; then 65 + echo " Building debug library (simulator)..." 66 + ./build-ios.sh 67 + else 68 + echo " Debug library exists (use ./build-ios.sh --force to rebuild)" 69 + fi 70 + if [ ! -f src-tauri/target/aarch64-apple-ios/release/libpeek_save_lib.a ]; then 71 + echo " Building release library (device)..." 72 + ./build-release.sh 73 + else 74 + echo " Release library exists (use ./build-release.sh --force to rebuild)" 75 + fi 66 76 67 77 echo "Opening Xcode..." 68 78 open src-tauri/gen/apple/peek-save.xcodeproj
+1 -1
backend/tauri-mobile/src-tauri/Cargo.toml
··· 19 19 cc = "1.0" 20 20 21 21 [dependencies] 22 - tauri = { version = "2", features = ["custom-protocol"] } 22 + tauri = { version = "2", features = [] } 23 23 tauri-plugin-opener = "2" 24 24 serde = { version = "1", features = ["derive"] } 25 25 serde_json = "1"
+1 -1
backend/tauri-mobile/src-tauri/gen/apple/assets/assets/index-ChkCr5Ch.js backend/tauri-mobile/src-tauri/gen/apple/assets/assets/index-DbCPW-hJ.js
··· 12 12 ${F}${mt} `,il=r+ge+j;Y(il),requestAnimationFrame(()=>{if(ct.current){const yl=W+ge.length;ct.current.selectionStart=yl,ct.current.selectionEnd=yl}})}};return z.useEffect(()=>{const U=r=>ce(r.clientY),J=r=>{r.touches.length===1&&ce(r.touches[0].clientY)},W=()=>b();return document.addEventListener("mousemove",U),document.addEventListener("mouseup",W),document.addEventListener("touchmove",J,{passive:!0}),document.addEventListener("touchend",W),()=>{document.removeEventListener("mousemove",U),document.removeEventListener("mouseup",W),document.removeEventListener("touchmove",J),document.removeEventListener("touchend",W)}},[Ut]),z.useEffect(()=>{if(!k)return;const U=setTimeout(()=>{if(ct.current){ct.current.focus();const J=ct.current.value.length;ct.current.selectionStart=J,ct.current.selectionEnd=J}},50);return()=>clearTimeout(U)},[]),s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"undo-redo-buttons",children:[s.jsx("button",{type:"button",onClick:le,disabled:Qt.current<=0,title:"Undo",children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("polyline",{points:"1 4 1 10 7 10"}),s.jsx("path",{d:"M3.51 15a9 9 0 1 0 2.13-9.36L1 10"})]})}),s.jsx("button",{type:"button",onClick:yt,disabled:Qt.current>=St.current.length-1,title:"Redo",children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("polyline",{points:"23 4 23 10 17 10"}),s.jsx("path",{d:"M20.49 15a9 9 0 1 1-2.13-9.36L23 10"})]})})]}),s.jsxs("div",{className:"resizable-input-wrapper",ref:V,style:$!=null?{height:`${je}px`,minHeight:`${Ut}px`}:{minHeight:`${Ut}px`},children:[s.jsx("textarea",{ref:ct,className:"resizable-input-textarea",value:E,onChange:U=>{const J=U.target.value.replace(/^(\s*(?:[-*+]|\d+\.))\s{2,}/gm,"$1 ");Y(J),gt&&gt(J)},onFocus:()=>{requestAnimationFrame(()=>window.scrollTo(0,0))},onKeyDown:M,placeholder:B,autoCapitalize:H,autoCorrect:T,autoComplete:"off",spellCheck:T==="on"}),rt&&s.jsx(Kc,{show:E.length>0,onClear:()=>Y(""),className:"textarea-clear"}),s.jsx("div",{className:"drag-handle",onMouseDown:U=>{U.preventDefault(),Kt(U.clientY)},onTouchStart:U=>{Kt(U.touches[0].clientY)},children:s.jsx("div",{className:"drag-handle-bar"})})]})]})},pm=()=>{const[E,Y]=z.useState(0),B=z.useRef(0);return z.useEffect(()=>{const v=window.visualViewport;if(!v)return;const q=()=>{const k=Math.max(0,window.innerHeight-v.height);k===0?(B.current=0,Y(0)):(B.current=Math.max(B.current,k),Y(B.current))};return v.addEventListener("resize",q),v.addEventListener("scroll",q),()=>{v.removeEventListener("resize",q),v.removeEventListener("scroll",q)}},[]),E};function Sm(){z.useEffect(()=>{const c=Math.floor(Math.random()*360);document.documentElement.style.setProperty("--dev-bg-light",`hsl(${c}, 80%, 85%)`),document.documentElement.style.setProperty("--dev-bg-dark",`hsl(${c}, 15%, 12%)`)},[]);const[E,Y]=z.useState("all"),[B,v]=z.useState([]),[q,k]=z.useState([]),[rt,gt]=z.useState([]),[H,T]=z.useState([]),[$,Q]=z.useState([]),[V,ct]=z.useState(null),[wt,Ht]=z.useState(""),[ee,St]=z.useState(new Set),[Qt,At]=z.useState([]),[Xt,le]=z.useState(""),[yt,lt]=z.useState(null),[It,Te]=z.useState(""),[ve,ie]=z.useState(new Set),[Ut,je]=z.useState(""),[Kt,ce]=z.useState(null),[b,M]=z.useState(new Set),[U,J]=z.useState(""),[W,r]=z.useState(null),[j,O]=z.useState(new Set),[R,Z]=z.useState(""),[F,nt]=z.useState(""),[zt,mt]=z.useState(new Set),[ae,ge]=z.useState(!1),[il,yl]=z.useState(""),pl=300,[Sl,hn]=z.useState(null),[ou,mn]=z.useState(!1),[ru,Da]=z.useState(!1),[vn,du]=z.useState(!1),[Ma,ye]=z.useState(null),[bl,Oa]=z.useState(new Set),[qe,xl]=z.useState(""),gi=z.useRef(null),$l=z.useRef(null),gn=z.useRef(null),[yn,Tl]=z.useState(null),[Lt,Ye]=z.useState(()=>localStorage.getItem("searchText")||""),[Bt,hu]=z.useState(()=>{const c=localStorage.getItem("selectedFilterTags");return c?new Set(JSON.parse(c)):new Set}),[Ua,Jc]=z.useState(()=>localStorage.getItem("sortOrder")||"newest"),[El,pn]=z.useState(()=>{const c=localStorage.getItem("filterTagsHeight");return c?parseInt(c,10):116}),Ra=z.useRef(null),Ge=z.useRef(!1),jl=z.useRef(!1),Il=z.useRef(0),yi=z.useRef(0),[Sn,bn]=z.useState(null),_l=z.useRef(null),qt=(c,h="success")=>{_l.current&&clearTimeout(_l.current),bn({message:c,type:h}),_l.current=setTimeout(()=>bn(null),3e3)},[xn,Al]=z.useState(null),[Pt,Me]=z.useState(null),[Tn,mu]=z.useState(!1),[pi,tl]=z.useState(!1),[Nt,se]=z.useState(""),[el,En]=z.useState(""),[kc,Si]=z.useState(""),[wa,Pl]=z.useState(""),[vu,zl]=z.useState(!1),[cl,Ha]=z.useState(!1),[_e,Ct]=z.useState(!1),[La,tt]=z.useState(null),[sl,Nl]=z.useState(null),[jn,bi]=z.useState(null),[Dt,_n]=z.useState(null),[Cl,Dl]=z.useState(""),[Qe,pe]=z.useState(!1),[ta,xi]=z.useState("archive"),[ea,gu]=z.useState("archive"),Xe=pm(),Ml=z.useRef(null),Jt=z.useRef(null),[la,Ol]=z.useState("idle"),An=80,aa=300,yu=c=>{Ge.current=!0,jl.current=!0,Il.current=c,yi.current=Ra.current?.offsetHeight??El,document.body.style.userSelect="none",document.body.style.cursor="ns-resize"};z.useEffect(()=>{const c=D=>{if(!Ge.current)return;const pt=D-Il.current,at=Math.max(71,yi.current+pt);pn(at)},h=D=>c(D.clientY),N=D=>{D.touches.length===1&&c(D.touches[0].clientY)},C=()=>{Ge.current&&(Ge.current=!1,jl.current=!1,document.body.style.userSelect="",document.body.style.cursor="",localStorage.setItem("filterTagsHeight",String(Math.round(El))))};return document.addEventListener("mousemove",h),document.addEventListener("mouseup",C),document.addEventListener("touchmove",N,{passive:!0}),document.addEventListener("touchend",C),()=>{document.removeEventListener("mousemove",h),document.removeEventListener("mouseup",C),document.removeEventListener("touchmove",N),document.removeEventListener("touchend",C)}},[El]),z.useEffect(()=>{localStorage.setItem("searchText",Lt)},[Lt]),z.useEffect(()=>{localStorage.setItem("selectedFilterTags",JSON.stringify(Array.from(Bt)))},[Bt]),z.useEffect(()=>{localStorage.setItem("sortOrder",Ua)},[Ua]),z.useEffect(()=>{},[]),z.useEffect(()=>{const c=async()=>{try{const D=await X("is_dark_mode");mu(D)}catch{const pt=window.matchMedia("(prefers-color-scheme: dark)");mu(pt.matches)}};c();const h=window.matchMedia("(prefers-color-scheme: dark)"),N=()=>c();h.addEventListener("change",N);const C=()=>{document.visibilityState==="visible"&&c()};return document.addEventListener("visibilitychange",C),()=>{h.removeEventListener("change",N),document.removeEventListener("visibilitychange",C)}},[]),z.useEffect(()=>{document.body.classList.toggle("dark",Tn)},[Tn]),z.useEffect(()=>{const c=()=>{Ze(),Ve(),Oe(),fe(),oe()},h=async()=>{try{await X("auto_sync_if_needed")}catch(C){console.log("Auto-sync check:",C)}};c(),Ti(),na(),Wc(),_i(),zn(),Nn(),ji(),h();const N=()=>{document.visibilityState==="visible"&&(c(),h())};return document.addEventListener("visibilitychange",N),()=>{document.removeEventListener("visibilitychange",N)}},[]),z.useEffect(()=>{let c;return(async()=>{c=await ym("webview:navigated",async N=>{const{itemId:C}=N.payload;try{await X("record_visit",{itemId:C,source:"webview",windowType:"embedded"})}catch(D){console.error("Failed to record webview visit:",D)}})})(),()=>{c&&c()}},[]),z.useEffect(()=>{const c=()=>{document.visibilityState==="visible"&&ae&&!F.trim()&&zt.size===0&&ge(!1)};return document.addEventListener("visibilitychange",c),()=>{document.removeEventListener("visibilitychange",c)}},[ae,F,zt]);const Ti=async()=>{try{const c=await X("get_webhook_url");c&&(se(c),En(c))}catch(c){console.error("Failed to load webhook URL:",c)}},na=async()=>{try{const c=await X("get_webhook_api_key");c&&(Si(c),Pl(c))}catch(c){console.error("Failed to load webhook API key:",c)}},Wc=async()=>{try{const c=await X("get_auto_sync");zl(c)}catch(c){console.error("Failed to load auto-sync setting:",c)}},Ei=async c=>{try{await X("set_auto_sync",{enabled:c}),zl(c)}catch(h){console.error("Failed to set auto-sync:",h)}},ji=async()=>{try{const c=await X("get_archive_tag");xi(c),gu(c)}catch(c){console.error("Failed to load archive tag:",c)}},pu=async()=>{try{await X("set_archive_tag",{tag:ea}),xi(ea)}catch(c){console.error("Failed to save archive tag:",c)}},_i=async()=>{try{const c=await X("get_last_sync");Nl(c)}catch(c){console.error("Failed to load last sync:",c)}},zn=async()=>{try{const c=await X("get_sync_status");bi(c),c.last_sync_time&&Nl(c.last_sync_time)}catch(c){console.error("Failed to load sync status:",c)}},Nn=async()=>{try{const c=await X("get_profile_info");_n(c),Dl("")}catch(c){console.error("Failed to load profile info:",c)}},ll=async c=>{console.log(`[Profile] setProfile called with: ${c}`);try{console.log("[Profile] Invoking set_profile command...");const h=await X("set_profile",{profileId:c});console.log("[Profile] set_profile returned:",h),_n(h),Dl(""),pe(!0)}catch(h){console.error("[Profile] Failed to set profile:",h),tt(`Failed: ${h}`),setTimeout(()=>tt(null),3e3)}},Cn=async()=>{try{await X("quit_app")}catch(c){console.error("Failed to quit:",c)}},Su=async()=>{try{await X("set_webhook_url",{url:el}),await X("set_webhook_api_key",{key:wa}),se(el),Si(wa),tt("Settings saved"),setTimeout(()=>tt(null),2e3)}catch(c){console.error("Failed to save webhook settings:",c),tt("Failed to save settings"),setTimeout(()=>tt(null),3e3)}},Ul=async()=>{if(!Nt){qt("Please configure server URL first","error");return}Ct(!0),qt("Syncing...");try{const c=await X("sync_all"),h=`Synced: ${c.pulled} pulled, ${c.pushed} pushed${c.conflicts>0?`, ${c.conflicts} conflicts`:""}`;qt(h),tt(h),await _i(),await zn(),Ze(),Ve(),Oe(),fe(),oe(),setTimeout(()=>tt(null),4e3)}catch(c){console.error("Failed to sync:",c);const h=`Sync failed: ${c}`;qt(h,"error"),tt(h),setTimeout(()=>tt(null),5e3)}finally{Ct(!1)}},ua=async()=>{if(!Nt){tt("Please save a server URL first"),setTimeout(()=>tt(null),3e3);return}Ct(!0),tt(null);try{const c=await X("pull_from_server"),h=`Pulled ${c.pulled} items${c.conflicts>0?`, ${c.conflicts} conflicts`:""}`;tt(h),await zn(),Ze(),Ve(),Oe(),fe(),oe(),setTimeout(()=>tt(null),4e3)}catch(c){console.error("Failed to pull:",c),tt(`Pull failed: ${c}`),setTimeout(()=>tt(null),5e3)}finally{Ct(!1)}},Ai=async()=>{if(!Nt){tt("Please save a server URL first"),setTimeout(()=>tt(null),3e3);return}Ct(!0),tt(null);try{const c=await X("push_to_server");tt(`Pushed ${c.pushed} items`),await zn(),setTimeout(()=>tt(null),4e3)}catch(c){console.error("Failed to push:",c),tt(`Push failed: ${c}`),setTimeout(()=>tt(null),5e3)}finally{Ct(!1)}},Ze=async()=>{try{const c=await X("get_saved_urls");v(c)}catch(c){console.error("Failed to load saved URLs:",c)}},Ve=async()=>{try{const c=await X("get_saved_texts");k(c)}catch(c){console.error("Failed to load saved texts:",c)}},Oe=async()=>{try{const c=await X("get_saved_tagsets");gt(c)}catch(c){console.error("Failed to load saved tagsets:",c)}},fe=async()=>{try{const c=await X("get_saved_images");T(c)}catch(c){console.error("Failed to load saved images:",c)}},oe=async()=>{try{const c=await X("get_tags_by_frecency");Q(c)}catch(c){console.error("Failed to load tags:",c)}},Ba=()=>Pt?wt!==Pt.url||JSON.stringify(Array.from(ee).sort())!==JSON.stringify(Pt.tags):!1,fl=()=>Pt?It!==Pt.content||JSON.stringify(Array.from(ve).sort())!==JSON.stringify(Pt.tags):!1,bu=()=>Pt?JSON.stringify(Array.from(b).sort())!==JSON.stringify(Pt.tags):!1,Dn=()=>Pt?JSON.stringify(Array.from(j).sort())!==JSON.stringify(Pt.tags):!1,zi=async c=>{$l.current?.focus(),ct(c.id),Ht(c.url),St(new Set(c.tags)),le(""),Me({url:c.url,tags:[...c.tags].sort()});try{const h=await X("get_tags_by_frecency_for_url",{url:c.url});At(h)}catch(h){console.error("Failed to load domain-boosted tags:",h),At($)}},Rl=()=>{ct(null),Ht(""),St(new Set),At([]),le(""),Me(null)},qa=()=>{Ba()?Al({type:"page"}):Rl()},Ni=async c=>{console.log("[Frontend] deleteUrl called for id:",c);try{await X("delete_url",{id:c}),console.log("[Frontend] delete_url invoke succeeded"),await Ze(),Rl()}catch(h){console.error("[Frontend] Failed to delete URL:",h)}},Se=c=>{const h=new Set(ee);h.has(c)?h.delete(c):h.add(c),St(h)},wl=()=>{const c=new Set(ee),h=Xt.split(",");let N=!1;for(const C of h){const D=C.trim().toLowerCase();D&&!c.has(D)&&(c.add(D),N=!0)}N&&St(c),le("")},Mn=async()=>{if(!V)return;const c=new Set(ee);if(Xt.trim()){for(const h of Xt.split(",").map(N=>N.trim().toLowerCase()).filter(N=>N.length>0))c.add(h);le("")}try{await X("update_url",{id:V,url:wt,tags:Array.from(c)}),await Ze(),await oe(),Rl(),qt("Page saved")}catch(h){console.error("[Frontend] Failed to update URL:",h),qt("Failed to save page","error")}},Ya=c=>{console.log("[toggleAddInputTag] toggling tag:",c);const h=new Set(zt);h.has(c)?h.delete(c):h.add(c),console.log("[toggleAddInputTag] new tags:",Array.from(h)),mt(h)},xu=()=>{nt(""),mt(new Set),ge(!1),yl("")},Tu=()=>{const c=new Set(zt),h=il.split(",");for(const N of h){const C=N.trim().toLowerCase();C&&c.add(C)}mt(c),yl("")},Eu=()=>{gi.current?.click()},Ga=c=>{const h=c.target.files?.[0];if(!h)return;const N=new FileReader;N.onload=C=>{const D=C.target?.result;ye(D),Oa(new Set),xl("")},N.readAsDataURL(h),c.target.value=""},Qa=c=>{const h=new Set(bl);h.has(c)?h.delete(c):h.add(c),Oa(h)},ju=()=>{const c=new Set(bl),h=qe.split(",");for(const N of h){const C=N.trim().toLowerCase();C&&c.add(C)}Oa(c),xl("")},_u=()=>{ye(null),Oa(new Set),xl("")},Fc=async()=>{if(!Ma)return;const c=new Set(bl);if(qe.trim()){const h=qe.split(",");for(const N of h){const C=N.trim().toLowerCase();C&&c.add(C)}}try{const h=Ma.split(",")[1],N=Ma.split(";")[0].split(":")[1];await X("save_captured_image",{imageData:h,mimeType:N,tags:Array.from(c)}),_u(),await fe(),await oe()}catch(h){console.error("Failed to save captured image:",h)}},$c=async()=>{const c=F.trim(),h=new Set(zt);if(console.log("[saveAddInput] addInputTags:",Array.from(zt)),il.trim()){const D=il.split(",");for(const pt of D){const at=pt.trim().toLowerCase();at&&h.add(at)}}const N=Array.from(h);if(console.log("[saveAddInput] final tags to save:",N),c.startsWith("http://")||c.startsWith("https://"))try{await X("save_url",{url:c,tags:N}),xu(),await Ze(),await oe(),qt("Page saved")}catch(D){console.error("Failed to save URL:",D),qt("Failed to save page","error")}else if(c)try{console.log("[saveAddInput] Saving text with tags:",{content:c,tags:N}),await X("save_text",{content:c,tags:N}),xu(),await Ve(),await oe(),qt("Note saved")}catch(D){console.error("Failed to save text:",D),qt("Failed to save note","error")}else if(N.length>0)try{await X("save_tagset",{tags:N}),xu(),await Oe(),await oe(),qt("Tags saved")}catch(D){console.error("Failed to save tagset:",D),qt("Failed to save tags","error")}},Au=()=>{const c=F.trim();return c.startsWith("http://")||c.startsWith("https://")?"url":c?"text":zt.size>0?"tagset":null},Ic=c=>{$l.current?.focus(),lt(c.id),Te(c.content);const h=c.tags.length>0?c.tags:Ui(c.content);ie(new Set(h)),je(""),Me({content:c.content,tags:[...h].sort()})},On=()=>{lt(null),Te(""),ie(new Set),je(""),Me(null)},Ci=()=>{fl()?Al({type:"text"}):On()},Pc=c=>{const h=new Set(ve);h.has(c)?h.delete(c):h.add(c),ie(h)},ts=()=>{const c=Ut.trim().toLowerCase();c&&(ie(new Set(ve).add(c)),je(""))},ol=z.useRef(null),es=z.useCallback(c=>{!yt||!Pt||(ol.current&&clearTimeout(ol.current),c.trim()!==Pt.content&&(ol.current=setTimeout(async()=>{try{await X("update_text",{id:yt,content:c.trim(),tags:Array.from(ve)}),Me(h=>h?{...h,content:c.trim()}:null),await Ve()}catch(h){console.error("Auto-save failed:",h)}},500)))},[yt,Pt,ve]);z.useEffect(()=>()=>{ol.current&&clearTimeout(ol.current)},[yt]);const ls=async()=>{if(!yt)return;ol.current&&clearTimeout(ol.current);const c=new Set(ve);if(Ut.trim())for(const h of Ut.split(",").map(N=>N.trim().toLowerCase()).filter(N=>N.length>0))c.add(h);try{await X("update_text",{id:yt,content:It.trim(),tags:Array.from(c)}),await Ve(),await oe(),On(),qt("Note saved")}catch(h){console.error("Failed to update text:",h),qt("Failed to save note","error")}},as=async c=>{try{await X("delete_url",{id:c}),await Ve(),On()}catch(h){console.error("Failed to delete text:",h)}},ns=c=>{$l.current?.focus(),ce(c.id),M(new Set(c.tags)),J(""),Me({tags:[...c.tags].sort()})},ia=()=>{ce(null),M(new Set),J(""),Me(null)},Di=()=>{bu()?Al({type:"tagset"}):ia()},us=c=>{const h=new Set(b);h.has(c)?h.delete(c):h.add(c),M(h)},is=()=>{const c=new Set(b),h=U.split(",");for(const N of h){const C=N.trim().toLowerCase();C&&c.add(C)}M(c),J("")},Mi=async()=>{if(!Kt)return;const c=new Set(b);if(U.trim())for(const h of U.split(",").map(N=>N.trim().toLowerCase()).filter(N=>N.length>0))c.add(h);if(c.size===0){qt("At least one tag is required","error");return}try{await X("update_tagset",{id:Kt,tags:Array.from(c)}),await Oe(),await oe(),ia(),qt("Tags saved")}catch(h){console.error("Failed to update tagset:",h),qt("Failed to save tags","error")}},cs=async c=>{try{await X("delete_url",{id:c}),await Oe(),ia()}catch(h){console.error("Failed to delete tagset:",h)}},ss=c=>{$l.current?.focus(),r(c.id),O(new Set(c.tags)),Z(""),Me({tags:[...c.tags].sort()})},Un=()=>{r(null),O(new Set),Z(""),Me(null)},Oi=()=>{Dn()?Al({type:"image"}):Un()},fs=c=>{const h=new Set(j);h.has(c)?h.delete(c):h.add(c),O(h)},os=()=>{const c=new Set(j),h=R.split(",");for(const N of h){const C=N.trim().toLowerCase();C&&c.add(C)}O(c),Z("")},rs=async()=>{if(!W)return;const c=new Set(j);if(R.trim()){const h=R.split(",");for(const N of h){const C=N.trim().toLowerCase();C&&c.add(C)}}try{await X("update_image_tags",{id:W,tags:Array.from(c)}),await fe(),await oe(),Un(),qt("Image saved")}catch(h){console.error("Failed to update image:",h),qt("Failed to save image","error")}},Ui=c=>{const h=c.match(/#(\w+)/g);return h?h.map(N=>N.slice(1).toLowerCase()):[]},Rn=c=>{Y(E===c?"all":c)},wn=()=>{gn.current?.scrollTo({top:0,behavior:"smooth"})},Xa=c=>{if(V||yt||Kt||W||ae||_e||jl.current||document.body.dataset.resizing)return;const N=gn.current;N&&N.scrollTop<=0&&(Ml.current=c.touches[0].clientY,Jt.current=null,Ol("idle"))},Ri=c=>{if(Ml.current===null)return;if(jl.current||document.body.dataset.resizing){Ml.current=null,Jt.current=null,Ol("idle");return}c.touches[0].clientY-Ml.current>An?(c.preventDefault(),Jt.current===null?(Jt.current=Date.now(),Ol("pulling")):Date.now()-Jt.current>=aa&&Ol("ready")):(Jt.current=null,Ol("idle"))},wi=c=>{if(Ml.current===null)return;const h=c.changedTouches[0].clientY-Ml.current,N=la==="ready";Ml.current=null,Jt.current=null,Ol("idle"),h>An&&N&&Ul()};z.useEffect(()=>{const c=gn.current;if(c)return c.addEventListener("touchmove",Ri,{passive:!1}),()=>{c.removeEventListener("touchmove",Ri)}},[V,yt,Kt,W,ae,_e]);const Hi=()=>{Y("all"),Ye(""),hu(new Set),wn()},Li=c=>{const h=new Set(Bt);h.has(c)?h.delete(c):h.add(c),hu(h)},zu=()=>{if(!Lt.trim())return $;const c=Lt.toLowerCase();return $.filter(h=>h.name.toLowerCase().includes(c))},Bi=()=>{const c=[],h=D=>E==="all"||E===D;h("page")&&B.forEach(D=>{c.push({id:D.id,type:"page",url:D.url,tags:D.tags,saved_at:D.saved_at,metadata:D.metadata})}),h("text")&&q.forEach(D=>{c.push({id:D.id,type:"text",content:D.content,tags:D.tags,saved_at:D.saved_at,metadata:D.metadata})}),h("tagset")&&rt.forEach(D=>{c.push({id:D.id,type:"tagset",tags:D.tags,saved_at:D.saved_at,metadata:D.metadata})}),h("image")&&H.forEach(D=>{c.push({id:D.id,type:"image",tags:D.tags,saved_at:D.saved_at,metadata:D.metadata,thumbnail:D.thumbnail,mime_type:D.mime_type,width:D.width,height:D.height})});const N=Lt.toLowerCase();return c.filter(D=>{const pt=!Lt.trim()||D.tags.some(ca=>ca.toLowerCase().includes(N))||D.url?.toLowerCase().includes(N)||D.content?.toLowerCase().includes(N)||D.metadata?.title?.toLowerCase().includes(N),at=Bt.size===0||Array.from(Bt).every(ca=>D.tags.includes(ca)),ne=ta&&D.tags.includes(ta),Fa=ta&&Bt.has(ta);return ne&&!Fa?!1:pt&&at}).sort((D,pt)=>{const at=new Date(pt.saved_at).getTime()-new Date(D.saved_at).getTime();return Ua==="oldest"?-at:at})},rl=V||yt||Kt||W;z.useEffect(()=>(rl||ae?document.body.classList.add("editor-open"):document.body.classList.remove("editor-open"),()=>{document.body.classList.remove("editor-open")}),[rl,ae]);const ds=()=>{if(!rl)return null;if(V)return B.find(h=>h.id===V)?s.jsxs(hi,{onDismiss:qa,keyboardHeight:Xe,className:"text-editor-overlay",children:[s.jsxs("div",{className:"input-with-clear editor-url-wrapper",children:[s.jsx("input",{type:"url",className:"editor-url-input",value:wt,onChange:h=>Ht(h.target.value),onFocus:()=>{requestAnimationFrame(()=>window.scrollTo(0,0))},placeholder:"URL",autoCapitalize:"none",autoCorrect:"off"}),s.jsx(Kc,{show:wt.length>0,onClear:()=>Ht("")})]}),s.jsx(mi,{selectedTags:ee,availableTags:Qt,tagInput:Xt,onTagInputChange:le,onToggleTag:Se,onAddTag:wl}),s.jsx(vi,{onSave:Mn,onCancel:qa,onDelete:()=>dl(V,"page")})]}):null;if(yt)return s.jsxs(hi,{onDismiss:Ci,keyboardHeight:Xe,className:"text-editor-overlay",children:[s.jsx(wh,{value:It,onChange:Te,placeholder:"Note text...",keyboardHeight:Xe,autoFocus:!0,showClearButton:!1,onAutoSave:es}),s.jsx(mi,{selectedTags:ve,availableTags:$,tagInput:Ut,onTagInputChange:je,onToggleTag:Pc,onAddTag:ts}),s.jsx(vi,{onSave:ls,onCancel:Ci,onDelete:()=>dl(yt,"text"),saveLabel:"Done"})]});if(Kt)return s.jsxs(hi,{onDismiss:Di,keyboardHeight:Xe,className:"text-editor-overlay",children:[s.jsx(mi,{selectedTags:b,availableTags:$,tagInput:U,onTagInputChange:J,onToggleTag:us,onAddTag:is}),s.jsx(vi,{onSave:Mi,onCancel:Di,onDelete:()=>dl(Kt,"tagset")})]});if(W){const c=H.find(C=>C.id===W);if(!c)return null;const N=c.metadata?.title;return s.jsxs(hi,{onDismiss:Oi,keyboardHeight:Xe,className:"text-editor-overlay",children:[s.jsxs("div",{className:"editor-image-preview",children:[c.thumbnail?s.jsx("img",{src:`data:image/jpeg;base64,${c.thumbnail}`,alt:N||"Preview",className:"edit-modal-image"}):s.jsx("div",{className:"image-placeholder",children:s.jsxs("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),s.jsx("polyline",{points:"21 15 16 10 5 21"})]})}),N&&s.jsx("div",{className:"edit-image-title",children:N})]}),s.jsx(mi,{selectedTags:j,availableTags:$,tagInput:R,onTagInputChange:Z,onToggleTag:fs,onAddTag:os}),s.jsx(vi,{onSave:rs,onCancel:Oi,onDelete:()=>dl(W,"image")})]})}return null},hs=c=>{switch(c.type){case"page":return Yi({id:c.id,url:c.url,tags:c.tags,saved_at:c.saved_at,metadata:c.metadata});case"text":return Gi({id:c.id,content:c.content,tags:c.tags,saved_at:c.saved_at,metadata:c.metadata});case"tagset":return Za({id:c.id,tags:c.tags,saved_at:c.saved_at,metadata:c.metadata});case"image":return gs({id:c.id,tags:c.tags,saved_at:c.saved_at,metadata:c.metadata,thumbnail:c.thumbnail,mime_type:c.mime_type||"image/jpeg",width:c.width,height:c.height});default:return null}},qi=c=>s.jsxs("div",{className:`webview-inline ${ou?"webview-expanded":""}`,children:[vn?s.jsxs("div",{className:"webview-error",children:[s.jsx("p",{children:"This site can't be displayed inline."}),s.jsx("button",{onClick:h=>{h.stopPropagation(),Vc(c)},children:"Open in Safari"})]}):s.jsx("iframe",{src:c,className:"webview-iframe",onLoad:()=>Da(!0),onError:()=>du(!0),sandbox:"allow-scripts allow-same-origin allow-forms allow-popups"}),!ru&&!vn&&s.jsx("div",{className:"webview-loading",children:"Loading..."})]}),Yi=c=>{const h=c.metadata?.title,N=Sl?.itemId===c.id;return s.jsxs("div",{id:`card-${c.id}`,className:`saved-item-card ${N?"card-webview-expanded":""}`,onClick:()=>!N&&zi(c),children:[s.jsxs("div",{className:"card-header",children:[N&&s.jsx("button",{className:`card-action-btn webview-back-btn ${ou?"visible":""}`,onClick:C=>{C.stopPropagation(),Hn()},title:"Back",children:s.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",children:s.jsx("path",{d:"M15 18l-6-6 6-6"})})}),s.jsx("div",{className:"card-type-icon",children:s.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"10"}),s.jsx("line",{x1:"2",y1:"12",x2:"22",y2:"12"}),s.jsx("path",{d:"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"})]})}),s.jsx("span",{className:"card-title",children:h||c.url}),s.jsxs("div",{className:"card-actions",children:[s.jsx("button",{className:"card-action-btn",onClick:C=>N?(C.stopPropagation(),Vc(c.url)):Du(c.url,c.id,C),title:"Open in Safari",children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"}),s.jsx("polyline",{points:"15 3 21 3 21 9"}),s.jsx("line",{x1:"10",y1:"14",x2:"21",y2:"3"})]})}),s.jsx("button",{className:"card-action-btn",onClick:C=>N?(C.stopPropagation(),Hn()):Mu(c.url,c.id,C),title:N?"Close webview":"Open in app",children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("line",{x1:"3",y1:"9",x2:"21",y2:"9"})]})}),s.jsx("button",{className:"card-delete-btn",onClick:C=>{C.stopPropagation(),dl(c.id,"page")},children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("polyline",{points:"3 6 5 6 21 6"}),s.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]})})]})]}),N&&qi(Sl.url),s.jsxs("div",{className:"card-footer",children:[(c.tags.includes("todo")||c.tags.includes("done"))&&s.jsx("button",{className:`todo-checkbox ${c.tags.includes("done")?"checked":""}`,onClick:C=>Ja(C,c.id,"page",c.tags),children:c.tags.includes("done")?s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("polyline",{points:"9 11 12 14 22 4"})]}):s.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"})})}),s.jsxs("div",{className:"card-tags",children:[c.tags.map(C=>s.jsx("span",{className:"card-tag",children:C},C)),s.jsx("span",{className:"card-date",children:new Date(c.saved_at).toLocaleDateString()})]})]})]},c.id)},Gi=c=>{const h=c.tags.length>0?c.tags:Ui(c.content),C=c.content.replace(/#\w+/g,"").trim().split(` 13 13 `)[0].slice(0,100)||c.content.slice(0,100),D=c.content.match(/https?:\/\/[^\s<>"{}|\\^`[\]]+/),pt=Sl?.itemId===c.id;return s.jsxs("div",{id:`card-${c.id}`,className:`saved-item-card ${pt?"card-webview-expanded":""}`,onClick:()=>!pt&&Ic(c),children:[s.jsxs("div",{className:"card-header",children:[pt&&s.jsx("button",{className:`card-action-btn webview-back-btn ${ou?"visible":""}`,onClick:at=>{at.stopPropagation(),Hn()},title:"Back",children:s.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",children:s.jsx("path",{d:"M15 18l-6-6 6-6"})})}),s.jsx("div",{className:"card-type-icon",children:s.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"}),s.jsx("polyline",{points:"14 2 14 8 20 8"}),s.jsx("line",{x1:"16",y1:"13",x2:"8",y2:"13"}),s.jsx("line",{x1:"16",y1:"17",x2:"8",y2:"17"})]})}),s.jsx("div",{className:"card-title",children:C}),s.jsxs("div",{className:"card-actions",children:[D&&s.jsx("button",{className:"card-action-btn",onClick:at=>pt?(at.stopPropagation(),Vc(D[0])):Du(D[0],c.id,at),title:"Open in Safari",children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"}),s.jsx("polyline",{points:"15 3 21 3 21 9"}),s.jsx("line",{x1:"10",y1:"14",x2:"21",y2:"3"})]})}),D&&s.jsx("button",{className:"card-action-btn",onClick:at=>pt?(at.stopPropagation(),Hn()):Mu(D[0],c.id,at),title:pt?"Close webview":"Open in app",children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("line",{x1:"3",y1:"9",x2:"21",y2:"9"})]})}),s.jsx("button",{className:"card-delete-btn",onClick:at=>{at.stopPropagation(),dl(c.id,"text")},children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("polyline",{points:"3 6 5 6 21 6"}),s.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]})})]})]}),pt&&qi(Sl.url),s.jsxs("div",{className:"card-footer",children:[(h.includes("todo")||h.includes("done"))&&s.jsx("button",{className:`todo-checkbox ${h.includes("done")?"checked":""}`,onClick:at=>Ja(at,c.id,"text",h),children:h.includes("done")?s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("polyline",{points:"9 11 12 14 22 4"})]}):s.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"})})}),s.jsxs("div",{className:"card-tags",children:[h.map(at=>s.jsx("span",{className:"card-tag",children:at},at)),s.jsx("span",{className:"card-date",children:new Date(c.saved_at).toLocaleDateString()})]})]})]},c.id)},Za=c=>s.jsxs("div",{className:"saved-item-card",onClick:()=>ns(c),children:[s.jsxs("div",{className:"card-header",children:[s.jsx("div",{className:"card-type-icon",children:s.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"}),s.jsx("line",{x1:"7",y1:"7",x2:"7.01",y2:"7"})]})}),s.jsx("div",{className:"card-title",children:c.tags.join(", ")}),s.jsx("button",{className:"card-delete-btn",onClick:h=>{h.stopPropagation(),dl(c.id,"tagset")},children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("polyline",{points:"3 6 5 6 21 6"}),s.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]})})]}),s.jsx("div",{className:"card-footer",children:s.jsx("div",{className:"card-tags",children:s.jsx("span",{className:"card-date",children:new Date(c.saved_at).toLocaleDateString()})})})]},c.id),Va=async c=>{try{await X("delete_url",{id:c}),await fe(),Un()}catch(h){console.error("Failed to delete image:",h)}},dl=(c,h)=>{Tl({id:c,type:h})},Ka=()=>{Tl(null)},Qi=async()=>{if(!yn)return;const{id:c,type:h}=yn;Tl(null);const N={page:"Page",text:"Note",tagset:"Tags",image:"Image"};try{switch(h){case"page":await Ni(c);break;case"text":await as(c);break;case"tagset":await cs(c);break;case"image":await Va(c);break}qt(`${N[h]} deleted`)}catch(C){console.error("Failed to delete:",C),qt("Failed to delete","error")}},Nu=()=>{Al(null)},Cu=async()=>{if(!xn)return;const{type:c}=xn;switch(Al(null),c){case"page":Rl();break;case"text":if(yt&&Pt?.content!==void 0)try{await X("update_text",{id:yt,content:Pt.content,tags:Pt.tags||[]}),await Ve()}catch(h){console.error("Failed to restore original content:",h)}On();break;case"tagset":ia();break;case"image":Un();break}},Ja=async(c,h,N,C)=>{c.stopPropagation();const D=C.includes("todo"),pt=C.includes("done");let at;if(D)at=C.filter(ne=>ne!=="todo").concat("done");else if(pt)at=C.filter(ne=>ne!=="done").concat("todo");else return;try{switch(await X("update_url_tags",{id:h,tags:at}),N){case"page":await Ze();break;case"text":await Ve();break;case"tagset":await Oe();break;case"image":await fe();break}await oe()}catch(ne){console.error("Failed to toggle todo/done:",ne)}},Du=async(c,h,N)=>{N.stopPropagation();try{await X("record_visit",{itemId:h,source:"browser",windowType:"external"}),await Vc(c)}catch(C){console.error("Failed to open in browser:",C)}},ka=z.useRef(null),Mu=async(c,h,N)=>{N.stopPropagation(),Da(!1),du(!1),mn(!1),hn({url:c,itemId:h}),requestAnimationFrame(()=>{requestAnimationFrame(()=>{const C=document.getElementById(`card-${h}`),D=ka.current;if(C&&D){const pt=C.getBoundingClientRect(),at=D.getBoundingClientRect(),ne=document.createElement("div");ne.style.cssText="position:fixed;top:0;height:env(safe-area-inset-top,0px);visibility:hidden;",document.body.appendChild(ne);const Fa=ne.offsetHeight;document.body.removeChild(ne);const ca=pt.top-at.top-Fa;D.style.setProperty("--slide-offset",`${Math.max(0,ca)}px`)}document.documentElement.style.setProperty("--webview-ease","var(--webview-ease-in)"),mn(!0)})});try{await X("record_visit",{itemId:h,source:"webview",windowType:"embedded"})}catch(C){console.error("[App] Failed to record webview visit:",C)}},Hn=()=>{document.documentElement.style.setProperty("--webview-ease","var(--webview-ease-out)"),mn(!1),ka.current&&ka.current.style.setProperty("--slide-offset","0px"),setTimeout(()=>{hn(null),Da(!1),du(!1)},pl)},ms=()=>xn?s.jsx("div",{className:"confirm-modal-overlay",onClick:Nu,children:s.jsxs("div",{className:"confirm-modal",onClick:c=>c.stopPropagation(),children:[s.jsx("p",{children:"Discard unsaved changes?"}),s.jsxs("div",{className:"confirm-modal-buttons",children:[s.jsx("button",{className:"cancel-btn",onClick:Nu,children:"Cancel"}),s.jsx("button",{className:"delete-btn",onClick:Cu,children:"Discard"})]})]})}):null,vs=()=>{if(!yn)return null;const c={page:"page",text:"note",tagset:"tag set",image:"image"};return s.jsx("div",{className:"confirm-modal-overlay",onClick:Ka,children:s.jsxs("div",{className:"confirm-modal",onClick:h=>h.stopPropagation(),children:[s.jsxs("p",{children:["Delete this ",c[yn.type],"?"]}),s.jsxs("div",{className:"confirm-modal-buttons",children:[s.jsx("button",{className:"cancel-btn",onClick:Ka,children:"Cancel"}),s.jsx("button",{className:"delete-btn",onClick:Qi,children:"Delete"})]})]})})},gs=c=>{const h=c.metadata,N=h?.title,C=h?.sourceUrl;return s.jsxs("div",{className:"saved-item-card image-card",onClick:()=>ss(c),children:[s.jsxs("div",{className:"card-header",children:[s.jsx("div",{className:"card-thumbnail",children:c.thumbnail?s.jsx("img",{src:`data:image/jpeg;base64,${c.thumbnail}`,alt:N||"Preview"}):s.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),s.jsx("polyline",{points:"21 15 16 10 5 21"})]})}),s.jsx("div",{className:"card-title",children:N||C||"Image"}),s.jsx("button",{className:"card-delete-btn",onClick:D=>{D.stopPropagation(),dl(c.id,"image")},children:s.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("polyline",{points:"3 6 5 6 21 6"}),s.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]})})]}),s.jsxs("div",{className:"card-footer",children:[(c.tags.includes("todo")||c.tags.includes("done"))&&s.jsx("button",{className:`todo-checkbox ${c.tags.includes("done")?"checked":""}`,onClick:D=>Ja(D,c.id,"image",c.tags),children:c.tags.includes("done")?s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("polyline",{points:"9 11 12 14 22 4"})]}):s.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"})})}),s.jsxs("div",{className:"card-tags",children:[c.tags.map(D=>s.jsx("span",{className:"card-tag",children:D},D)),s.jsx("span",{className:"card-date",children:new Date(c.saved_at).toLocaleDateString()})]})]})]},c.id)},ys=()=>{tl(!1),Ze(),oe()};if(pi)return s.jsxs("div",{className:"app",children:[s.jsxs("header",{children:[s.jsx("button",{className:"header-btn back-btn",onClick:ys,children:"Back"}),s.jsx("h1",{children:"Settings"}),s.jsx("div",{className:"header-spacer"})]}),s.jsxs("main",{className:"settings-view",children:[s.jsxs("div",{className:"settings-section",children:[s.jsx("h2",{children:"Server Sync"}),s.jsx("p",{className:"settings-description",children:"Sync your saved items with the server. Pull to get items from other devices, push to send local items, or sync all to do both."}),s.jsx("p",{className:"settings-description",style:{fontSize:"0.85rem",opacity:.8},children:"Items sync to your account's current profile on the server."}),s.jsx("div",{className:"webhook-input",children:s.jsx("input",{type:"url",value:el,onChange:c=>En(c.target.value),placeholder:"https://your-server.example.com",autoCapitalize:"none",autoCorrect:"off"})}),s.jsxs("div",{className:"webhook-input api-key-field",children:[s.jsx("input",{type:cl?"text":"password",value:wa,onChange:c=>Pl(c.target.value),placeholder:"API key",autoCapitalize:"none",autoCorrect:"off"}),s.jsx("button",{type:"button",className:"toggle-visibility-btn",onClick:()=>Ha(!cl),children:cl?s.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"}),s.jsx("line",{x1:"1",y1:"1",x2:"23",y2:"23"})]}):s.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"}),s.jsx("circle",{cx:"12",cy:"12",r:"3"})]})})]}),s.jsx("button",{onClick:Su,disabled:el===Nt&&wa===kc,className:"save-settings-btn",children:"Save Settings"}),s.jsxs("label",{className:"auto-sync-toggle",children:[s.jsx("input",{type:"checkbox",checked:vu,onChange:c=>Ei(c.target.checked)}),s.jsx("span",{children:"Auto-sync when items are added or modified"})]}),sl&&s.jsxs("p",{className:"last-sync-info",children:["Last synced: ",new Date(sl).toLocaleString()]}),jn&&jn.pending_count>0&&s.jsxs("p",{className:"sync-pending-info",children:[jn.pending_count," item",jn.pending_count===1?"":"s"," pending sync"]}),s.jsx("button",{className:"sync-btn primary",onClick:Ul,disabled:!Nt||_e,children:_e?"Syncing...":"Sync All"}),s.jsxs("div",{className:"sync-btn-row",children:[s.jsx("button",{className:"sync-btn secondary",onClick:ua,disabled:!Nt||_e,children:"Pull"}),s.jsx("button",{className:"sync-btn secondary",onClick:Ai,disabled:!Nt||_e,children:"Push"})]}),La&&s.jsx("div",{className:`sync-message ${La.includes("failed")||La.includes("Failed")?"error":"success"}`,children:La})]}),s.jsxs("div",{className:"settings-section",children:[s.jsx("h2",{children:"Profiles"}),Dt&&s.jsxs(s.Fragment,{children:[s.jsxs("p",{className:"settings-description",children:[Dt.isProductionBuild?"App Store/TestFlight build":"Development build",". Each profile has separate local data and sync destination."]}),(()=>{const c=Dt.profiles.find(C=>C.id===Dt.currentProfileId),h=Dt.profiles[0],N=c?.id===h?.id;return s.jsxs(s.Fragment,{children:[!N&&c&&s.jsxs("div",{className:"profile-warning-banner",children:['Using "',c.name,'" profile - data is isolated from default']}),s.jsx("div",{className:"profile-list",children:Dt.profiles.map(C=>{const D=C.id===Dt.currentProfileId,pt=!D&&Dt.profiles.length>1;return s.jsxs("div",{className:`profile-item ${D?"active":""}`,children:[s.jsxs("label",{className:"profile-radio-label",children:[s.jsx("input",{type:"radio",name:"profile",checked:D,onChange:()=>{console.log(`[Profile] Radio clicked: ${C.id}, isCurrent: ${D}`),D||(console.log(`[Profile] Switching to: ${C.id}`),ll(C.id))}}),s.jsx("span",{className:"profile-name",children:C.name}),D&&s.jsx("span",{className:"profile-badge current",children:"active"})]}),pt&&s.jsx("button",{className:"profile-delete-btn",onClick:async()=>{if(confirm(`Delete profile "${C.name}"? 14 14 15 - The database file will be preserved.`))try{const at=await X("delete_profile",{profileId:C.id});_n(at)}catch(at){alert(`Failed to delete: ${at}`)}},children:"Delete"})]},C.id)})}),s.jsx("div",{className:"profile-add-section",children:s.jsxs("div",{className:"profile-input-row",children:[s.jsx("input",{type:"text",value:Cl,onChange:C=>Dl(C.target.value),placeholder:"New profile name"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{if(Cl.trim())try{const C=await X("create_profile",{name:Cl.trim()});_n(C),Dl("")}catch(C){alert(`Failed to create: ${C}`)}},disabled:!Cl.trim(),children:"Add"})]})})]})})()]})]}),s.jsxs("div",{className:"settings-section",children:[s.jsx("h2",{children:"Display"}),s.jsx("p",{className:"settings-description",children:"Items with this tag are hidden from the main view unless the tag is selected as a filter."}),s.jsx("div",{className:"webhook-input",children:s.jsx("input",{type:"text",value:ea,onChange:c=>gu(c.target.value),placeholder:"archive",autoCapitalize:"none",autoCorrect:"off"})}),s.jsx("button",{onClick:pu,disabled:ea===ta,className:"save-settings-btn",children:"Save Archive Tag"})]}),s.jsxs("div",{className:"settings-section",children:[s.jsx("h2",{children:"Debug"}),s.jsxs("div",{className:"sync-btn-row",style:{flexDirection:"column",gap:"0.5rem"},children:[s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_list_container_files");tt("FILES: "+c.join(" | "))}catch(c){tt("ERROR: "+String(c))}},children:"List Container Files"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_profiles_json");tt(c)}catch(c){tt("PROFILES ERROR: "+String(c))}},children:"Show profiles.json"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_settings_table");tt(c)}catch(c){tt("SETTINGS ERROR: "+String(c))}},children:"Show Settings Table"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_query_database");tt(c)}catch(c){tt("DB ERROR: "+String(c))}},children:"Query Database"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{tt("Exporting...");const c=await X("debug_export_database");tt("DB_START>>>"+c.substring(0,500)+"...("+c.length+" total chars). Use AirDrop or copy manually."),console.log("FULL_DB_BASE64:",c)}catch(c){tt("EXPORT ERROR: "+String(c))}},children:"Export Database"}),Dt&&Dt.profiles.length>=2&&s.jsx("button",{className:"sync-btn secondary",style:{backgroundColor:"#c44"},onClick:async()=>{const c=Dt.profiles[0],h=Dt.profiles[1];try{tt("Swapping...");const N=await X("swap_profile_databases",{profileIdA:c.id,profileIdB:h.id});tt(N)}catch(N){tt("SWAP ERROR: "+String(N))}},children:"Swap Default ↔ Dev Databases"})]})]})]}),Qe&&s.jsx("div",{className:"modal-overlay",children:s.jsxs("div",{className:"modal-content",children:[s.jsx("h3",{children:"Profile Changed"}),s.jsxs("p",{children:["Switched to ",s.jsx("strong",{children:Dt?.profiles.find(c=>c.id===Dt?.currentProfileId)?.name??"unknown"})," profile."]}),s.jsx("p",{children:"Please restart the app to ensure complete data isolation."}),s.jsxs("div",{className:"modal-buttons",children:[s.jsx("button",{className:"modal-btn secondary",onClick:()=>pe(!1),children:"Later"}),s.jsx("button",{className:"modal-btn primary",onClick:Cn,children:"Quit Now"})]})]})})]});const be=Bi(),Wa=B.length+q.length+rt.length+H.length,Ou=s.jsx("input",{ref:gi,type:"file",accept:"image/*",capture:"environment",onChange:Ga,style:{display:"none"}});return Ma?s.jsxs("div",{className:"app",children:[Ou,s.jsxs("header",{children:[s.jsx("button",{className:"header-btn back-btn",onClick:_u,children:"Cancel"}),s.jsx("h1",{children:"Save Photo"}),s.jsx("div",{className:"header-spacer"})]}),s.jsx("main",{className:"saved-view",children:s.jsxs("div",{className:"captured-image-view",children:[s.jsx("div",{className:"captured-image-preview",children:s.jsx("img",{src:Ma,alt:"Captured"})}),bl.size>0&&s.jsx("div",{className:"edit-section",children:s.jsx("div",{className:"editing-tags",children:Array.from(bl).sort().map(c=>s.jsxs("span",{className:"editing-tag",children:[c,s.jsx("button",{onClick:()=>Qa(c),children:"×"})]},c))})}),s.jsx("div",{className:"edit-section",children:s.jsxs("div",{className:"new-tag-input",children:[s.jsx("input",{type:"text",value:qe,onChange:c=>xl(c.target.value),onKeyDown:c=>{c.key==="Enter"&&(c.preventDefault(),ju())},placeholder:"Add tag...",autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",spellCheck:!1}),s.jsx("button",{onClick:ju,disabled:!qe.trim(),children:"Add"})]})}),$.filter(c=>!bl.has(c.name)&&(!qe.trim()||c.name.toLowerCase().includes(qe.toLowerCase().trim()))).length>0&&s.jsx("div",{className:"edit-section",children:s.jsx("div",{className:"all-tags-list",children:$.filter(c=>!bl.has(c.name)&&(!qe.trim()||c.name.toLowerCase().includes(qe.toLowerCase().trim()))).map(c=>s.jsx("span",{className:"tag-chip",onClick:()=>Qa(c.name),children:c.name},c.name))})}),s.jsxs("div",{className:"edit-buttons",children:[s.jsx("button",{className:"cancel-btn",onClick:_u,children:"Cancel"}),s.jsx("button",{className:"save-btn",onClick:Fc,children:"Save"})]})]})})]}):s.jsxs("div",{className:`app ${Sl?"webview-active":""}`,ref:ka,children:[s.jsx("input",{ref:$l,style:{position:"fixed",opacity:0,top:"-100px"},readOnly:!0}),Ou,s.jsxs("header",{children:[s.jsxs("h1",{onClick:()=>{E!=="all"||Lt||Bt.size>0?Hi():wn()},style:{cursor:"pointer"},children:["Peek ",s.jsx("span",{style:{fontSize:"0.5em",opacity:.5},children:"v1034"})]}),s.jsxs("div",{className:"filter-icons",children:[s.jsxs("button",{className:`filter-btn ${E==="page"?"active":""}`,onClick:()=>Rn("page"),title:"Pages",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"10"}),s.jsx("line",{x1:"2",y1:"12",x2:"22",y2:"12"}),s.jsx("path",{d:"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"})]}),s.jsx("span",{className:"filter-count",children:B.length})]}),s.jsxs("button",{className:`filter-btn ${E==="text"?"active":""}`,onClick:()=>Rn("text"),title:"Notes",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"}),s.jsx("polyline",{points:"14 2 14 8 20 8"}),s.jsx("line",{x1:"16",y1:"13",x2:"8",y2:"13"}),s.jsx("line",{x1:"16",y1:"17",x2:"8",y2:"17"})]}),s.jsx("span",{className:"filter-count",children:q.length})]}),s.jsxs("button",{className:`filter-btn ${E==="tagset"?"active":""}`,onClick:()=>Rn("tagset"),title:"Tag Sets",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"}),s.jsx("line",{x1:"7",y1:"7",x2:"7.01",y2:"7"})]}),s.jsx("span",{className:"filter-count",children:rt.length})]}),s.jsxs("button",{className:`filter-btn ${E==="image"?"active":""}`,onClick:()=>Rn("image"),title:"Images",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),s.jsx("polyline",{points:"21 15 16 10 5 21"})]}),s.jsx("span",{className:"filter-count",children:H.length})]})]}),s.jsx("button",{className:"sort-btn",onClick:()=>Jc(c=>c==="newest"?"oldest":"newest"),title:Ua==="newest"?"Newest first":"Oldest first",children:Ua==="newest"?s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),s.jsx("polyline",{points:"19 12 12 19 5 12"})]}):s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("line",{x1:"12",y1:"19",x2:"12",y2:"5"}),s.jsx("polyline",{points:"5 12 12 5 19 12"})]})}),s.jsx("button",{className:`header-btn settings-btn ${_e?"syncing":""}`,onClick:()=>tl(!0),children:s.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"3"}),s.jsx("path",{d:"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"})]})})]}),Dt&&Dt.profiles.length>0&&Dt.currentProfileId!==Dt.profiles[0].id&&s.jsxs("div",{className:"profile-banner",children:["Profile: ",Dt.profiles.find(c=>c.id===Dt.currentProfileId)?.name??"Unknown"]}),s.jsxs("main",{className:"saved-view",ref:gn,onTouchStart:Xa,onTouchEnd:wi,children:[la!=="idle"&&s.jsx("div",{className:`pull-indicator ${la}`,children:la==="pulling"?"Hold to refresh...":"Release to refresh!"}),s.jsxs("div",{className:"input-row",children:[s.jsx("div",{className:"input-row-card",children:s.jsxs("div",{className:"input-with-clear",style:{flex:1},children:[s.jsx("input",{type:"text",className:"input-row-input",placeholder:"Search...",value:Lt,onChange:c=>Ye(c.target.value),autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",spellCheck:!1}),s.jsx(Kc,{show:Lt.length>0||Bt.size>0,onClear:()=>{Ye(""),hu(new Set)}})]})}),s.jsxs("div",{className:"input-row-card",children:[s.jsx("div",{className:"input-with-clear",style:{flex:1},children:s.jsx("input",{type:"text",className:"input-row-input",placeholder:"Add...",value:F,onChange:c=>nt(c.target.value),onFocus:()=>ge(!0),autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",spellCheck:!1})}),s.jsx("button",{className:"camera-btn",onClick:Eu,title:"Take photo",children:s.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"}),s.jsx("circle",{cx:"12",cy:"13",r:"4"})]})})]})]}),s.jsxs("div",{className:"drag-handle-wrapper",children:[s.jsx("div",{className:"filter-tags-container",ref:Ra,style:{height:`${El}px`},children:zu().length===0?s.jsx("div",{className:"filter-tags-empty",children:"No matching tags"}):s.jsx("div",{className:"filter-tags",children:zu().map(c=>s.jsx("span",{className:`tag-chip ${Bt.has(c.name)?"selected":""}`,onClick:()=>Li(c.name),children:c.name},c.name))})}),s.jsx("div",{className:"drag-handle",onMouseDown:c=>{c.preventDefault(),yu(c.clientY)},onTouchStart:c=>{yu(c.touches[0].clientY)},children:s.jsx("div",{className:"drag-handle-bar"})})]}),s.jsx("div",{className:"unified-list",children:Wa===0?s.jsxs("div",{className:"empty-state",children:[s.jsx("p",{children:"No saved items yet."}),s.jsx("p",{children:"Share a URL from any app to get started!"})]}):be.length===0?s.jsxs("div",{className:"empty-state",children:[s.jsx("p",{children:"No matching items."}),s.jsx("p",{children:"Tap Peek to clear filters."})]}):be.map(c=>hs(c))})]}),ds(),ae&&s.jsxs(hi,{onDismiss:()=>ge(!1),keyboardHeight:Xe,children:[s.jsx(wh,{value:F,onChange:nt,placeholder:"Enter text, URL, or just select tags...",keyboardHeight:Xe,autoFocus:!0,autoCapitalize:"none",autoCorrect:"off"}),s.jsx(mi,{selectedTags:zt,availableTags:$,tagInput:il,onTagInputChange:yl,onToggleTag:Ya,onAddTag:Tu,placeholder:"Add new tag..."}),s.jsx(vi,{onSave:$c,onCancel:()=>ge(!1),cancelLabel:"Close",saveDisabled:!Au()})]}),vs(),ms(),Sn&&s.jsx("div",{className:`toast toast-${Sn.type}`,children:Sn.message}),Qe&&s.jsx("div",{className:"modal-overlay",children:s.jsxs("div",{className:"modal-content",children:[s.jsx("h3",{children:"Profile Changed"}),s.jsxs("p",{children:["Switched to ",s.jsx("strong",{children:Dt?.profiles.find(c=>c.id===Dt?.currentProfileId)?.name??"unknown"})," profile."]}),s.jsx("p",{children:"Please restart the app to ensure complete data isolation."}),s.jsxs("div",{className:"modal-buttons",children:[s.jsx("button",{className:"modal-btn secondary",onClick:()=>pe(!1),children:"Later"}),s.jsx("button",{className:"modal-btn primary",onClick:Cn,children:"Quit Now"})]})]})})]})}mm.createRoot(document.getElementById("root")).render(s.jsx(im.StrictMode,{children:s.jsx(Sm,{})})); 15 + The database file will be preserved.`))try{const at=await X("delete_profile",{profileId:C.id});_n(at)}catch(at){alert(`Failed to delete: ${at}`)}},children:"Delete"})]},C.id)})}),s.jsx("div",{className:"profile-add-section",children:s.jsxs("div",{className:"profile-input-row",children:[s.jsx("input",{type:"text",value:Cl,onChange:C=>Dl(C.target.value),placeholder:"New profile name"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{if(Cl.trim())try{const C=await X("create_profile",{name:Cl.trim()});_n(C),Dl("")}catch(C){alert(`Failed to create: ${C}`)}},disabled:!Cl.trim(),children:"Add"})]})})]})})()]})]}),s.jsxs("div",{className:"settings-section",children:[s.jsx("h2",{children:"Display"}),s.jsx("p",{className:"settings-description",children:"Items with this tag are hidden from the main view unless the tag is selected as a filter."}),s.jsx("div",{className:"webhook-input",children:s.jsx("input",{type:"text",value:ea,onChange:c=>gu(c.target.value),placeholder:"archive",autoCapitalize:"none",autoCorrect:"off"})}),s.jsx("button",{onClick:pu,disabled:ea===ta,className:"save-settings-btn",children:"Save Archive Tag"})]}),s.jsxs("div",{className:"settings-section",children:[s.jsx("h2",{children:"Debug"}),s.jsxs("div",{className:"sync-btn-row",style:{flexDirection:"column",gap:"0.5rem"},children:[s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_list_container_files");tt("FILES: "+c.join(" | "))}catch(c){tt("ERROR: "+String(c))}},children:"List Container Files"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_profiles_json");tt(c)}catch(c){tt("PROFILES ERROR: "+String(c))}},children:"Show profiles.json"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_settings_table");tt(c)}catch(c){tt("SETTINGS ERROR: "+String(c))}},children:"Show Settings Table"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{const c=await X("debug_query_database");tt(c)}catch(c){tt("DB ERROR: "+String(c))}},children:"Query Database"}),s.jsx("button",{className:"sync-btn secondary",onClick:async()=>{try{tt("Exporting...");const c=await X("debug_export_database");tt("DB_START>>>"+c.substring(0,500)+"...("+c.length+" total chars). Use AirDrop or copy manually."),console.log("FULL_DB_BASE64:",c)}catch(c){tt("EXPORT ERROR: "+String(c))}},children:"Export Database"}),Dt&&Dt.profiles.length>=2&&s.jsx("button",{className:"sync-btn secondary",style:{backgroundColor:"#c44"},onClick:async()=>{const c=Dt.profiles[0],h=Dt.profiles[1];try{tt("Swapping...");const N=await X("swap_profile_databases",{profileIdA:c.id,profileIdB:h.id});tt(N)}catch(N){tt("SWAP ERROR: "+String(N))}},children:"Swap Default ↔ Dev Databases"})]})]})]}),Qe&&s.jsx("div",{className:"modal-overlay",children:s.jsxs("div",{className:"modal-content",children:[s.jsx("h3",{children:"Profile Changed"}),s.jsxs("p",{children:["Switched to ",s.jsx("strong",{children:Dt?.profiles.find(c=>c.id===Dt?.currentProfileId)?.name??"unknown"})," profile."]}),s.jsx("p",{children:"Please restart the app to ensure complete data isolation."}),s.jsxs("div",{className:"modal-buttons",children:[s.jsx("button",{className:"modal-btn secondary",onClick:()=>pe(!1),children:"Later"}),s.jsx("button",{className:"modal-btn primary",onClick:Cn,children:"Quit Now"})]})]})})]});const be=Bi(),Wa=B.length+q.length+rt.length+H.length,Ou=s.jsx("input",{ref:gi,type:"file",accept:"image/*",capture:"environment",onChange:Ga,style:{display:"none"}});return Ma?s.jsxs("div",{className:"app",children:[Ou,s.jsxs("header",{children:[s.jsx("button",{className:"header-btn back-btn",onClick:_u,children:"Cancel"}),s.jsx("h1",{children:"Save Photo"}),s.jsx("div",{className:"header-spacer"})]}),s.jsx("main",{className:"saved-view",children:s.jsxs("div",{className:"captured-image-view",children:[s.jsx("div",{className:"captured-image-preview",children:s.jsx("img",{src:Ma,alt:"Captured"})}),bl.size>0&&s.jsx("div",{className:"edit-section",children:s.jsx("div",{className:"editing-tags",children:Array.from(bl).sort().map(c=>s.jsxs("span",{className:"editing-tag",children:[c,s.jsx("button",{onClick:()=>Qa(c),children:"×"})]},c))})}),s.jsx("div",{className:"edit-section",children:s.jsxs("div",{className:"new-tag-input",children:[s.jsx("input",{type:"text",value:qe,onChange:c=>xl(c.target.value),onKeyDown:c=>{c.key==="Enter"&&(c.preventDefault(),ju())},placeholder:"Add tag...",autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",spellCheck:!1}),s.jsx("button",{onClick:ju,disabled:!qe.trim(),children:"Add"})]})}),$.filter(c=>!bl.has(c.name)&&(!qe.trim()||c.name.toLowerCase().includes(qe.toLowerCase().trim()))).length>0&&s.jsx("div",{className:"edit-section",children:s.jsx("div",{className:"all-tags-list",children:$.filter(c=>!bl.has(c.name)&&(!qe.trim()||c.name.toLowerCase().includes(qe.toLowerCase().trim()))).map(c=>s.jsx("span",{className:"tag-chip",onClick:()=>Qa(c.name),children:c.name},c.name))})}),s.jsxs("div",{className:"edit-buttons",children:[s.jsx("button",{className:"cancel-btn",onClick:_u,children:"Cancel"}),s.jsx("button",{className:"save-btn",onClick:Fc,children:"Save"})]})]})})]}):s.jsxs("div",{className:`app ${Sl?"webview-active":""}`,ref:ka,children:[s.jsx("input",{ref:$l,style:{position:"fixed",opacity:0,top:"-100px"},readOnly:!0}),Ou,s.jsxs("header",{children:[s.jsxs("h1",{onClick:()=>{E!=="all"||Lt||Bt.size>0?Hi():wn()},style:{cursor:"pointer"},children:["Peek ",s.jsx("span",{style:{fontSize:"0.5em",opacity:.5},children:"v1037"})]}),s.jsxs("div",{className:"filter-icons",children:[s.jsxs("button",{className:`filter-btn ${E==="page"?"active":""}`,onClick:()=>Rn("page"),title:"Pages",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"10"}),s.jsx("line",{x1:"2",y1:"12",x2:"22",y2:"12"}),s.jsx("path",{d:"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"})]}),s.jsx("span",{className:"filter-count",children:B.length})]}),s.jsxs("button",{className:`filter-btn ${E==="text"?"active":""}`,onClick:()=>Rn("text"),title:"Notes",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"}),s.jsx("polyline",{points:"14 2 14 8 20 8"}),s.jsx("line",{x1:"16",y1:"13",x2:"8",y2:"13"}),s.jsx("line",{x1:"16",y1:"17",x2:"8",y2:"17"})]}),s.jsx("span",{className:"filter-count",children:q.length})]}),s.jsxs("button",{className:`filter-btn ${E==="tagset"?"active":""}`,onClick:()=>Rn("tagset"),title:"Tag Sets",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"}),s.jsx("line",{x1:"7",y1:"7",x2:"7.01",y2:"7"})]}),s.jsx("span",{className:"filter-count",children:rt.length})]}),s.jsxs("button",{className:`filter-btn ${E==="image"?"active":""}`,onClick:()=>Rn("image"),title:"Images",children:[s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),s.jsx("polyline",{points:"21 15 16 10 5 21"})]}),s.jsx("span",{className:"filter-count",children:H.length})]})]}),s.jsx("button",{className:"sort-btn",onClick:()=>Jc(c=>c==="newest"?"oldest":"newest"),title:Ua==="newest"?"Newest first":"Oldest first",children:Ua==="newest"?s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),s.jsx("polyline",{points:"19 12 12 19 5 12"})]}):s.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("line",{x1:"12",y1:"19",x2:"12",y2:"5"}),s.jsx("polyline",{points:"5 12 12 5 19 12"})]})}),s.jsx("button",{className:`header-btn settings-btn ${_e?"syncing":""}`,onClick:()=>tl(!0),children:s.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"3"}),s.jsx("path",{d:"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"})]})})]}),Dt&&Dt.profiles.length>0&&Dt.currentProfileId!==Dt.profiles[0].id&&s.jsxs("div",{className:"profile-banner",children:["Profile: ",Dt.profiles.find(c=>c.id===Dt.currentProfileId)?.name??"Unknown"]}),s.jsxs("main",{className:"saved-view",ref:gn,onTouchStart:Xa,onTouchEnd:wi,children:[la!=="idle"&&s.jsx("div",{className:`pull-indicator ${la}`,children:la==="pulling"?"Hold to refresh...":"Release to refresh!"}),s.jsxs("div",{className:"input-row",children:[s.jsx("div",{className:"input-row-card",children:s.jsxs("div",{className:"input-with-clear",style:{flex:1},children:[s.jsx("input",{type:"text",className:"input-row-input",placeholder:"Search...",value:Lt,onChange:c=>Ye(c.target.value),autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",spellCheck:!1}),s.jsx(Kc,{show:Lt.length>0||Bt.size>0,onClear:()=>{Ye(""),hu(new Set)}})]})}),s.jsxs("div",{className:"input-row-card",children:[s.jsx("div",{className:"input-with-clear",style:{flex:1},children:s.jsx("input",{type:"text",className:"input-row-input",placeholder:"Add...",value:F,onChange:c=>nt(c.target.value),onFocus:()=>ge(!0),autoCapitalize:"none",autoCorrect:"off",autoComplete:"off",spellCheck:!1})}),s.jsx("button",{className:"camera-btn",onClick:Eu,title:"Take photo",children:s.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"}),s.jsx("circle",{cx:"12",cy:"13",r:"4"})]})})]})]}),s.jsxs("div",{className:"drag-handle-wrapper",children:[s.jsx("div",{className:"filter-tags-container",ref:Ra,style:{height:`${El}px`},children:zu().length===0?s.jsx("div",{className:"filter-tags-empty",children:"No matching tags"}):s.jsx("div",{className:"filter-tags",children:zu().map(c=>s.jsx("span",{className:`tag-chip ${Bt.has(c.name)?"selected":""}`,onClick:()=>Li(c.name),children:c.name},c.name))})}),s.jsx("div",{className:"drag-handle",onMouseDown:c=>{c.preventDefault(),yu(c.clientY)},onTouchStart:c=>{yu(c.touches[0].clientY)},children:s.jsx("div",{className:"drag-handle-bar"})})]}),s.jsx("div",{className:"unified-list",children:Wa===0?s.jsxs("div",{className:"empty-state",children:[s.jsx("p",{children:"No saved items yet."}),s.jsx("p",{children:"Share a URL from any app to get started!"})]}):be.length===0?s.jsxs("div",{className:"empty-state",children:[s.jsx("p",{children:"No matching items."}),s.jsx("p",{children:"Tap Peek to clear filters."})]}):be.map(c=>hs(c))})]}),ds(),ae&&s.jsxs(hi,{onDismiss:()=>ge(!1),keyboardHeight:Xe,children:[s.jsx(wh,{value:F,onChange:nt,placeholder:"Enter text, URL, or just select tags...",keyboardHeight:Xe,autoFocus:!0,autoCapitalize:"none",autoCorrect:"off"}),s.jsx(mi,{selectedTags:zt,availableTags:$,tagInput:il,onTagInputChange:yl,onToggleTag:Ya,onAddTag:Tu,placeholder:"Add new tag..."}),s.jsx(vi,{onSave:$c,onCancel:()=>ge(!1),cancelLabel:"Close",saveDisabled:!Au()})]}),vs(),ms(),Sn&&s.jsx("div",{className:`toast toast-${Sn.type}`,children:Sn.message}),Qe&&s.jsx("div",{className:"modal-overlay",children:s.jsxs("div",{className:"modal-content",children:[s.jsx("h3",{children:"Profile Changed"}),s.jsxs("p",{children:["Switched to ",s.jsx("strong",{children:Dt?.profiles.find(c=>c.id===Dt?.currentProfileId)?.name??"unknown"})," profile."]}),s.jsx("p",{children:"Please restart the app to ensure complete data isolation."}),s.jsxs("div",{className:"modal-buttons",children:[s.jsx("button",{className:"modal-btn secondary",onClick:()=>pe(!1),children:"Later"}),s.jsx("button",{className:"modal-btn primary",onClick:Cn,children:"Quit Now"})]})]})})]})}mm.createRoot(document.getElementById("root")).render(s.jsx(im.StrictMode,{children:s.jsx(Sm,{})}));
+1 -1
backend/tauri-mobile/src-tauri/gen/apple/assets/index.html
··· 6 6 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" /> 7 7 <meta name="color-scheme" content="light dark" /> 8 8 <title>Tauri + React + Typescript</title> 9 - <script type="module" crossorigin src="/assets/index-ChkCr5Ch.js"></script> 9 + <script type="module" crossorigin src="/assets/index-DbCPW-hJ.js"></script> 10 10 <link rel="stylesheet" crossorigin href="/assets/index-CH7TEVAW.css"> 11 11 </head> 12 12
+2
backend/tauri-mobile/src-tauri/gen/apple/peek-save.xcodeproj/project.pbxproj
··· 418 418 PRODUCT_NAME = "Peek Save"; 419 419 SDKROOT = iphoneos; 420 420 TARGETED_DEVICE_FAMILY = "1,2"; 421 + ARCHS = arm64; 421 422 VALID_ARCHS = arm64; 422 423 DEVELOPMENT_TEAM = "TXZTDLL5LC"; 423 424 }; ··· 533 534 PRODUCT_NAME = "Peek Save"; 534 535 SDKROOT = iphoneos; 535 536 TARGETED_DEVICE_FAMILY = "1,2"; 537 + ARCHS = arm64; 536 538 VALID_ARCHS = arm64; 537 539 DEVELOPMENT_TEAM = "TXZTDLL5LC"; 538 540 };