feat: update image requirements to landscape orientation and add CI/CD workflow
Some checks failed
Build App / build (push) Failing after 3m44s

This commit is contained in:
2026-03-01 15:53:36 +01:00
parent 44b4277b8e
commit 2f4a238eba
9 changed files with 95 additions and 15 deletions

43
.gitea/workflows/ci.yml Normal file
View File

@@ -0,0 +1,43 @@
name: Build App
on:
push:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 🏗 Setup repo
uses: actions/checkout@v2
- name: 🏗 Setup Node
uses: actions/setup-node@v2
with:
node-version: 22
- name: 🏗 Setup Expo and EAS
uses: expo/expo-github-action@v7
with:
token: ${{ secrets.EXPO_TOKEN }}
expo-version: latest
eas-version: latest
- name: 📦 Install dependencies
run: npm install
working-directory: App
- name: 👷 Build app
run: |
eas build --local \
--non-interactive \
--output=./app-build \
--platform=android \
--profile=preview
working-directory: App
- name: 📤 Upload build artifact
uses: actions/upload-artifact@v4
with:
name: android-preview-build.zip
path: App/app-build/*
if-no-files-found: error

View File

@@ -37,9 +37,9 @@ Images/rotator assets stored in MinIO at `content2.reversed.dev`, bucket `tv-con
`settings` is a persistent object with global TV display configuration (typed as `SettingsState` in `tv/src/types.ts`). `settings` is a persistent object with global TV display configuration (typed as `SettingsState` in `tv/src/types.ts`).
- **`background_url`** — a portrait image (height > width) rendered as a full-screen `object-cover` background behind all TV content. Empty string = no background. - **`background_url`** — a landscape image (width > height) rendered as a full-screen `object-cover` background behind all TV content. Empty string = no background.
- Set via `push_settings { background_url }`, cleared by passing `""`. - Set via `push_settings { background_url }`, cleared by passing `""`.
- The constraint (portrait orientation) is enforced in the mobile picker (`mobile/src/pages/settings.tsx`) — `asset.width >= asset.height` is rejected. - The constraint (landscape orientation) is enforced in the mobile picker (`mobile/src/pages/settings.tsx`) — `asset.width <= asset.height` is rejected.
- Images are uploaded first via `push_upload_images` to get a MinIO URL, then saved via `push_settings`. - Images are uploaded first via `push_upload_images` to get a MinIO URL, then saved via `push_settings`.
- The Settings tab is visible in the mobile bottom nav (no `hideInNav`). - The Settings tab is visible in the mobile bottom nav (no `hideInNav`).

View File

@@ -1,30 +1,37 @@
{ {
"expo": { "expo": {
"name": "mobile", "name": "TV Control",
"slug": "mobile", "slug": "tv-control",
"version": "1.0.0", "version": "1.0.0",
"orientation": "portrait", "orientation": "portrait",
"icon": "./assets/icon.png", "icon": "./assets/icon.png",
"userInterfaceStyle": "light", "userInterfaceStyle": "automatic",
"newArchEnabled": true, "newArchEnabled": true,
"splash": { "splash": {
"image": "./assets/splash-icon.png", "image": "./assets/splash-icon.png",
"resizeMode": "contain", "resizeMode": "contain",
"backgroundColor": "#ffffff" "backgroundColor": "#8c8c8c"
}, },
"ios": { "ios": {
"supportsTablet": true "supportsTablet": false,
"bundleIdentifier": "dev.reversed.tvcontrol"
}, },
"android": { "android": {
"adaptiveIcon": { "adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png", "foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff" "backgroundColor": "#8c8c8c"
}, },
"package": "dev.reversed.tvcontrol",
"edgeToEdgeEnabled": true, "edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false "predictiveBackGestureEnabled": false
}, },
"web": { "web": {
"favicon": "./assets/favicon.png" "favicon": "./assets/favicon.png"
},
"extra": {
"eas": {
"projectId": "4e663169-e9d3-4ca5-95e3-4c2477fcd072"
}
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 584 KiB

30
mobile/eas.json Normal file
View File

@@ -0,0 +1,30 @@
{
"cli": {
"version": ">= 16.0.0",
"appVersionSource": "local"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"android": {
"buildType": "apk"
},
"ios": {
"simulator": true
}
},
"preview": {
"distribution": "internal",
"android": {
"buildType": "apk"
}
},
"production": {
"autoIncrement": true,
"android": {
"buildType": "app-bundle"
}
}
}
}

View File

@@ -39,7 +39,7 @@ export function SettingsPage() {
.finally(() => setLoading(false)); .finally(() => setLoading(false));
}, []); }, []);
// ── Pick a portrait image from the gallery // ── Pick a landscape image from the gallery
const handlePickBackground = async () => { const handlePickBackground = async () => {
const { granted } = await ImagePicker.requestMediaLibraryPermissionsAsync(); const { granted } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!granted) { if (!granted) {
@@ -57,9 +57,9 @@ export function SettingsPage() {
const asset = result.assets[0]; const asset = result.assets[0];
// Enforce portrait orientation (height must exceed width) // Enforce landscape orientation (width must exceed height)
if (asset.width >= asset.height) { if (asset.width <= asset.height) {
setStatus("Please pick a portrait image (height must be greater than width)."); setStatus("Please pick a landscape image (width must be greater than height).");
return; return;
} }
@@ -150,7 +150,7 @@ export function SettingsPage() {
<View style={styles.section}> <View style={styles.section}>
<Text style={shared.sectionLabel}>TV Background</Text> <Text style={shared.sectionLabel}>TV Background</Text>
<Text style={shared.hint}> <Text style={shared.hint}>
Displayed behind all content on the TV. Must be a portrait image (taller than wide). Displayed behind all content on the TV. Must be a landscape image (wider than tall).
</Text> </Text>
{loading ? ( {loading ? (
@@ -246,7 +246,7 @@ const styles = StyleSheet.create({
}, },
preview: { preview: {
width: "100%", width: "100%",
aspectRatio: 9 / 16, aspectRatio: 16 / 9,
}, },
pendingBadge: { pendingBadge: {
position: "absolute", position: "absolute",
@@ -266,7 +266,7 @@ const styles = StyleSheet.create({
}, },
emptyPreview: { emptyPreview: {
width: "100%", width: "100%",
aspectRatio: 9 / 16, aspectRatio: 16 / 9,
borderRadius: 14, borderRadius: 14,
borderWidth: 1, borderWidth: 1,
borderColor: colors.border, borderColor: colors.border,