diff --git a/.env b/.env
new file mode 100644
index 0000000..53a6945
--- /dev/null
+++ b/.env
@@ -0,0 +1 @@
+API_ENDPOINT=http://192.168.31.115:18080/api
\ No newline at end of file
diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000..a102646
--- /dev/null
+++ b/.env.production
@@ -0,0 +1 @@
+API_ENDPOINT=https://api.memorywake.com/api
\ No newline at end of file
diff --git a/.gitea/workflows/prod.yaml b/.gitea/workflows/prod.yaml
new file mode 100644
index 0000000..957e503
--- /dev/null
+++ b/.gitea/workflows/prod.yaml
@@ -0,0 +1,36 @@
+name: Prod Deploy
+run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
+on:
+ push:
+ tags:
+ - 'releases/*'
+
+jobs:
+ Explore-Gitea-Actions:
+ runs-on: self_hosted
+ steps:
+ - run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
+ - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
+ - run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
+ - name: Check out repository code
+ uses: https://git.fairclip.cn/mirrors/actions-checkout@v4
+ - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
+ - run: echo "🖥️ The workflow is now ready to test your code on the runner."
+ - name: List files in the repository
+ run: |
+ ls ${{ gitea.workspace }}
+ - name: Build Docker Image
+ run: |
+ echo "Building the Docker image..."
+ tag_name=${{ gitea.ref_name }}
+ tag_name=$(echo "${{ gitea.ref_name }}" | tr '/' '-')
+ docker build -t hub.fairclip.cn/memowake/memowake-front:${tag_name} -f dockerfiles/prod.Dockerfile .
+ docker push hub.fairclip.cn/memowake/memowake-front:${tag_name}
+ echo "Docker image built successfully!"
+ - name: Deploy
+ run: |
+ echo "Deploying the project..."
+ tag_name=${{ gitea.ref_name }}
+ tag_name=$(echo "${{ gitea.ref_name }}" | tr '/' '-')
+ bash ./scripts/prod_deploy.sh ${tag_name}
+ echo "Deploy successful!"
\ No newline at end of file
diff --git a/app.config.js b/app.config.js
new file mode 100644
index 0000000..aee3564
--- /dev/null
+++ b/app.config.js
@@ -0,0 +1,7 @@
+// app.config.js
+export default ({ config }) => ({
+ ...config,
+ extra: {
+ API_ENDPOINT: process.env.API_ENDPOINT || "http://192.168.31.115:18080/api"
+ }
+});
\ No newline at end of file
diff --git a/app/(tabs)/download.tsx b/app/(tabs)/download.tsx
new file mode 100644
index 0000000..35cd9d9
--- /dev/null
+++ b/app/(tabs)/download.tsx
@@ -0,0 +1,63 @@
+import AndroidLogo from '@/assets/icons/svg/android.svg';
+import AppleLogo from '@/assets/icons/svg/apple.svg';
+import MemoIP from '@/assets/icons/svg/memo-ip.svg';
+import { LinearGradient } from 'expo-linear-gradient';
+import { useTranslation } from 'react-i18next';
+import { Linking, Text, TouchableOpacity, View } from 'react-native';
+
+const IOS_APP_STORE_URL = 'https://apps.apple.com/cn/app/id6748205761';
+const ANDROID_APK_URL = 'https://cdn.memorywake.com/apks/application-f086a38c-dac1-43f1-9d24-e4378c2ce121.apk';
+export default function DownloadScreen() {
+ const handleIOSDownload = () => {
+ Linking.openURL(IOS_APP_STORE_URL);
+ };
+
+ const handleAndroidDownload = () => {
+ Linking.openURL(ANDROID_APK_URL);
+ };
+
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+
+
+ MemoWake
+
+
+ {t('desc', { ns: 'download' })}
+
+
+
+
+
+
+
+ {t('ios', { ns: 'download' })}
+
+
+
+
+
+
+ {t('android', { ns: 'download' })}
+
+
+
+
+ );
+}
diff --git a/assets/icons/svg/android.svg b/assets/icons/svg/android.svg
new file mode 100644
index 0000000..59f4ee2
--- /dev/null
+++ b/assets/icons/svg/android.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/svg/apple.svg b/assets/icons/svg/apple.svg
new file mode 100644
index 0000000..b590be7
--- /dev/null
+++ b/assets/icons/svg/apple.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dockerfiles/prod.Dockerfile b/dockerfiles/prod.Dockerfile
new file mode 100644
index 0000000..84f7180
--- /dev/null
+++ b/dockerfiles/prod.Dockerfile
@@ -0,0 +1,18 @@
+# 第一阶段:构建 Expo Web 静态文件
+FROM docker.fairclip.cn/node:22 AS builder
+WORKDIR /app
+COPY package.json .
+# 设置npm源
+RUN npm config set registry http://192.168.31.115:8081/repository/npm/
+RUN npm install -g expo-cli && npm install
+COPY . .
+RUN cp .env.production .env
+ENV API_ENDPOINT=https://api.memorywake.com/api
+RUN npx expo export -p web
+
+# 第二阶段:使用 nginx 作为 Web 服务器
+FROM docker.fairclip.cn/nginx:1.29-alpine
+COPY --from=builder /app/dist /usr/share/nginx/html
+COPY nginx.conf /etc/nginx/nginx.conf
+EXPOSE 80
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/i18n/index.ts b/i18n/index.ts
index 8b5ff26..02374a2 100644
--- a/i18n/index.ts
+++ b/i18n/index.ts
@@ -17,7 +17,7 @@ i18n
resources: translations,
// 支持命名空间
- ns: ['common', 'example'],
+ ns: ['common', 'example', 'download'],
defaultNS: 'common',
// 设置默认语言为中文
diff --git a/i18n/locales/en/download.json b/i18n/locales/en/download.json
new file mode 100644
index 0000000..faaec14
--- /dev/null
+++ b/i18n/locales/en/download.json
@@ -0,0 +1,6 @@
+{
+ "title": "Download Our App",
+ "desc": "Get the full experience by downloading our app on your favorite platform.",
+ "ios": "Download for iOS",
+ "android": "Download for Android"
+}
\ No newline at end of file
diff --git a/i18n/locales/zh/download.json b/i18n/locales/zh/download.json
new file mode 100644
index 0000000..3b1a5d0
--- /dev/null
+++ b/i18n/locales/zh/download.json
@@ -0,0 +1,6 @@
+{
+ "title": "下载我们的应用",
+ "desc": "在您喜欢的平台上下载我们的应用,以获得完整的体验。",
+ "ios": "下载 iOS 版",
+ "android": "下载 Android 版"
+}
\ No newline at end of file
diff --git a/i18n/translations-generated.ts b/i18n/translations-generated.ts
index be54939..4edacca 100644
--- a/i18n/translations-generated.ts
+++ b/i18n/translations-generated.ts
@@ -3,6 +3,7 @@
import enAdmin from './locales/en/admin.json';
import enAsk from './locales/en/ask.json';
import enCommon from './locales/en/common.json';
+import enDownload from './locales/en/download.json';
import enExample from './locales/en/example.json';
import enFairclip from './locales/en/fairclip.json';
import enLanding from './locales/en/landing.json';
@@ -12,6 +13,7 @@ import enUpload from './locales/en/upload.json';
import zhAdmin from './locales/zh/admin.json';
import zhAsk from './locales/zh/ask.json';
import zhCommon from './locales/zh/common.json';
+import zhDownload from './locales/zh/download.json';
import zhExample from './locales/zh/example.json';
import zhFairclip from './locales/zh/fairclip.json';
import zhLanding from './locales/zh/landing.json';
@@ -22,25 +24,27 @@ import zhUpload from './locales/zh/upload.json';
const translations = {
en: {
admin: enAdmin,
+ ask: enAsk,
common: enCommon,
+ download: enDownload,
example: enExample,
fairclip: enFairclip,
landing: enLanding,
login: enLogin,
personal: enPersonal,
- upload: enUpload,
- ask: enAsk
+ upload: enUpload
},
zh: {
admin: zhAdmin,
+ ask: zhAsk,
common: zhCommon,
+ download: zhDownload,
example: zhExample,
fairclip: zhFairclip,
landing: zhLanding,
login: zhLogin,
personal: zhPersonal,
- upload: zhUpload,
- ask: zhAsk
+ upload: zhUpload
},
};
diff --git a/lib/server-api-util.ts b/lib/server-api-util.ts
index 18d045c..b122f7f 100644
--- a/lib/server-api-util.ts
+++ b/lib/server-api-util.ts
@@ -1,4 +1,5 @@
import { setCredentials } from '@/features/auth/authSlice';
+import Constants from 'expo-constants';
import * as SecureStore from 'expo-secure-store';
import { Platform } from 'react-native';
import Toast from 'react-native-toast-message';
@@ -23,7 +24,8 @@ export interface PagedResult {
}
// 获取.env文件中的变量
-export const API_ENDPOINT = "http://192.168.31.115:18080/api"
+
+export const API_ENDPOINT = Constants.expoConfig?.extra?.API_ENDPOINT || "http://192.168.31.115:18080/api";
// 更新 access_token 的逻辑 - 用于React组件中
export const useAuthToken = async(message: string | null) => {
diff --git a/package-lock.json b/package-lock.json
index d25ad73..09f375c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8889,6 +8889,17 @@
"react": "*"
}
},
+ "node_modules/expo-linear-gradient": {
+ "version": "14.1.5",
+ "resolved": "http://192.168.31.115:8081/repository/npm/expo-linear-gradient/-/expo-linear-gradient-14.1.5.tgz",
+ "integrity": "sha512-BSN3MkSGLZoHMduEnAgfhoj3xqcDWaoICgIr4cIYEx1GcHfKMhzA/O4mpZJ/WC27BP1rnAqoKfbclk1eA70ndQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/expo-linking": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-7.1.7.tgz",
diff --git a/scripts/prod_deploy.sh b/scripts/prod_deploy.sh
new file mode 100644
index 0000000..4ebfc4a
--- /dev/null
+++ b/scripts/prod_deploy.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -x
+
+TAG=${1:-latest}
+
+CONTROLPANEL_HOST="101.132.185.243"
+CONTROLPANEL_USER="ecs-user"
+CONTROLPANEL_SSH_KEY="~/.ssh/id_ed25519"
+
+# SSH到CONTROLPANEL_HOST执行以下命令
+# helm install memowake-front . -n memowake
+ssh ${CONTROLPANEL_USER}@${CONTROLPANEL_HOST} "cd /home/ecs-user/infra-deploy/memowake-front && helm upgrade memowake-front . -n memowake --set image.tag=${TAG}"
\ No newline at end of file