fix: gộp các nút của thành viên và guest vào một

This commit is contained in:
2026-06-27 15:37:00 +07:00
parent 5f49070a98
commit 400a3d098d
33 changed files with 1142 additions and 250 deletions
+117
View File
@@ -0,0 +1,117 @@
# To AI Agent: Implement Server-Hosted Android APK Download Button and Automated Build Deployment Pipeline
## 1. Context & Feature Objective
We are adding a native Android app distribution workflow directly from our self-hosted server backend. Instead of relying purely on app stores, users visiting the web version from an Android device must be able to download the official compiled `.apk` file directly.
**Objective:** 1. **Backend Asset Exposure:** Configure a secure, static file directory on the Node.js/Express server to host the production `.apk` binary.
2. **Build Pipeline Link Automation:** Create a post-build deployment shell script. Every time a new production Android APK is generated (`release`), the script must automatically rename and copy it to the backend's public distribution folder under a persistent file pointer name (`yotrip-latest.apk`).
3. **Frontend Action Button:** Add an interactive "Tải ứng dụng Android" action row with a download icon inside both the Member and Guest profile menu sheets.
---
## 2. Technical Architecture & Implementation Steps
[Android Build Output] ➔ [deploy-apk.sh Script] ➔ [Backend public/downloads/yotrip-latest.apk]
[Frontend UI Button] ➔ ➔ ➔ [Triggers HTTP GET Request] ➔ ➔ ➔ ➔ ➔ ┛
### Step 1: Configure Backend Static Asset Folder
Locate the core server setup file (e.g., `server.ts`, `app.ts`, or `index.js`). Ensure a dedicated folder path named `public/downloads` is created and mapped to express static file serving handlers:
```typescript
import express from 'express';
import path from 'path';
const app = express();
// Ensure the directory exists: public/downloads/
const downloadsDir = path.join(__dirname, '../public/downloads');
/* ✅ BACKEND STATIC MIDDLEWARE REGISTRATION
This exposes the file at: [https://yourdomain.com/downloads/yotrip-latest.apk](https://yourdomain.com/downloads/yotrip-latest.apk)
*/
app.use('/downloads', express.static(downloadsDir, {
setHeaders: (res) => {
// Force browser engines to download the file directly instead of trying to parse it
res.set('Content-Type', 'application/vnd.android.package-archive');
res.set('Content-Disposition', 'attachment; filename="yotrip-latest.apk"');
}
}));
### Step 2: Automate APK Release Mapping Link (Post-Build Script)
Create an automation script file named scripts/deploy-apk.sh in the root environment. This script runs instantly after your Android compiler output is generated (e.g., via Gradle ./gradlew assembleRelease or Capacitor/Cordova build actions):
#!/bin/bash
# Define relative path coordinates
ANDROID_OUTPUT_PATH="./android/app/build/outputs/apk/release/app-release.apk"
BACKEND_TARGET_DIR="./backend/public/downloads"
TARGET_FILE_NAME="yotrip-latest.apk"
echo "🚀 Starting automated post-build Android deployment pipeline..."
# 1. Verify compiler target exists
if [ -f "$ANDROID_OUTPUT_PATH" ]; then
# 2. Ensure target storage folder structure is active
mkdir -p "$BACKEND_TARGET_DIR"
# 3. Copy and force overwrite the old production bundle with the updated version
cp -f "$ANDROID_OUTPUT_PATH" "$BACKEND_TARGET_DIR/$TARGET_FILE_NAME"
echo "✅ Success! New build copied safely to $BACKEND_TARGET_DIR/$TARGET_FILE_NAME"
echo "🔗 Direct Download Link Active: /downloads/$TARGET_FILE_NAME"
else
echo "❌ Critical Error: Android build output artifact not found at $ANDROID_OUTPUT_PATH"
exit 1
fi
Add "build:android": "cd android && ./gradlew assembleRelease && cd .. && sh scripts/deploy-apk.sh" inside package.json scripts matrix for unified execution hooks.
### Step 3: Add Download Trigger into Frontend UI (MapProfileDropdown.tsx)
Locate the unified dropdown menu component created in the previous layout consolidation phase. Inject the direct-download operational action rows:
// Define the static destination asset link helper
const APK_DOWNLOAD_URL = `${process.env.REACT_APP_API_BASE_URL || ''}/downloads/yotrip-latest.apk`;
/* --- INSIDE AUTHENTICATED MEMBER STACK SECTION --- */
<div className="flex flex-col space-y-1">
{/* Existing Dashboard, Profile, Create Tour rows... */}
{/* NEW: ANDROID APK DIRECT DOWNLOAD BUTTON */}
<a
href={APK_DOWNLOAD_URL}
download="yotrip.apk"
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-lg text-left text-xs text-slate-200 transition-colors"
>
<svg xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" className="w-4 h-4 text-green-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
<span>Tải ứng dụng Android (APK)</span>
</a>
</div>
/* --- INSIDE ANONYMOUS GUEST STACK SECTION --- */
<div className="flex flex-col space-y-1">
{/* Existing Guest language/theme configurations... */}
<div className="h-[1px] bg-slate-800 my-1 mx-2" />
{/* NEW: GUEST STATE ANDROID APK DOWNLOAD BUTTON */}
<a
href={APK_DOWNLOAD_URL}
download="yotrip.apk"
className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-lg text-left text-xs text-slate-200 transition-colors"
>
<svg xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" className="w-4 h-4 text-green-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
<span>Cài đặt bản Android (.APK)</span>
</a>
{/* Existing Register/Login Button row below... */}
</div>
## 3. Verification & Acceptance Criteria for AI Agent
[ ] Deployment Script Validation: Run the build sequence script. Confirm that backend/public/downloads/yotrip-latest.apk updates its file modification timestamp matching the compiler execution timing logs.
[ ] Direct Download Header Safety: Trigger a request to GET /downloads/yotrip-latest.apk. The network tab response must show content-type: application/vnd.android.package-archive to guarantee mobile devices instantly trigger package installation workflows.
[ ] UI Integrity Test: Open the drop menu layout panel on a mobile simulator frame. Confirm that clicking the text icon row acts as a standard link target that downloads the binary file smoothly without breaking route navigation states.