diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 737a8c47..56b32008 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,28 +1,30 @@ -{ - "permissions": { - "allow": [ - "Bash(dir:*)", - "Bash(tree:*)", - "Bash(find:*)", - "Bash(ls -la \"c:\\Users\\dong\\Desktop\\rwadurian\\backend\\services\"\" 2>/dev/null || dir \"c:UsersdongDesktoprwadurianbackendservices\"\")", - "Bash(mkdir:*)", - "Bash(npm run build:*)", - "Bash(npx nest build)", - "Bash(npm install)", - "Bash(npx prisma migrate dev:*)", - "Bash(npx jest:*)", - "Bash(flutter test:*)", - "Bash(flutter analyze:*)", - "Bash(findstr:*)", - "Bash(flutter pub get:*)", - "Bash(cat:*)", - "Bash(git add:*)", - "Bash(git commit -m \"$(cat <<''EOF''\nrefactor(infra): 统一微服务基础设施为共享模式\n\n- 将 presence-service 添加到主 docker-compose.yml(端口 3011,Redis DB 10)\n- 更新 init-databases.sh 添加 rwa_admin 和 rwa_presence 数据库\n- 重构 admin-service/deploy.sh 使用共享基础设施\n- 重构 presence-service/deploy.sh 使用共享基础设施\n- 添加 authorization-service 开发指南文档\n\n解决多个微服务独立启动重复基础设施(PostgreSQL/Redis/Kafka)的问题\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", - "Bash(git push)", - "Bash(git commit -m \"$(cat <<''EOF''\nfeat(admin-service): 增强移动端版本上传功能\n\n- 添加 APK/IPA 文件解析器自动提取版本信息\n- 支持从安装包自动读取 versionName 和 versionCode\n- 添加 adbkit-apkreader 依赖解析 APK 文件\n- 添加 plist 依赖解析 IPA 文件\n- 优化上传接口支持自动填充版本信息\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", - "Bash(git commit:*)" - ], - "deny": [], - "ask": [] - } -} +{ + "permissions": { + "allow": [ + "Bash(dir:*)", + "Bash(tree:*)", + "Bash(find:*)", + "Bash(ls -la \"c:\\Users\\dong\\Desktop\\rwadurian\\backend\\services\"\" 2>/dev/null || dir \"c:UsersdongDesktoprwadurianbackendservices\"\")", + "Bash(mkdir:*)", + "Bash(npm run build:*)", + "Bash(npx nest build)", + "Bash(npm install)", + "Bash(npx prisma migrate dev:*)", + "Bash(npx jest:*)", + "Bash(flutter test:*)", + "Bash(flutter analyze:*)", + "Bash(findstr:*)", + "Bash(flutter pub get:*)", + "Bash(cat:*)", + "Bash(git add:*)", + "Bash(git commit -m \"$(cat <<''EOF''\nrefactor(infra): 统一微服务基础设施为共享模式\n\n- 将 presence-service 添加到主 docker-compose.yml(端口 3011,Redis DB 10)\n- 更新 init-databases.sh 添加 rwa_admin 和 rwa_presence 数据库\n- 重构 admin-service/deploy.sh 使用共享基础设施\n- 重构 presence-service/deploy.sh 使用共享基础设施\n- 添加 authorization-service 开发指南文档\n\n解决多个微服务独立启动重复基础设施(PostgreSQL/Redis/Kafka)的问题\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", + "Bash(git push)", + "Bash(git commit -m \"$(cat <<''EOF''\nfeat(admin-service): 增强移动端版本上传功能\n\n- 添加 APK/IPA 文件解析器自动提取版本信息\n- 支持从安装包自动读取 versionName 和 versionCode\n- 添加 adbkit-apkreader 依赖解析 APK 文件\n- 添加 plist 依赖解析 IPA 文件\n- 优化上传接口支持自动填充版本信息\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", + "Bash(git commit:*)", + "Bash(grep:*)", + "Bash(ls:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/backend/services/.claude/settings.local.json b/backend/services/.claude/settings.local.json index 7ab967ee..b99eee48 100644 --- a/backend/services/.claude/settings.local.json +++ b/backend/services/.claude/settings.local.json @@ -4,7 +4,23 @@ "Bash(cat:*)", "Bash(git add:*)", "Bash(git commit:*)", - "Bash(git push:*)" + "Bash(git push:*)", + "Bash(git pull:*)", + "Bash(services/identity-service/src/infrastructure/external/mpc/mpc-client.service.ts )", + "Bash(services/identity-service/src/infrastructure/external/mpc/mpc.module.ts )", + "Bash(services/identity-service/src/infrastructure/kafka/index.ts )", + "Bash(services/identity-service/src/infrastructure/kafka/kafka.module.ts )", + "Bash(services/identity-service/src/infrastructure/kafka/mpc-event-consumer.service.ts )", + "Bash(services/mpc-service/src/application/application.module.ts )", + "Bash(services/mpc-service/src/application/services/index.ts )", + "Bash(services/mpc-service/src/application/services/event-consumer-starter.service.ts )", + "Bash(services/mpc-service/src/application/event-handlers/ )", + "Bash(services/mpc-service/src/infrastructure/infrastructure.module.ts )", + "Bash(services/mpc-service/src/infrastructure/messaging/kafka/index.ts )", + "Bash(services/mpc-service/src/infrastructure/messaging/kafka/event-consumer.service.ts)", + "Bash(npm run build:*)", + "Bash(npx nest build)", + "Bash(npm install)" ], "deny": [], "ask": [] diff --git a/backend/services/blockchain-service/.claude/settings.local.json b/backend/services/blockchain-service/.claude/settings.local.json index b16370d9..fc699961 100644 --- a/backend/services/blockchain-service/.claude/settings.local.json +++ b/backend/services/blockchain-service/.claude/settings.local.json @@ -11,7 +11,9 @@ "Bash(docker compose:*)", "Bash(powershell:*)", "Bash(npm run lint)", - "Bash(git add:*)" + "Bash(git add:*)", + "Bash(git commit -m \"$(cat <<''EOF''\nfeat(blockchain-service): implement complete blockchain service with DDD + Hexagonal architecture\n\n- Domain layer: ChainType, EvmAddress, TxHash, TokenAmount, BlockNumber value objects\n- Domain events: DepositDetected, DepositConfirmed, WalletAddressCreated, TransactionBroadcasted\n- Aggregates: DepositTransaction, MonitoredAddress, TransactionRequest\n- Infrastructure: Prisma ORM, Redis cache, Kafka messaging, EVM blockchain adapters\n- Application services: AddressDerivation, DepositDetection, BalanceQuery\n- API: Health, Balance, Internal controllers with Swagger documentation\n- Deployment: Docker, docker-compose, deploy.sh, health-check scripts\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Opus 4.5 \nEOF\n)\")", + "Bash(git push)" ], "deny": [], "ask": [] diff --git a/backend/services/identity-service/.env.example b/backend/services/identity-service/.env.example index 8dc5dd88..584be756 100644 --- a/backend/services/identity-service/.env.example +++ b/backend/services/identity-service/.env.example @@ -1,4 +1,12 @@ -# Database +# ============================================================================= +# Identity Service - Environment Variables +# ============================================================================= + +# Application +APP_PORT=3000 +APP_ENV="development" + +# Database (PostgreSQL) DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_identity?schema=public" # JWT @@ -21,20 +29,34 @@ KAFKA_GROUP_ID="identity-service-group" SMS_API_URL="https://sms-api.example.com" SMS_API_KEY="your-sms-api-key" -# App -APP_PORT=3000 -APP_ENV="development" - -# Blockchain Encryption +# Wallet Encryption WALLET_ENCRYPTION_SALT="rwa-wallet-salt-change-in-production" -# MPC Service (NestJS 中间层) -# 调用路径: identity-service → mpc-service (NestJS) → mpc-system (Go) -MPC_SERVICE_URL="http://localhost:3001" -MPC_MODE="local" # local 使用本地模拟,remote 调用 mpc-service +# ============================================================================= +# MPC Service Configuration +# ============================================================================= +# 调用路径: identity-service -> mpc-service (NestJS) -> mpc-system (Go) -# Backup Service (MPC 备份分片存储) +# MPC Service URL (NestJS gateway) +MPC_SERVICE_URL="http://localhost:3001" + +# MPC Mode: local (模拟) / remote (调用 mpc-service) +MPC_MODE="local" + +# Use event-driven communication for MPC operations +MPC_USE_EVENT_DRIVEN="true" + +# ============================================================================= +# Backup Service Configuration +# ============================================================================= # 安全要求: 必须部署在与 identity-service 不同的物理服务器上! + BACKUP_SERVICE_URL="http://backup-server:3002" -BACKUP_SERVICE_ENABLED="true" +BACKUP_SERVICE_ENABLED="false" SERVICE_JWT_SECRET="your-service-jwt-secret-change-in-production" + +# ============================================================================= +# Blockchain RPC URLs (for address verification) +# ============================================================================= +KAVA_RPC_URL="https://evm.kava.io" +BSC_RPC_URL="https://bsc-dataseed.binance.org" diff --git a/backend/services/identity-service/docker-compose.yml b/backend/services/identity-service/docker-compose.yml index e4b38464..b55e7fa2 100644 --- a/backend/services/identity-service/docker-compose.yml +++ b/backend/services/identity-service/docker-compose.yml @@ -4,6 +4,9 @@ services: ports: - "3000:3000" environment: + # Application + - APP_PORT=3000 + - APP_ENV=production # Database - DATABASE_URL=postgresql://postgres:password@postgres:5432/rwa_identity?schema=public # JWT @@ -19,18 +22,19 @@ services: - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=identity-service - KAFKA_GROUP_ID=identity-service-group - # App - - APP_PORT=3000 - - APP_ENV=production - # Blockchain + # Wallet Encryption - WALLET_ENCRYPTION_SALT=rwa-wallet-salt-change-in-production # MPC Service - MPC_SERVICE_URL=http://mpc-service:3001 - - MPC_MODE=local + - MPC_MODE=remote + - MPC_USE_EVENT_DRIVEN=true # Backup Service - BACKUP_SERVICE_URL=http://backup-service:3002 - BACKUP_SERVICE_ENABLED=false - SERVICE_JWT_SECRET=your-service-jwt-secret-change-in-production + # Blockchain RPC + - KAVA_RPC_URL=https://evm.kava.io + - BSC_RPC_URL=https://bsc-dataseed.binance.org depends_on: postgres: condition: service_healthy diff --git a/backend/services/identity-service/prisma/migrations/20241206000000_add_device_hardware_info/migration.sql b/backend/services/identity-service/prisma/migrations/20241206000000_add_device_hardware_info/migration.sql new file mode 100644 index 00000000..9f8a975c --- /dev/null +++ b/backend/services/identity-service/prisma/migrations/20241206000000_add_device_hardware_info/migration.sql @@ -0,0 +1,12 @@ +-- AlterTable: Add hardware info fields to user_devices +ALTER TABLE "user_devices" ADD COLUMN "platform" VARCHAR(20); +ALTER TABLE "user_devices" ADD COLUMN "device_model" VARCHAR(100); +ALTER TABLE "user_devices" ADD COLUMN "os_version" VARCHAR(50); +ALTER TABLE "user_devices" ADD COLUMN "app_version" VARCHAR(20); +ALTER TABLE "user_devices" ADD COLUMN "screen_width" INTEGER; +ALTER TABLE "user_devices" ADD COLUMN "screen_height" INTEGER; +ALTER TABLE "user_devices" ADD COLUMN "locale" VARCHAR(10); +ALTER TABLE "user_devices" ADD COLUMN "timezone" VARCHAR(50); + +-- CreateIndex +CREATE INDEX "idx_platform" ON "user_devices"("platform"); diff --git a/backend/services/identity-service/prisma/schema.prisma b/backend/services/identity-service/prisma/schema.prisma index 5b6dbdec..2a078434 100644 --- a/backend/services/identity-service/prisma/schema.prisma +++ b/backend/services/identity-service/prisma/schema.prisma @@ -53,16 +53,27 @@ model UserDevice { userId BigInt @map("user_id") deviceId String @map("device_id") @db.VarChar(100) deviceName String? @map("device_name") @db.VarChar(100) - + + // Hardware Info - 设备硬件信息 + platform String? @db.VarChar(20) // ios, android, web + deviceModel String? @map("device_model") @db.VarChar(100) // iPhone 15 Pro, Pixel 8 + osVersion String? @map("os_version") @db.VarChar(50) // iOS 17.2, Android 14 + appVersion String? @map("app_version") @db.VarChar(20) // 1.0.0 + screenWidth Int? @map("screen_width") + screenHeight Int? @map("screen_height") + locale String? @db.VarChar(10) // zh-CN, en-US + timezone String? @db.VarChar(50) // Asia/Shanghai + addedAt DateTime @default(now()) @map("added_at") lastActiveAt DateTime @default(now()) @map("last_active_at") - + user UserAccount @relation(fields: [userId], references: [userId], onDelete: Cascade) - + @@unique([userId, deviceId], name: "uk_user_device") @@index([deviceId], name: "idx_device") @@index([userId], name: "idx_user") @@index([lastActiveAt], name: "idx_last_active") + @@index([platform], name: "idx_platform") @@map("user_devices") } diff --git a/backend/services/mpc-service/.env.example b/backend/services/mpc-service/.env.example index b34f3b98..08a55db4 100644 --- a/backend/services/mpc-service/.env.example +++ b/backend/services/mpc-service/.env.example @@ -1,49 +1,73 @@ # ============================================================================= -# MPC Party Service - Environment Variables +# MPC Service - Environment Variables +# ============================================================================= +# +# mpc-service 作为 MPC 服务网关: +# 1. 缓存 username + publicKey 的映射关系 +# 2. 存储 delegate share +# 3. 转发请求到 mpc-system (Go/TSS实现) +# # ============================================================================= # Application -NODE_ENV=development -APP_PORT=3006 -API_PREFIX=api/v1 +NODE_ENV="development" +APP_PORT=3001 +API_PREFIX="api/v1" -# Database (Prisma) -DATABASE_URL="mysql://mpc_user:password@localhost:3306/rwa_mpc_party_db" +# Database (PostgreSQL) +DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_mpc?schema=public" # Redis -REDIS_HOST=localhost +REDIS_HOST="localhost" REDIS_PORT=6379 -REDIS_PASSWORD= +REDIS_PASSWORD="" REDIS_DB=5 # JWT -JWT_SECRET=your-jwt-secret-change-in-production -JWT_ACCESS_EXPIRES_IN=2h -JWT_REFRESH_EXPIRES_IN=30d +JWT_SECRET="your-jwt-secret-change-in-production" +JWT_ACCESS_EXPIRES_IN="2h" +JWT_REFRESH_EXPIRES_IN="30d" # Kafka -KAFKA_BROKERS=localhost:9092 -KAFKA_CLIENT_ID=mpc-party-service -KAFKA_GROUP_ID=mpc-party-group +KAFKA_BROKERS="localhost:9092" +KAFKA_CLIENT_ID="mpc-service" +KAFKA_GROUP_ID="mpc-service-group" -# MPC System (deployed on 192.168.1.111) -# account-service: Creates keygen/signing sessions -MPC_ACCOUNT_SERVICE_URL=http://192.168.1.111:4000 -# session-coordinator: Coordinates TSS sessions (used by MPCCoordinatorClient) -MPC_COORDINATOR_URL=http://192.168.1.111:8081 -MPC_SESSION_COORDINATOR_URL=http://192.168.1.111:8081 -# message-router: WebSocket for TSS message routing -MPC_MESSAGE_ROUTER_WS_URL=ws://192.168.1.111:8082 -# server-party-api: Generates user shares (synchronous) -MPC_SERVER_PARTY_API_URL=http://192.168.1.111:8083 -# API key for authenticating with MPC system -MPC_API_KEY=your-mpc-api-key-change-in-production +# ============================================================================= +# MPC System Configuration (Go/TSS Backend) +# ============================================================================= +# MPC System Account Service URL (creates keygen/signing sessions) +MPC_SYSTEM_URL="http://192.168.1.111:4000" + +# API Key for authenticating with MPC system +MPC_API_KEY="your-mpc-api-key-change-in-production" + +# Session Coordinator URL (coordinates TSS sessions) +MPC_COORDINATOR_URL="http://192.168.1.111:8081" + +# Message Router WebSocket URL (TSS message routing) +MPC_MESSAGE_ROUTER_WS_URL="ws://192.168.1.111:8082" + +# Coordinator timeout in milliseconds +MPC_COORDINATOR_TIMEOUT=30000 + +# ============================================================================= # Share Encryption +# ============================================================================= # IMPORTANT: Generate a secure 32-byte hex key for production -SHARE_MASTER_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef +# Example: openssl rand -hex 32 +SHARE_MASTER_KEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +# ============================================================================= # MPC Protocol Timeouts (in milliseconds) -MPC_KEYGEN_TIMEOUT=600000 -MPC_SIGNING_TIMEOUT=300000 -MPC_REFRESH_TIMEOUT=600000 +# ============================================================================= +MPC_KEYGEN_TIMEOUT=300000 +MPC_SIGNING_TIMEOUT=180000 +MPC_REFRESH_TIMEOUT=300000 + +# ============================================================================= +# TSS Library (optional, for direct TSS operations) +# ============================================================================= +TSS_LIB_PATH="/opt/tss-lib/tss" +TSS_TEMP_DIR="/tmp/tss" diff --git a/backend/services/mpc-service/docker-compose.yml b/backend/services/mpc-service/docker-compose.yml index c860a594..92a08f6b 100644 --- a/backend/services/mpc-service/docker-compose.yml +++ b/backend/services/mpc-service/docker-compose.yml @@ -1,64 +1,85 @@ # ============================================================================= -# MPC Party Service - Docker Compose +# MPC Service - Docker Compose # ============================================================================= -version: '3.8' - services: - # MPC Party Service - mpc-party-service: + mpc-service: build: context: . dockerfile: Dockerfile - container_name: rwa-mpc-party + container_name: rwa-mpc-service ports: - - "3006:3006" + - "3001:3001" environment: - NODE_ENV: development - APP_PORT: 3006 - DATABASE_URL: mysql://mpc_user:password@mysql:3306/rwa_mpc_party_db + # Application + NODE_ENV: production + APP_PORT: 3001 + API_PREFIX: api/v1 + # Database (PostgreSQL) + DATABASE_URL: postgresql://postgres:password@postgres:5432/rwa_mpc?schema=public + # Redis REDIS_HOST: redis REDIS_PORT: 6379 + REDIS_PASSWORD: "" REDIS_DB: 5 - KAFKA_BROKERS: kafka:9092 - MPC_COORDINATOR_URL: http://mpc-session-coordinator:50051 - MPC_MESSAGE_ROUTER_WS_URL: ws://mpc-message-router:50052 + # JWT + JWT_SECRET: ${JWT_SECRET:-your-jwt-secret-change-in-production} + JWT_ACCESS_EXPIRES_IN: 2h + JWT_REFRESH_EXPIRES_IN: 30d + # Kafka + KAFKA_BROKERS: kafka:29092 + KAFKA_CLIENT_ID: mpc-service + KAFKA_GROUP_ID: mpc-service-group + # MPC System (Go/TSS Backend) + MPC_SYSTEM_URL: ${MPC_SYSTEM_URL:-http://mpc-system:4000} + MPC_API_KEY: ${MPC_API_KEY:-your-mpc-api-key} + MPC_COORDINATOR_URL: ${MPC_COORDINATOR_URL:-http://mpc-system:8081} + MPC_MESSAGE_ROUTER_WS_URL: ${MPC_MESSAGE_ROUTER_WS_URL:-ws://mpc-system:8082} + MPC_COORDINATOR_TIMEOUT: 30000 + # Share Encryption SHARE_MASTER_KEY: ${SHARE_MASTER_KEY:-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef} - JWT_SECRET: ${JWT_SECRET:-your-jwt-secret-here} + # Timeouts + MPC_KEYGEN_TIMEOUT: 300000 + MPC_SIGNING_TIMEOUT: 180000 + MPC_REFRESH_TIMEOUT: 300000 depends_on: - mysql: + postgres: condition: service_healthy redis: condition: service_started + kafka: + condition: service_started networks: - mpc-network restart: unless-stopped volumes: - ./logs:/app/logs - - # MySQL Database - mysql: - image: mysql:8.0 - container_name: rwa-mpc-mysql - ports: - - "3307:3306" - environment: - MYSQL_ROOT_PASSWORD: rootpassword - MYSQL_DATABASE: rwa_mpc_party_db - MYSQL_USER: mpc_user - MYSQL_PASSWORD: password - volumes: - - mysql_data:/var/lib/mysql - - ./database/migrations:/docker-entrypoint-initdb.d healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] - interval: 10s + test: ["CMD", "wget", "-q", "--spider", "http://localhost:3001/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + postgres: + image: postgres:16-alpine + container_name: rwa-mpc-postgres + ports: + - "5433:5432" + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: rwa_mpc + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s timeout: 5s - retries: 5 + retries: 10 networks: - mpc-network - # Redis redis: image: redis:7-alpine container_name: rwa-mpc-redis @@ -69,7 +90,6 @@ services: networks: - mpc-network - # Kafka (for event publishing) zookeeper: image: confluentinc/cp-zookeeper:7.5.0 container_name: rwa-mpc-zookeeper @@ -87,8 +107,12 @@ services: environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9093,PLAINTEXT_INTERNAL://kafka:29092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT + KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,PLAINTEXT_INTERNAL://0.0.0.0:29092 + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT_INTERNAL KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" depends_on: - zookeeper networks: @@ -99,5 +123,5 @@ networks: driver: bridge volumes: - mysql_data: + postgres_data: redis_data: diff --git a/frontend/mobile-app/.claude/settings.local.json b/frontend/mobile-app/.claude/settings.local.json index 838973d8..70b9bf32 100644 --- a/frontend/mobile-app/.claude/settings.local.json +++ b/frontend/mobile-app/.claude/settings.local.json @@ -1,67 +1,69 @@ -{ - "permissions": { - "allow": [ - "Bash(flutter build:*)", - "Bash(flutter clean:*)", - "Bash(git add:*)", - "Bash(flutter pub get:*)", - "Bash(flutter analyze:*)", - "Bash(git commit -m \"$(cat <<''EOF''\nfeat: 添加APK在线升级和遥测统计模块\n\nAPK升级模块 (lib/core/updater/):\n- 支持自建服务器和Google Play双渠道更新\n- 版本检测、APK下载、SHA-256校验、安装\n- 应用市场来源检测\n- 强制更新和普通更新对话框\n\n遥测模块 (lib/core/telemetry/):\n- 设备信息采集 (品牌、型号、系统版本、屏幕等)\n- 会话管理 (DAU日活统计)\n- 心跳服务 (实时在线人数统计)\n- 事件队列和批量上传\n- 远程配置热更新\n\nAndroid原生配置:\n- MainActivity.kt Platform Channel实现\n- FileProvider配置 (APK安装)\n- 权限配置 (INTERNET, REQUEST_INSTALL_PACKAGES)\n\n文档:\n- docs/backend_api_guide.md 后端API开发指南\n- docs/testing_guide.md 测试指南\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", - "Bash(mkdir:*)", - "Bash(keytool:*)", - "Bash(flutter doctor:*)", - "Bash(flutter emulators:*)", - "Bash(c:Androidemulatoremulator -list-avds)", - "Bash(flutter devices:*)", - "Bash(c:Androidcmdline-toolslatestbinsdkmanager.bat --list)", - "Bash(findstr:*)", - "Bash(cmd /c \"c:\\Android\\cmdline-tools\\latest\\bin\\sdkmanager.bat --list\")", - "Bash(cmd /c \"dir c:\\Android\\cmdline-tools\\latest\\bin\")", - "Bash(cmd /c \"dir c:\\Android\")", - "Bash(dir:*)", - "Bash(powershell -Command:*)", - "Bash(Select-String \"system-images\")", - "Bash(Select-Object -First 10)", - "Bash(powershell:*)", - "Bash(c:/Android/platform-tools/adb.exe devices:*)", - "Bash(c:/Android/platform-tools/adb.exe kill-server)", - "Bash(c:/Android/platform-tools/adb.exe start-server:*)", - "Bash(flutter run:*)", - "Bash(git commit:*)", - "Bash(docker-compose config:*)", - "Bash(docker compose config:*)", - "Bash(node -e:*)", - "Bash(wsl -e bash -c \"cd /mnt/c/Users/dong/Desktop/rwadurian/backend/services/identity-service && docker compose config --quiet && echo ''Docker Compose config is valid''\")", - "Bash(ls:*)", - "Bash(find:*)", - "Bash(wsl --list --verbose)", - "Bash(wsl -d Ubuntu -- bash -c \"echo ''WSL Ubuntu is running'' && cat /etc/os-release | head -3\")", - "Bash(wsl:*)", - "Bash(git push)", - "Bash(cat:*)", - "Bash(done)", - "Bash(timeout:*)", - "Bash(npm run build:*)", - "Bash(test:*)", - "Bash(npx prisma migrate dev:*)", - "Bash(DATABASE_URL=\"postgresql://user:pass@localhost:5432/db\" npx prisma migrate:*)", - "Bash(npm install:*)", - "Bash(npm run prisma:generate:*)", - "Bash(echo:*)", - "Bash(git checkout:*)", - "Bash(git reset:*)", - "Bash(docker exec:*)", - "Bash(docker build:*)", - "Bash(if [ -f nul ])", - "Bash(then rm nul)", - "Bash(else echo \"nul file not found\")", - "Bash(fi)", - "Bash(docker-compose:*)", - "Bash(c:/Android/platform-tools/adb.exe shell ping:*)", - "Bash(curl:*)", - "Bash(DATABASE_URL=\"postgresql://postgres:password@localhost:5432/rwa_identity?schema=public\" npx prisma migrate:*)" - ], - "deny": [], - "ask": [] - } -} +{ + "permissions": { + "allow": [ + "Bash(flutter build:*)", + "Bash(flutter clean:*)", + "Bash(git add:*)", + "Bash(flutter pub get:*)", + "Bash(flutter analyze:*)", + "Bash(git commit -m \"$(cat <<''EOF''\nfeat: 添加APK在线升级和遥测统计模块\n\nAPK升级模块 (lib/core/updater/):\n- 支持自建服务器和Google Play双渠道更新\n- 版本检测、APK下载、SHA-256校验、安装\n- 应用市场来源检测\n- 强制更新和普通更新对话框\n\n遥测模块 (lib/core/telemetry/):\n- 设备信息采集 (品牌、型号、系统版本、屏幕等)\n- 会话管理 (DAU日活统计)\n- 心跳服务 (实时在线人数统计)\n- 事件队列和批量上传\n- 远程配置热更新\n\nAndroid原生配置:\n- MainActivity.kt Platform Channel实现\n- FileProvider配置 (APK安装)\n- 权限配置 (INTERNET, REQUEST_INSTALL_PACKAGES)\n\n文档:\n- docs/backend_api_guide.md 后端API开发指南\n- docs/testing_guide.md 测试指南\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", + "Bash(mkdir:*)", + "Bash(keytool:*)", + "Bash(flutter doctor:*)", + "Bash(flutter emulators:*)", + "Bash(c:Androidemulatoremulator -list-avds)", + "Bash(flutter devices:*)", + "Bash(c:Androidcmdline-toolslatestbinsdkmanager.bat --list)", + "Bash(findstr:*)", + "Bash(cmd /c \"c:\\Android\\cmdline-tools\\latest\\bin\\sdkmanager.bat --list\")", + "Bash(cmd /c \"dir c:\\Android\\cmdline-tools\\latest\\bin\")", + "Bash(cmd /c \"dir c:\\Android\")", + "Bash(dir:*)", + "Bash(powershell -Command:*)", + "Bash(Select-String \"system-images\")", + "Bash(Select-Object -First 10)", + "Bash(powershell:*)", + "Bash(c:/Android/platform-tools/adb.exe devices:*)", + "Bash(c:/Android/platform-tools/adb.exe kill-server)", + "Bash(c:/Android/platform-tools/adb.exe start-server:*)", + "Bash(flutter run:*)", + "Bash(git commit:*)", + "Bash(docker-compose config:*)", + "Bash(docker compose config:*)", + "Bash(node -e:*)", + "Bash(wsl -e bash -c \"cd /mnt/c/Users/dong/Desktop/rwadurian/backend/services/identity-service && docker compose config --quiet && echo ''Docker Compose config is valid''\")", + "Bash(ls:*)", + "Bash(find:*)", + "Bash(wsl --list --verbose)", + "Bash(wsl -d Ubuntu -- bash -c \"echo ''WSL Ubuntu is running'' && cat /etc/os-release | head -3\")", + "Bash(wsl:*)", + "Bash(git push)", + "Bash(cat:*)", + "Bash(done)", + "Bash(timeout:*)", + "Bash(npm run build:*)", + "Bash(test:*)", + "Bash(npx prisma migrate dev:*)", + "Bash(DATABASE_URL=\"postgresql://user:pass@localhost:5432/db\" npx prisma migrate:*)", + "Bash(npm install:*)", + "Bash(npm run prisma:generate:*)", + "Bash(echo:*)", + "Bash(git checkout:*)", + "Bash(git reset:*)", + "Bash(docker exec:*)", + "Bash(docker build:*)", + "Bash(if [ -f nul ])", + "Bash(then rm nul)", + "Bash(else echo \"nul file not found\")", + "Bash(fi)", + "Bash(docker-compose:*)", + "Bash(c:/Android/platform-tools/adb.exe shell ping:*)", + "Bash(curl:*)", + "Bash(DATABASE_URL=\"postgresql://postgres:password@localhost:5432/rwa_identity?schema=public\" npx prisma migrate:*)", + "Bash(del \"c:\\Users\\dong\\Desktop\\rwadurian\\frontend\\mobile-app\\lib\\core\\services\\mpc_share_service.dart\")", + "Bash(dart compile exe:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/frontend/mobile-app/lib/features/auth/presentation/pages/wallet_created_page.dart b/frontend/mobile-app/lib/features/auth/presentation/pages/wallet_created_page.dart index e00b892b..1831a3f7 100644 --- a/frontend/mobile-app/lib/features/auth/presentation/pages/wallet_created_page.dart +++ b/frontend/mobile-app/lib/features/auth/presentation/pages/wallet_created_page.dart @@ -49,8 +49,8 @@ class WalletCreatedPage extends ConsumerWidget { void _shareToFriends(BuildContext context) { // 构建分享链接 (带推荐码) final shareLink = referralCode != null - ? 'https://rwa-durian.app/invite?code=$referralCode' - : 'https://rwa-durian.app/invite?seq=$userSerialNum'; + ? 'https://rwaapi.szaiai.com/invite?code=$referralCode' + : 'https://rwaapi.szaiai.com/invite?seq=$userSerialNum'; context.push( RoutePaths.share, diff --git a/frontend/mobile-app/linux/flutter/generated_plugin_registrant.cc b/frontend/mobile-app/linux/flutter/generated_plugin_registrant.cc index 438c4f25..3ccd5513 100644 --- a/frontend/mobile-app/linux/flutter/generated_plugin_registrant.cc +++ b/frontend/mobile-app/linux/flutter/generated_plugin_registrant.cc @@ -1,23 +1,23 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include -#include - -void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); - file_selector_plugin_register_with_registrar(file_selector_linux_registrar); - g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); - flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); - g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); - url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); -} +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); +} diff --git a/frontend/mobile-app/linux/flutter/generated_plugin_registrant.h b/frontend/mobile-app/linux/flutter/generated_plugin_registrant.h index a002cfd8..e0f0a47b 100644 --- a/frontend/mobile-app/linux/flutter/generated_plugin_registrant.h +++ b/frontend/mobile-app/linux/flutter/generated_plugin_registrant.h @@ -1,15 +1,15 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/frontend/mobile-app/linux/flutter/generated_plugins.cmake b/frontend/mobile-app/linux/flutter/generated_plugins.cmake index 63b88082..9ce94c49 100644 --- a/frontend/mobile-app/linux/flutter/generated_plugins.cmake +++ b/frontend/mobile-app/linux/flutter/generated_plugins.cmake @@ -1,26 +1,26 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - file_selector_linux - flutter_secure_storage_linux - url_launcher_linux -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux + flutter_secure_storage_linux + url_launcher_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/frontend/mobile-app/macos/Flutter/GeneratedPluginRegistrant.swift b/frontend/mobile-app/macos/Flutter/GeneratedPluginRegistrant.swift index d9976f31..87cdbc2b 100644 --- a/frontend/mobile-app/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/frontend/mobile-app/macos/Flutter/GeneratedPluginRegistrant.swift @@ -1,34 +1,34 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import connectivity_plus -import device_info_plus -import file_selector_macos -import flutter_secure_storage_macos -import local_auth_darwin -import mobile_scanner -import package_info_plus -import path_provider_foundation -import share_plus -import shared_preferences_foundation -import sqflite_darwin -import url_launcher_macos - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) - DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) - FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) - FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) - LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) - MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) - FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) - SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) - SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) - UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) -} +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import connectivity_plus +import device_info_plus +import file_selector_macos +import flutter_secure_storage_macos +import local_auth_darwin +import mobile_scanner +import package_info_plus +import path_provider_foundation +import share_plus +import shared_preferences_foundation +import sqflite_darwin +import url_launcher_macos + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) + MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) +} diff --git a/frontend/mobile-app/windows/flutter/generated_plugin_registrant.cc b/frontend/mobile-app/windows/flutter/generated_plugin_registrant.cc index 34521606..4124c5b9 100644 --- a/frontend/mobile-app/windows/flutter/generated_plugin_registrant.cc +++ b/frontend/mobile-app/windows/flutter/generated_plugin_registrant.cc @@ -1,32 +1,32 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include -#include -#include -#include -#include -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - ConnectivityPlusWindowsPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); - FileSelectorWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FileSelectorWindows")); - FlutterSecureStorageWindowsPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); - LocalAuthPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("LocalAuthPlugin")); - PermissionHandlerWindowsPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); - SharePlusWindowsPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); - UrlLauncherWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("UrlLauncherWindows")); -} +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include +#include +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + ConnectivityPlusWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + LocalAuthPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("LocalAuthPlugin")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/frontend/mobile-app/windows/flutter/generated_plugin_registrant.h b/frontend/mobile-app/windows/flutter/generated_plugin_registrant.h index 99f8f84d..dc139d85 100644 --- a/frontend/mobile-app/windows/flutter/generated_plugin_registrant.h +++ b/frontend/mobile-app/windows/flutter/generated_plugin_registrant.h @@ -1,15 +1,15 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/frontend/mobile-app/windows/flutter/generated_plugins.cmake b/frontend/mobile-app/windows/flutter/generated_plugins.cmake index eb6f7019..4aa2827f 100644 --- a/frontend/mobile-app/windows/flutter/generated_plugins.cmake +++ b/frontend/mobile-app/windows/flutter/generated_plugins.cmake @@ -1,30 +1,30 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - connectivity_plus - file_selector_windows - flutter_secure_storage_windows - local_auth_windows - permission_handler_windows - share_plus - url_launcher_windows -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + connectivity_plus + file_selector_windows + flutter_secure_storage_windows + local_auth_windows + permission_handler_windows + share_plus + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin)