revised image asset structure
This commit is contained in:
4
pi/ui/assets/.gitignore
vendored
Normal file
4
pi/ui/assets/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Ignore font files (may have licensing restrictions)
|
||||||
|
# Keep .gitkeep to preserve directory structure
|
||||||
|
fonts/*
|
||||||
|
!fonts/.gitkeep
|
||||||
0
pi/ui/assets/fonts/.gitkeep
Normal file
0
pi/ui/assets/fonts/.gitkeep
Normal file
2
pi/ui/assets/images/.gitignore
vendored
2
pi/ui/assets/images/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
# Generated/symlinked images - created by prepare_assets.sh
|
|
||||||
rei_default.png
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
"assets_path": "/home/pi/smartserow-ui/assets",
|
||||||
|
"navigator": "rei",
|
||||||
"overheat": {
|
"overheat": {
|
||||||
"threshold_celsius": 75.0,
|
"threshold_celsius": 75.0,
|
||||||
"trigger_duration_sec": 10,
|
"trigger_duration_sec": 10,
|
||||||
|
|||||||
3
pi/ui/fonts/.gitignore
vendored
3
pi/ui/fonts/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
# Generated/symlinked font files - created by prepare_assets.sh
|
|
||||||
din1451alt.ttf
|
|
||||||
NotoSans-*.ttf
|
|
||||||
@@ -21,7 +21,6 @@ class SmartSerowApp extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
fontFamily: 'DIN1451',
|
fontFamily: 'DIN1451',
|
||||||
fontFamilyFallback: const ['NotoSans', 'Roboto'],
|
|
||||||
),
|
),
|
||||||
home: const AppRoot(),
|
home: const AppRoot(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../services/config_service.dart';
|
||||||
import '../services/pi_io.dart';
|
import '../services/pi_io.dart';
|
||||||
import '../widgets/stat_box.dart';
|
import '../widgets/stat_box.dart';
|
||||||
|
|
||||||
@@ -46,6 +48,21 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build navigator image from filesystem
|
||||||
|
Widget _buildNavigatorImage() {
|
||||||
|
final config = ConfigService.instance;
|
||||||
|
final imagePath = '${config.assetsPath}/navigator/${config.navigator}/default.png';
|
||||||
|
|
||||||
|
return Image.file(
|
||||||
|
File(imagePath),
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
// Graceful fallback - empty box if image missing
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -127,14 +144,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Image.asset(
|
child: _buildNavigatorImage(),
|
||||||
'assets/images/rei_default.png',
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
errorBuilder: (context, error, stackTrace) {
|
|
||||||
// Graceful fallback - empty box if image missing
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ class ConfigService {
|
|||||||
static const double _defaultThreshold = 80.0;
|
static const double _defaultThreshold = 80.0;
|
||||||
static const int _defaultTriggerDuration = 10;
|
static const int _defaultTriggerDuration = 10;
|
||||||
static const int _defaultShutdownDelay = 10;
|
static const int _defaultShutdownDelay = 10;
|
||||||
|
static const String _defaultNavigator = 'rei';
|
||||||
|
|
||||||
|
// Executable directory (for fallback paths)
|
||||||
|
late final String _exeDir;
|
||||||
|
|
||||||
/// Load config from JSON file
|
/// Load config from JSON file
|
||||||
///
|
///
|
||||||
@@ -24,11 +28,12 @@ class ConfigService {
|
|||||||
Future<void> load() async {
|
Future<void> load() async {
|
||||||
if (_loaded) return;
|
if (_loaded) return;
|
||||||
|
|
||||||
try {
|
|
||||||
// Config file sits next to the executable
|
// Config file sits next to the executable
|
||||||
final exePath = Platform.resolvedExecutable;
|
final exePath = Platform.resolvedExecutable;
|
||||||
final exeDir = File(exePath).parent.path;
|
_exeDir = File(exePath).parent.path;
|
||||||
final configPath = '$exeDir${Platform.pathSeparator}config.json';
|
|
||||||
|
try {
|
||||||
|
final configPath = '$_exeDir${Platform.pathSeparator}config.json';
|
||||||
|
|
||||||
final file = File(configPath);
|
final file = File(configPath);
|
||||||
if (await file.exists()) {
|
if (await file.exists()) {
|
||||||
@@ -66,4 +71,19 @@ class ConfigService {
|
|||||||
if (value is int) return Duration(seconds: value);
|
if (value is int) return Duration(seconds: value);
|
||||||
return Duration(seconds: _defaultShutdownDelay);
|
return Duration(seconds: _defaultShutdownDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Path to external assets directory
|
||||||
|
String get assetsPath {
|
||||||
|
final value = _config?['assets_path'];
|
||||||
|
if (value is String && value.isNotEmpty) return value;
|
||||||
|
// Fallback: assets/ next to executable
|
||||||
|
return '$_exeDir${Platform.pathSeparator}assets';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Navigator character name (subfolder in assets/navigator/)
|
||||||
|
String get navigator {
|
||||||
|
final value = _config?['navigator'];
|
||||||
|
if (value is String && value.isNotEmpty) return value;
|
||||||
|
return _defaultNavigator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.3"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -71,26 +71,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.8"
|
version: "11.0.2"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.9"
|
version: "3.0.10"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_testing
|
name: leak_tracker_testing
|
||||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -180,18 +180,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.6"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.2.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -201,5 +201,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "14.3.1"
|
version: "14.3.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.7.0-0 <4.0.0"
|
dart: ">=3.8.0-0 <4.0.0"
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
flutter: ">=3.18.0-18.0.pre.54"
|
||||||
|
|||||||
@@ -18,17 +18,7 @@ dev_dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
||||||
assets:
|
|
||||||
- assets/images/
|
|
||||||
|
|
||||||
fonts:
|
fonts:
|
||||||
- family: DIN1451
|
- family: DIN1451
|
||||||
fonts:
|
fonts:
|
||||||
- asset: fonts/din1451alt.ttf
|
- asset: assets/fonts/din1451alt.ttf
|
||||||
- family: NotoSans
|
|
||||||
fonts:
|
|
||||||
- asset: fonts/NotoSans-Regular.ttf
|
|
||||||
- asset: fonts/NotoSans-Bold.ttf
|
|
||||||
weight: 700
|
|
||||||
- asset: fonts/NotoSans-Light.ttf
|
|
||||||
weight: 300
|
|
||||||
|
|||||||
@@ -71,14 +71,6 @@ def build(clean: bool = False) -> bool:
|
|||||||
|
|
||||||
os.chdir(UI_DIR)
|
os.chdir(UI_DIR)
|
||||||
|
|
||||||
# Prepare assets (fonts, images)
|
|
||||||
prepare_script = SCRIPT_DIR / "prepare_assets.sh"
|
|
||||||
if prepare_script.exists():
|
|
||||||
print("Preparing assets...")
|
|
||||||
run(["bash", str(prepare_script)])
|
|
||||||
else:
|
|
||||||
print(f"WARNING: {prepare_script} not found")
|
|
||||||
|
|
||||||
# Initialize elinux project if needed
|
# Initialize elinux project if needed
|
||||||
elinux_dir = UI_DIR / "elinux"
|
elinux_dir = UI_DIR / "elinux"
|
||||||
if not elinux_dir.exists():
|
if not elinux_dir.exists():
|
||||||
|
|||||||
@@ -36,15 +36,6 @@ echo "Cross-compiler: $CXX"
|
|||||||
|
|
||||||
cd "$UI_DIR"
|
cd "$UI_DIR"
|
||||||
|
|
||||||
# Prepare assets (fonts, images)
|
|
||||||
PREPARE_SCRIPT="$SCRIPT_DIR/prepare_assets.sh"
|
|
||||||
if [ -x "$PREPARE_SCRIPT" ]; then
|
|
||||||
echo "Preparing assets..."
|
|
||||||
"$PREPARE_SCRIPT"
|
|
||||||
else
|
|
||||||
echo "WARNING: $PREPARE_SCRIPT not found or not executable"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Initialize elinux project if not already configured
|
# Initialize elinux project if not already configured
|
||||||
if [ ! -d "elinux" ]; then
|
if [ ! -d "elinux" ]; then
|
||||||
echo "Initializing elinux project structure..."
|
echo "Initializing elinux project structure..."
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ PROJECT_ROOT = SCRIPT_DIR.parent
|
|||||||
CONFIG_FILE = SCRIPT_DIR / "deploy_target.json"
|
CONFIG_FILE = SCRIPT_DIR / "deploy_target.json"
|
||||||
BUILD_DIR = PROJECT_ROOT / "pi" / "ui" / "build" / "elinux" / "arm64" / "release" / "bundle"
|
BUILD_DIR = PROJECT_ROOT / "pi" / "ui" / "build" / "elinux" / "arm64" / "release" / "bundle"
|
||||||
CONFIG_SRC = PROJECT_ROOT / "pi" / "ui" / "config.json"
|
CONFIG_SRC = PROJECT_ROOT / "pi" / "ui" / "config.json"
|
||||||
|
IMAGES_SRC = PROJECT_ROOT / "extra" / "images"
|
||||||
|
|
||||||
|
|
||||||
def run(cmd: list[str], check: bool = True, **kwargs) -> subprocess.CompletedProcess:
|
def run(cmd: list[str], check: bool = True, **kwargs) -> subprocess.CompletedProcess:
|
||||||
@@ -77,6 +78,20 @@ def deploy(restart: bool = False) -> bool:
|
|||||||
print()
|
print()
|
||||||
print("Note: No config.json found, using defaults")
|
print("Note: No config.json found, using defaults")
|
||||||
|
|
||||||
|
# Sync images to assets path
|
||||||
|
if IMAGES_SRC.exists():
|
||||||
|
assets_path = config.get("assets_path", f"{remote_path}/assets")
|
||||||
|
print()
|
||||||
|
print(f"Syncing images to {assets_path}...")
|
||||||
|
run([
|
||||||
|
"rsync", "-avz",
|
||||||
|
f"{IMAGES_SRC}/",
|
||||||
|
f"{ssh_target}:{assets_path}/",
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
print()
|
||||||
|
print("Note: No extra/images folder found, skipping image sync")
|
||||||
|
|
||||||
# Restart service if requested
|
# Restart service if requested
|
||||||
if restart:
|
if restart:
|
||||||
print()
|
print()
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ SERVICE_NAME=$(read_json service_name)
|
|||||||
SSH_TARGET="$PI_USER@$PI_HOST"
|
SSH_TARGET="$PI_USER@$PI_HOST"
|
||||||
BUILD_DIR="$PROJECT_ROOT/pi/ui/build/elinux/arm64/release/bundle"
|
BUILD_DIR="$PROJECT_ROOT/pi/ui/build/elinux/arm64/release/bundle"
|
||||||
CONFIG_SRC="$PROJECT_ROOT/pi/ui/config.json"
|
CONFIG_SRC="$PROJECT_ROOT/pi/ui/config.json"
|
||||||
|
IMAGES_SRC="$PROJECT_ROOT/extra/images"
|
||||||
|
|
||||||
echo "=== Smart Serow Deploy ==="
|
echo "=== Smart Serow Deploy ==="
|
||||||
echo "Target: $SSH_TARGET:$REMOTE_PATH"
|
echo "Target: $SSH_TARGET:$REMOTE_PATH"
|
||||||
@@ -55,6 +56,18 @@ else
|
|||||||
echo "Note: No config.json found, using defaults"
|
echo "Note: No config.json found, using defaults"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Sync images to assets path
|
||||||
|
if [ -d "$IMAGES_SRC" ]; then
|
||||||
|
# Read assets_path from config, fall back to default
|
||||||
|
ASSETS_PATH=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('assets_path', '$REMOTE_PATH/assets'))" 2>/dev/null || echo "$REMOTE_PATH/assets")
|
||||||
|
echo ""
|
||||||
|
echo "Syncing images to $ASSETS_PATH..."
|
||||||
|
rsync -avz "$IMAGES_SRC/" "$SSH_TARGET:$ASSETS_PATH/"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "Note: No extra/images folder found, skipping image sync"
|
||||||
|
fi
|
||||||
|
|
||||||
# Restart service if requested
|
# Restart service if requested
|
||||||
RESTART="${1:-}"
|
RESTART="${1:-}"
|
||||||
if [ "$RESTART" = "--restart" ] || [ "$RESTART" = "-r" ]; then
|
if [ "$RESTART" = "--restart" ] || [ "$RESTART" = "-r" ]; then
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"user": "pi",
|
"user": "pi",
|
||||||
"host": "raspberrypi.local",
|
"host": "raspberrypi.local",
|
||||||
"remote_path": "/opt/smartserow",
|
"remote_path": "/opt/smartserow",
|
||||||
"service_name": "smartserow-ui"
|
"service_name": "smartserow-ui",
|
||||||
|
"assets_path": "~/smartserow-ui/assets"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# prepare_assets.sh - Prepares fonts and images for Flutter build
|
|
||||||
# Run this before 'flutter build' to ensure assets are in place
|
|
||||||
#
|
|
||||||
# This script handles:
|
|
||||||
# - DIN1451 font: symlinks from extra/ if present, otherwise downloads Noto Sans as fallback
|
|
||||||
# - Dashboard image: symlinks from extra/ if present, otherwise skipped (handled at runtime)
|
|
||||||
|
|
||||||
set -e
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
||||||
|
|
||||||
UI_DIR="$PROJECT_ROOT/pi/ui"
|
|
||||||
FONTS_DIR="$UI_DIR/fonts"
|
|
||||||
IMAGES_DIR="$UI_DIR/assets/images"
|
|
||||||
EXTRA_FONTS="$PROJECT_ROOT/extra/fonts"
|
|
||||||
EXTRA_IMAGES="$PROJECT_ROOT/extra/images"
|
|
||||||
|
|
||||||
# Noto Sans download URLs (Google Fonts)
|
|
||||||
NOTO_SANS_BASE="https://github.com/googlefonts/noto-fonts/raw/main/hinted/ttf/NotoSans"
|
|
||||||
NOTO_REGULAR="$NOTO_SANS_BASE/NotoSans-Regular.ttf"
|
|
||||||
NOTO_BOLD="$NOTO_SANS_BASE/NotoSans-Bold.ttf"
|
|
||||||
NOTO_LIGHT="$NOTO_SANS_BASE/NotoSans-Light.ttf"
|
|
||||||
|
|
||||||
echo "=== Smart Serow Asset Preparation ==="
|
|
||||||
|
|
||||||
# --- FONTS ---
|
|
||||||
echo ""
|
|
||||||
echo "--- Fonts ---"
|
|
||||||
|
|
||||||
# Ensure Noto Sans fallbacks exist
|
|
||||||
download_noto() {
|
|
||||||
local weight=$1
|
|
||||||
local url=$2
|
|
||||||
local dest="$FONTS_DIR/NotoSans-${weight}.ttf"
|
|
||||||
|
|
||||||
if [ ! -f "$dest" ]; then
|
|
||||||
echo "Downloading Noto Sans $weight..."
|
|
||||||
curl -sL "$url" -o "$dest" || {
|
|
||||||
echo "Warning: Failed to download Noto Sans $weight"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
echo " -> Downloaded $dest"
|
|
||||||
else
|
|
||||||
echo " Noto Sans $weight already present"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
download_noto "Regular" "$NOTO_REGULAR"
|
|
||||||
download_noto "Bold" "$NOTO_BOLD"
|
|
||||||
download_noto "Light" "$NOTO_LIGHT"
|
|
||||||
|
|
||||||
# DIN1451 - symlink if available, otherwise use Noto Sans
|
|
||||||
DIN_TARGET="$FONTS_DIR/din1451alt.ttf"
|
|
||||||
DIN_SOURCE="$EXTRA_FONTS/din1451alt.ttf"
|
|
||||||
|
|
||||||
# Remove old symlink/file to ensure fresh state
|
|
||||||
rm -f "$DIN_TARGET"
|
|
||||||
|
|
||||||
if [ -f "$DIN_SOURCE" ]; then
|
|
||||||
echo "DIN1451 found - linking/copying"
|
|
||||||
# Try symlink first, fall back to copy (Windows compatibility)
|
|
||||||
if ln -s "$DIN_SOURCE" "$DIN_TARGET" 2>/dev/null; then
|
|
||||||
echo " -> Linked $DIN_TARGET -> $DIN_SOURCE"
|
|
||||||
else
|
|
||||||
cp "$DIN_SOURCE" "$DIN_TARGET"
|
|
||||||
echo " -> Copied $DIN_TARGET (symlinks not supported)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "DIN1451 not found - using Noto Sans as fallback"
|
|
||||||
if [ -f "$FONTS_DIR/NotoSans-Regular.ttf" ]; then
|
|
||||||
cp "$FONTS_DIR/NotoSans-Regular.ttf" "$DIN_TARGET"
|
|
||||||
echo " -> Copied Noto Sans Regular as $DIN_TARGET"
|
|
||||||
else
|
|
||||||
echo " ERROR: No fallback font available!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- IMAGES ---
|
|
||||||
echo ""
|
|
||||||
echo "--- Images ---"
|
|
||||||
|
|
||||||
REI_TARGET="$IMAGES_DIR/rei_default.png"
|
|
||||||
REI_SOURCE="$EXTRA_IMAGES/rei_default.png"
|
|
||||||
|
|
||||||
# Remove old symlink/file
|
|
||||||
rm -f "$REI_TARGET"
|
|
||||||
|
|
||||||
if [ -f "$REI_SOURCE" ]; then
|
|
||||||
echo "Dashboard image found - linking/copying"
|
|
||||||
# Try symlink first, fall back to copy (Windows compatibility)
|
|
||||||
if ln -s "$REI_SOURCE" "$REI_TARGET" 2>/dev/null; then
|
|
||||||
echo " -> Linked $REI_TARGET -> $REI_SOURCE"
|
|
||||||
else
|
|
||||||
cp "$REI_SOURCE" "$REI_TARGET"
|
|
||||||
echo " -> Copied $REI_TARGET (symlinks not supported)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Dashboard image not found - will use empty fallback at runtime"
|
|
||||||
# Create a tiny transparent PNG placeholder (1x1 pixel)
|
|
||||||
# This avoids asset not found errors while keeping the build clean
|
|
||||||
printf '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\nIDATx\x9cc\x00\x01\x00\x00\x05\x00\x01\r\n-\xb4\x00\x00\x00\x00IEND\xaeB`\x82' > "$REI_TARGET"
|
|
||||||
echo " -> Created 1x1 transparent placeholder"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Asset preparation complete ==="
|
|
||||||
echo "You can now run: flutter build linux"
|
|
||||||
Reference in New Issue
Block a user