mirror of
https://github.com/zimplexing/OrionTV.git
synced 2026-02-04 03:36:29 +08:00
refactor(config): clean up and standardize code formatting in configuration files
This commit is contained in:
91
.github/workflows/build-apk.yml
vendored
91
.github/workflows/build-apk.yml
vendored
@@ -7,7 +7,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build_tv:
|
||||
direct_build:
|
||||
name: Build Android TV APK
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -34,97 +34,24 @@ jobs:
|
||||
java-version: "17"
|
||||
|
||||
- name: Prebuild TV App
|
||||
run: yarn prebuild
|
||||
run: yarn prebuild-tv
|
||||
|
||||
- name: Build TV APK
|
||||
run: yarn build-tv
|
||||
run: yarn build-local
|
||||
|
||||
- name: Upload TV APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: orion-tv-apk
|
||||
path: android/app/build/outputs/apk/release/app-release.apk
|
||||
|
||||
build_mobile:
|
||||
name: Build Android Mobile APK
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "yarn"
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Get version from package.json
|
||||
id: package-version
|
||||
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Setup JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: "17"
|
||||
|
||||
- name: Prebuild Mobile App
|
||||
run: yarn prebuild
|
||||
|
||||
- name: Build Mobile APK
|
||||
run: yarn build-mobile
|
||||
|
||||
- name: Upload Mobile APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: orion-mobile-apk
|
||||
path: android/app/build/outputs/apk/release/app-release.apk
|
||||
|
||||
release:
|
||||
name: Create Release
|
||||
needs: [build_tv, build_mobile]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get version from package.json
|
||||
id: package-version
|
||||
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download TV APK
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: orion-tv-apk
|
||||
path: artifacts/tv
|
||||
|
||||
- name: Download Mobile APK
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: orion-mobile-apk
|
||||
path: artifacts/mobile
|
||||
|
||||
- name: Rename APK files
|
||||
- name: Rename APK file
|
||||
run: |
|
||||
mv artifacts/tv/app-release.apk artifacts/orionTV-tv.${{ steps.package-version.outputs.version }}.apk
|
||||
mv artifacts/mobile/app-release.apk artifacts/orionTV-mobile.${{ steps.package-version.outputs.version }}.apk
|
||||
mkdir -p artifacts
|
||||
cp android/app/build/outputs/apk/release/app-release.apk artifacts/orionTV.${{ steps.package-version.outputs.version }}.apk
|
||||
|
||||
- name: Create Release and Upload APKs
|
||||
- name: Create Release and Upload APK
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ steps.package-version.outputs.version }}
|
||||
name: Release v${{ steps.package-version.outputs.version }}
|
||||
body: |
|
||||
Automated release for version v${{ steps.package-version.outputs.version }}.
|
||||
- orionTV-tv.${{ steps.package-version.outputs.version }}.apk - Android TV版本
|
||||
- orionTV-mobile.${{ steps.package-version.outputs.version }}.apk - 手机/平板版本
|
||||
body: Automated release for version v${{ steps.package-version.outputs.version }}.
|
||||
draft: false
|
||||
prerelease: false
|
||||
files: |
|
||||
artifacts/orionTV-tv.${{ steps.package-version.outputs.version }}.apk
|
||||
artifacts/orionTV-mobile.${{ steps.package-version.outputs.version }}.apk
|
||||
files: artifacts/orionTV.${{ steps.package-version.outputs.version }}.apk
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { View, StyleSheet, Platform, ActivityIndicator } from "react-native";
|
||||
import { ThemedText } from "../ThemedText";
|
||||
import { StyledButton } from "../StyledButton";
|
||||
import { useUpdateStore } from "@/stores/updateStore";
|
||||
import { UPDATE_CONFIG } from "@/constants/UpdateConfig";
|
||||
// import { UPDATE_CONFIG } from "@/constants/UpdateConfig";
|
||||
|
||||
export function UpdateSection() {
|
||||
const { currentVersion, remoteVersion, updateAvailable, downloading, downloadProgress, checkForUpdate } =
|
||||
|
||||
@@ -1,39 +1,36 @@
|
||||
import { DeviceUtils } from '@/utils/DeviceUtils';
|
||||
|
||||
export const UPDATE_CONFIG = {
|
||||
// 自动检查更新
|
||||
AUTO_CHECK: true,
|
||||
|
||||
|
||||
// 检查更新间隔(毫秒)
|
||||
CHECK_INTERVAL: 12 * 60 * 60 * 1000, // 12小时
|
||||
|
||||
|
||||
// GitHub相关URL
|
||||
GITHUB_RAW_URL: 'https://ghfast.top/https://raw.githubusercontent.com/zimplexing/OrionTV/refs/heads/master/package.json',
|
||||
|
||||
GITHUB_RAW_URL:
|
||||
"https://ghfast.top/https://raw.githubusercontent.com/zimplexing/OrionTV/refs/heads/master/package.json",
|
||||
|
||||
// 获取平台特定的下载URL
|
||||
getDownloadUrl(version: string): string {
|
||||
const isTV = DeviceUtils.isTV();
|
||||
const platform = isTV ? 'tv' : 'mobile';
|
||||
return `https://ghfast.top/https://github.com/zimplexing/OrionTV/releases/download/v${version}/orionTV-${platform}.${version}.apk`;
|
||||
return `https://ghfast.top/https://github.com/zimplexing/OrionTV/releases/download/v${version}/orionTV.${version}.apk`;
|
||||
},
|
||||
|
||||
|
||||
// 是否显示更新日志
|
||||
SHOW_RELEASE_NOTES: true,
|
||||
|
||||
|
||||
// 是否允许跳过版本
|
||||
ALLOW_SKIP_VERSION: true,
|
||||
|
||||
|
||||
// 下载超时时间(毫秒)
|
||||
DOWNLOAD_TIMEOUT: 10 * 60 * 1000, // 10分钟
|
||||
|
||||
|
||||
// 是否在WIFI下自动下载
|
||||
AUTO_DOWNLOAD_ON_WIFI: false,
|
||||
|
||||
|
||||
// 更新通知设置
|
||||
NOTIFICATION: {
|
||||
ENABLED: true,
|
||||
TITLE: 'OrionTV 更新',
|
||||
DOWNLOADING_TEXT: '正在下载新版本...',
|
||||
DOWNLOAD_COMPLETE_TEXT: '下载完成,点击安装',
|
||||
TITLE: "OrionTV 更新",
|
||||
DOWNLOADING_TEXT: "正在下载新版本...",
|
||||
DOWNLOAD_COMPLETE_TEXT: "下载完成,点击安装",
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Dimensions, Platform } from 'react-native';
|
||||
import { useState, useEffect } from "react";
|
||||
import { Dimensions, Platform } from "react-native";
|
||||
|
||||
export type DeviceType = 'mobile' | 'tablet' | 'tv';
|
||||
export type DeviceType = "mobile" | "tablet" | "tv";
|
||||
|
||||
export interface ResponsiveConfig {
|
||||
deviceType: DeviceType;
|
||||
@@ -17,40 +17,44 @@ export interface ResponsiveConfig {
|
||||
const BREAKPOINTS = {
|
||||
mobile: { min: 0, max: 767 },
|
||||
tablet: { min: 768, max: 1023 },
|
||||
tv: { min: 1024, max: Infinity }
|
||||
tv: { min: 1024, max: Infinity },
|
||||
};
|
||||
|
||||
const getDeviceType = (width: number): DeviceType => {
|
||||
const isTV = process.env.EXPO_TV === '1' || Platform.isTV;
|
||||
if (isTV) return 'tv';
|
||||
|
||||
if (width >= BREAKPOINTS.tv.min) return 'tv';
|
||||
if (width >= BREAKPOINTS.tablet.min) return 'tablet';
|
||||
return 'mobile';
|
||||
if (Platform.isTV) return "tv";
|
||||
|
||||
if (width >= BREAKPOINTS.tv.min) return "tv";
|
||||
if (width >= BREAKPOINTS.tablet.min) return "tablet";
|
||||
return "mobile";
|
||||
};
|
||||
|
||||
const getLayoutConfig = (deviceType: DeviceType, width: number, height: number, isPortrait: boolean): ResponsiveConfig => {
|
||||
const spacing = deviceType === 'mobile' ? 8 : deviceType === 'tablet' ? 12 : 16;
|
||||
|
||||
const getLayoutConfig = (
|
||||
deviceType: DeviceType,
|
||||
width: number,
|
||||
height: number,
|
||||
isPortrait: boolean
|
||||
): ResponsiveConfig => {
|
||||
const spacing = deviceType === "mobile" ? 8 : deviceType === "tablet" ? 12 : 16;
|
||||
|
||||
let columns: number;
|
||||
let cardWidth: number;
|
||||
let cardHeight: number;
|
||||
|
||||
switch (deviceType) {
|
||||
case 'mobile':
|
||||
case "mobile":
|
||||
columns = isPortrait ? 3 : 4;
|
||||
// 使用flex布局,卡片可以更大一些来填充空间
|
||||
cardWidth = (width - spacing) / columns * 0.85; // 增大到85%
|
||||
cardWidth = ((width - spacing) / columns) * 0.85; // 增大到85%
|
||||
cardHeight = cardWidth * 1.2; // 5:6 aspect ratio (reduced from 2:3)
|
||||
break;
|
||||
|
||||
case 'tablet':
|
||||
|
||||
case "tablet":
|
||||
columns = isPortrait ? 3 : 4;
|
||||
cardWidth = (width - spacing) / columns * 0.85; // 增大到85%
|
||||
cardWidth = ((width - spacing) / columns) * 0.85; // 增大到85%
|
||||
cardHeight = cardWidth * 1.4; // slightly less tall ratio
|
||||
break;
|
||||
|
||||
case 'tv':
|
||||
|
||||
case "tv":
|
||||
default:
|
||||
columns = 5;
|
||||
cardWidth = 160; // Fixed width for TV
|
||||
@@ -72,12 +76,12 @@ const getLayoutConfig = (deviceType: DeviceType, width: number, height: number,
|
||||
|
||||
export const useResponsiveLayout = (): ResponsiveConfig => {
|
||||
const [dimensions, setDimensions] = useState(() => {
|
||||
const { width, height } = Dimensions.get('window');
|
||||
const { width, height } = Dimensions.get("window");
|
||||
return { width, height };
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = Dimensions.addEventListener('change', ({ window }) => {
|
||||
const subscription = Dimensions.addEventListener("change", ({ window }) => {
|
||||
setDimensions({ width: window.width, height: window.height });
|
||||
});
|
||||
|
||||
@@ -87,7 +91,7 @@ export const useResponsiveLayout = (): ResponsiveConfig => {
|
||||
const { width, height } = dimensions;
|
||||
const isPortrait = height > width;
|
||||
const deviceType = getDeviceType(width);
|
||||
|
||||
|
||||
return getLayoutConfig(deviceType, width, height, isPortrait);
|
||||
};
|
||||
|
||||
@@ -100,31 +104,31 @@ export const useResponsiveValue = <T>(values: { mobile: T; tablet: T; tv: T }):
|
||||
// Utility hook for responsive styles
|
||||
export const useResponsiveStyles = () => {
|
||||
const config = useResponsiveLayout();
|
||||
|
||||
|
||||
return {
|
||||
// Common responsive styles
|
||||
container: {
|
||||
paddingHorizontal: config.spacing,
|
||||
},
|
||||
|
||||
|
||||
// Card styles
|
||||
cardContainer: {
|
||||
width: config.cardWidth,
|
||||
height: config.cardHeight,
|
||||
marginBottom: config.spacing,
|
||||
},
|
||||
|
||||
|
||||
// Grid styles
|
||||
gridContainer: {
|
||||
paddingHorizontal: config.spacing / 2,
|
||||
},
|
||||
|
||||
|
||||
// Typography
|
||||
titleFontSize: config.deviceType === 'mobile' ? 18 : config.deviceType === 'tablet' ? 22 : 28,
|
||||
bodyFontSize: config.deviceType === 'mobile' ? 14 : config.deviceType === 'tablet' ? 16 : 18,
|
||||
|
||||
titleFontSize: config.deviceType === "mobile" ? 18 : config.deviceType === "tablet" ? 22 : 28,
|
||||
bodyFontSize: config.deviceType === "mobile" ? 14 : config.deviceType === "tablet" ? 16 : 18,
|
||||
|
||||
// Spacing
|
||||
sectionSpacing: config.deviceType === 'mobile' ? 16 : config.deviceType === 'tablet' ? 20 : 24,
|
||||
sectionSpacing: config.deviceType === "mobile" ? 16 : config.deviceType === "tablet" ? 20 : 24,
|
||||
itemSpacing: config.spacing,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Learn more https://docs.expo.io/guides/customizing-metro
|
||||
const {getDefaultConfig} = require('expo/metro-config');
|
||||
const path = require('path');
|
||||
const { getDefaultConfig } = require("expo/metro-config");
|
||||
const path = require("path");
|
||||
|
||||
// Find the project and workspace directories
|
||||
// eslint-disable-next-line no-undef
|
||||
@@ -16,24 +16,24 @@ const config = getDefaultConfig(projectRoot);
|
||||
// Metro will still resolve source files with standard extensions
|
||||
// as usual if TV-specific files are not found for a module.
|
||||
//
|
||||
if (process.env?.EXPO_TV === '1') {
|
||||
const originalSourceExts = config.resolver.sourceExts;
|
||||
const tvSourceExts = [
|
||||
...originalSourceExts.map((e) => `tv.${e}`),
|
||||
...originalSourceExts,
|
||||
];
|
||||
config.resolver.sourceExts = tvSourceExts;
|
||||
}
|
||||
// if (process.env?.EXPO_TV === '1') {
|
||||
// const originalSourceExts = config.resolver.sourceExts;
|
||||
// const tvSourceExts = [
|
||||
// ...originalSourceExts.map((e) => `tv.${e}`),
|
||||
// ...originalSourceExts,
|
||||
// ];
|
||||
// config.resolver.sourceExts = tvSourceExts;
|
||||
// }
|
||||
|
||||
// This can be replaced with `find-yarn-workspace-root`
|
||||
const monorepoRoot = path.resolve(projectRoot, '../..');
|
||||
const monorepoRoot = path.resolve(projectRoot, "../..");
|
||||
|
||||
// 1. Watch all files within the monorepo
|
||||
config.watchFolders = [monorepoRoot];
|
||||
// 2. Let Metro know where to resolve packages and in what order
|
||||
config.resolver.nodeModulesPaths = [
|
||||
path.resolve(projectRoot, 'node_modules'),
|
||||
path.resolve(monorepoRoot, 'node_modules'),
|
||||
path.resolve(projectRoot, "node_modules"),
|
||||
path.resolve(monorepoRoot, "node_modules"),
|
||||
];
|
||||
config.resolver.disableHierarchicalLookup = true;
|
||||
|
||||
|
||||
20
package.json
20
package.json
@@ -4,20 +4,12 @@
|
||||
"main": "expo-router/entry",
|
||||
"version": "1.3.0",
|
||||
"scripts": {
|
||||
"start": "EXPO_USE_METRO_WORKSPACE_ROOT=1 expo start",
|
||||
"start-tv": "EXPO_TV=1 EXPO_USE_METRO_WORKSPACE_ROOT=1 expo start",
|
||||
"start-mobile": "EXPO_USE_METRO_WORKSPACE_ROOT=1 expo start --tunnel",
|
||||
"android": "EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:android",
|
||||
"android-tv": "EXPO_TV=1 EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:android",
|
||||
"android-mobile": "EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:android --device",
|
||||
"ios": "EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:ios",
|
||||
"ios-tv": "EXPO_TV=1 EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:ios",
|
||||
"ios-mobile": "EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:ios --device",
|
||||
"prebuild": "EXPO_USE_METRO_WORKSPACE_ROOT=1 expo prebuild --clean && yarn copy-config",
|
||||
"start": "EXPO_TV=1 EXPO_USE_METRO_WORKSPACE_ROOT=1 expo start",
|
||||
"android": "EXPO_TV=1 EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:android",
|
||||
"ios": "EXPO_TV=1 EXPO_USE_METRO_WORKSPACE_ROOT=1 expo run:ios",
|
||||
"prebuild": "EXPO_TV=1 EXPO_USE_METRO_WORKSPACE_ROOT=1 expo prebuild --clean && yarn copy-config",
|
||||
"copy-config": "cp -r xml/* android/app/src/*",
|
||||
"build": "cd android && ./gradlew assembleRelease",
|
||||
"build-tv": "EXPO_TV=1 yarn prebuild && cd android && ./gradlew assembleRelease",
|
||||
"build-mobile": "yarn prebuild && cd android && ./gradlew assembleRelease",
|
||||
"build": "EXPO_TV=1 yarn prebuild && cd android && ./gradlew assembleRelease",
|
||||
"build-debug": "cd android && ./gradlew assembleDebug",
|
||||
"test": "jest --watchAll",
|
||||
"test-ci": "jest --ci --coverage --no-cache",
|
||||
@@ -90,4 +82,4 @@
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,39 @@
|
||||
import { Platform, Dimensions } from 'react-native';
|
||||
import { DeviceType } from '@/hooks/useResponsiveLayout';
|
||||
import { Platform, Dimensions } from "react-native";
|
||||
import { DeviceType } from "@/hooks/useResponsiveLayout";
|
||||
|
||||
export const DeviceUtils = {
|
||||
/**
|
||||
* 检测当前设备类型
|
||||
*/
|
||||
getDeviceType(): DeviceType {
|
||||
const isTV = process.env.EXPO_TV === '1' || Platform.isTV;
|
||||
if (isTV) return 'tv';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
if (width >= 1024) return 'tv';
|
||||
if (width >= 768) return 'tablet';
|
||||
return 'mobile';
|
||||
// if (Platform.isTV) return "tv";
|
||||
|
||||
const { width } = Dimensions.get("window");
|
||||
|
||||
if (width >= 1024) return "tv";
|
||||
if (width >= 768) return "tablet";
|
||||
return "mobile";
|
||||
},
|
||||
|
||||
/**
|
||||
* 检测是否为TV环境
|
||||
*/
|
||||
isTV(): boolean {
|
||||
return this.getDeviceType() === 'tv';
|
||||
return this.getDeviceType() === "tv";
|
||||
},
|
||||
|
||||
/**
|
||||
* 检测是否为移动设备
|
||||
*/
|
||||
isMobile(): boolean {
|
||||
return this.getDeviceType() === 'mobile';
|
||||
return this.getDeviceType() === "mobile";
|
||||
},
|
||||
|
||||
/**
|
||||
* 检测是否为平板设备
|
||||
*/
|
||||
isTablet(): boolean {
|
||||
return this.getDeviceType() === 'tablet';
|
||||
return this.getDeviceType() === "tablet";
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -56,11 +56,11 @@ export const DeviceUtils = {
|
||||
getMinTouchTargetSize(): number {
|
||||
const deviceType = this.getDeviceType();
|
||||
switch (deviceType) {
|
||||
case 'mobile':
|
||||
case "mobile":
|
||||
return 44; // iOS HIG minimum
|
||||
case 'tablet':
|
||||
case "tablet":
|
||||
return 48; // Material Design minimum
|
||||
case 'tv':
|
||||
case "tv":
|
||||
return 60; // TV optimized
|
||||
default:
|
||||
return 44;
|
||||
@@ -77,7 +77,7 @@ export const DeviceUtils = {
|
||||
tablet: 1.1,
|
||||
tv: 1.25,
|
||||
}[deviceType];
|
||||
|
||||
|
||||
return Math.round(baseSize * scaleFactor);
|
||||
},
|
||||
|
||||
@@ -91,7 +91,7 @@ export const DeviceUtils = {
|
||||
tablet: 1.0,
|
||||
tv: 1.5,
|
||||
}[deviceType];
|
||||
|
||||
|
||||
return Math.round(baseSpacing * scaleFactor);
|
||||
},
|
||||
|
||||
@@ -99,7 +99,7 @@ export const DeviceUtils = {
|
||||
* 检测设备是否处于横屏模式
|
||||
*/
|
||||
isLandscape(): boolean {
|
||||
const { width, height } = Dimensions.get('window');
|
||||
const { width, height } = Dimensions.get("window");
|
||||
return width > height;
|
||||
},
|
||||
|
||||
@@ -114,10 +114,10 @@ export const DeviceUtils = {
|
||||
* 获取安全的网格列数
|
||||
*/
|
||||
getSafeColumnCount(preferredColumns: number): number {
|
||||
const { width } = Dimensions.get('window');
|
||||
const { width } = Dimensions.get("window");
|
||||
const minCardWidth = this.isMobile() ? 120 : this.isTablet() ? 140 : 160;
|
||||
const maxColumns = Math.floor(width / minCardWidth);
|
||||
|
||||
|
||||
return Math.min(preferredColumns, maxColumns);
|
||||
},
|
||||
|
||||
@@ -132,7 +132,7 @@ export const DeviceUtils = {
|
||||
tablet: 1.0,
|
||||
tv: 1.2,
|
||||
}[deviceType];
|
||||
|
||||
|
||||
return Math.round(baseDuration * scaleFactor);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user