fix Music app layout and document RmlUi encoding issue

- Fixed Music app layout using incremental edit approach
- Documented RmlUi file encoding issue in DESKTOP-DESIGNER.md
- Added workaround: copy from working file and edit incrementally
This commit is contained in:
2026-01-20 19:27:15 +01:00
parent 0da90f976f
commit bd8ce61897
2 changed files with 129 additions and 149 deletions

View File

@@ -219,3 +219,49 @@ The JSON contains element bounds, classes, IDs, and visibility - useful for auto
## Action Recording and Playback
See [TESTING-FRAMEWORK.md](TESTING-FRAMEWORK.md) for details on recording and playing back UI interactions.
---
## Known Issues and Workarounds
### RmlUi Layout Breaking Due to File Encoding
**Problem**: Content fragments created with certain file-writing methods may render with broken layouts - elements appear with 0 width, text wraps excessively, and flex layouts collapse.
**Symptoms**:
- List items don't expand to full width
- Text wraps to very narrow columns
- Avatars/icons overlap with text
- UI hierarchy shows `"width": 0.0` for elements that should have proper width
**Root Cause**: RmlUi's parser is sensitive to certain invisible file formatting. While files may appear identical in text editors and have the same line endings (CRLF), subtle encoding differences can break layout parsing.
**Diagnosis**: Use `--hierarchy FILE` flag to dump UI element dimensions:
```bash
./designer/build/Release/mosis-designer.exe --simulator --playback tests/test_app.json --hierarchy hierarchy.json
```
Check the JSON for elements with `"width": 0.0` that should have proper dimensions.
**Workaround**: Instead of creating content fragments from scratch, copy an existing working file and modify it:
```bash
# 1. Copy a known working file (e.g., messages_content.rml)
cp src/main/assets/apps/messages/messages_content.rml src/main/assets/apps/myapp/myapp_content.rml
# 2. Edit the file incrementally (use sed, text editor, or Edit tool)
# DO NOT rewrite the entire file - preserve the original byte structure
# 3. Test the layout
./designer/build/Release/mosis-designer.exe --simulator --playback tests/test_myapp.json --screenshot-after test.png
```
**Working Reference Files**:
- `apps/messages/messages_content.rml` - Known good file format
- `apps/store/store_content.rml` - Created by copying from messages
- `apps/settings/settings_content.rml` - Created by copying from messages
**Prevention**: When creating new content fragments:
1. Always start by copying an existing working content fragment
2. Make incremental edits rather than full file rewrites
3. Test layout after changes using `--hierarchy` flag

View File

@@ -1,174 +1,108 @@
<!-- Music App Content Fragment -->
<!-- Uses classes from components.rcss -->
<div class="app-content" style="position: relative;">
<div class="app-content">
<div class="app-bar">
<span class="app-bar-title">Good afternoon</span>
<div class="btn-icon" onclick="openMusicSettings()">
<img src="../../icons/settings.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
<div style="flex: 1; overflow: auto; padding-bottom: 100px;">
<!-- Quick Access Grid -->
<div style="display: flex; flex-wrap: wrap; gap: 8px; padding: 16px;">
<div class="quick-card" onclick="openPlaylist('liked')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #7c3aed;">L</div>
<span class="quick-card-title">Liked Songs</span>
</div>
<div class="quick-card" onclick="openPlaylist('daily1')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #667eea;">D</div>
<span class="quick-card-title">Daily Mix 1</span>
</div>
<div class="quick-card" onclick="openPlaylist('release')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #16a34a;">R</div>
<span class="quick-card-title">Release Radar</span>
</div>
<div class="quick-card" onclick="openPlaylist('chill')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #f093fb;">C</div>
<span class="quick-card-title">Chill Vibes</span>
</div>
</div>
<!-- Recently Played -->
<div class="section-header">
<span class="section-title">Recently Played</span>
<span class="section-action" onclick="showAllRecent()">SEE ALL</span>
</div>
<div style="display: flex; overflow-x: auto; padding: 0 16px; gap: 16px;">
<div class="recent-item" onclick="openPlaylist('pop')">
<div class="recent-art" style="background-color: #43e97b;">P</div>
<div class="recent-title">Pop Hits</div>
<div class="recent-subtitle">Playlist</div>
</div>
<div class="recent-item" onclick="openPlaylist('electronic')">
<div class="recent-art" style="background-color: #fa709a;">E</div>
<div class="recent-title">Electronic</div>
<div class="recent-subtitle">Playlist</div>
</div>
<div class="recent-item" onclick="openPlaylist('jazz')">
<div class="recent-art" style="background-color: #667eea;">J</div>
<div class="recent-title">Jazz Classics</div>
<div class="recent-subtitle">Playlist</div>
</div>
</div>
<!-- Made For You -->
<div class="section-header">
<span class="section-title">Made For You</span>
<span class="section-action" onclick="showAllMixes()">SEE ALL</span>
</div>
<div class="playlist-item" onclick="openPlaylist('daily1')">
<div class="playlist-art" style="background-color: #4facfe;">1</div>
<div class="playlist-info">
<div class="playlist-title">Daily Mix 1</div>
<div class="playlist-meta">Based on your listening</div>
</div>
</div>
<div class="playlist-item" onclick="openPlaylist('daily2')">
<div class="playlist-art" style="background-color: #43e97b;">2</div>
<div class="playlist-info">
<div class="playlist-title">Daily Mix 2</div>
<div class="playlist-meta">Electronic, Ambient, Chill</div>
</div>
</div>
<div class="playlist-item" onclick="openPlaylist('discover')">
<div class="playlist-art" style="background-color: #fa709a;">D</div>
<div class="playlist-info">
<div class="playlist-title">Discover Weekly</div>
<div class="playlist-meta">Your weekly mixtape</div>
<span class="app-bar-title">Music</span>
<div class="app-bar-actions">
<div class="btn-icon" onclick="searchMusic()">
<img src="../../icons/search.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
</div>
<!-- Mini Player -->
<div class="mini-player" onclick="openNowPlaying()" style="position: absolute; bottom: 0; left: 0; right: 0;">
<div class="mini-player-art" id="mini-art" style="background-color: #667eea;">M</div>
<div class="mini-player-info">
<div class="mini-player-title" id="mini-title">Midnight City</div>
<div class="mini-player-artist" id="mini-artist">M83</div>
<div class="list" style="flex: 1; overflow: auto;">
<div class="list-item" onclick="playSong('midnight')">
<div class="list-item-avatar" style="background-color: #5C6BC0;">M</div>
<div class="list-item-content">
<span class="list-item-title" style="color: #BB86FC;">Midnight City</span>
<span class="list-item-subtitle" style="color: #FFFFFF;">M83</span>
</div>
<div class="mini-player-controls">
<div class="mini-control-btn" onclick="toggleLike(); event.stopPropagation();">
<img src="../../icons/heart.tga" style="width: 28px; height: 28px;"/>
<span style="font-size: 14px; color: #888888;">4:03</span>
</div>
<div class="mini-control-btn" id="play-btn" onclick="togglePlay(); event.stopPropagation();">
<img id="play-icon" src="../../icons/play.tga" style="width: 28px; height: 28px;"/>
<div class="list-divider"></div>
<div class="list-item" onclick="playSong('blinding')">
<div class="list-item-avatar" style="background-color: #E91E63;">B</div>
<div class="list-item-content">
<span class="list-item-title">Blinding Lights</span>
<span class="list-item-subtitle">The Weeknd</span>
</div>
<span style="font-size: 14px; color: #888888;">3:20</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="playSong('levitating')">
<div class="list-item-avatar" style="background-color: #9C27B0;">L</div>
<div class="list-item-content">
<span class="list-item-title" style="color: #BB86FC;">Levitating</span>
<span class="list-item-subtitle" style="color: #FFFFFF;">Dua Lipa</span>
</div>
<span style="font-size: 14px; color: #888888;">3:23</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openPlaylist('favorites')">
<div class="list-item-avatar" style="background-color: #F44336;">F</div>
<div class="list-item-content">
<span class="list-item-title">Favorites</span>
<span class="list-item-subtitle">24 songs</span>
</div>
<span style="font-size: 14px; color: #888888;">&gt;</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openPlaylist('workout')">
<div class="list-item-avatar" style="background-color: #4CAF50;">W</div>
<div class="list-item-content">
<span class="list-item-title">Workout Mix</span>
<span class="list-item-subtitle">18 songs</span>
</div>
<span style="font-size: 14px; color: #888888;">&gt;</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openPlaylist('chill')">
<div class="list-item-avatar" style="background-color: #00BCD4;">C</div>
<div class="list-item-content">
<span class="list-item-title">Chill Vibes</span>
<span class="list-item-subtitle">32 songs</span>
</div>
<span style="font-size: 14px; color: #888888;">&gt;</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openPlaylist('party')">
<div class="list-item-avatar" style="background-color: #FF9800;">P</div>
<div class="list-item-content">
<span class="list-item-title">Party Hits</span>
<span class="list-item-subtitle">45 songs</span>
</div>
<span style="font-size: 14px; color: #888888;">&gt;</span>
</div>
</div>
</div>
<script>
local is_playing = false
local current_track = {
title = "Midnight City",
artist = "M83"
}
local function getDoc()
return shell_document
function searchMusic()
print("[Music] Search")
if showToast then showToast("Search music") end
end
function togglePlay()
is_playing = not is_playing
local doc = getDoc()
if doc then
local icon = doc:GetElementById("play-icon")
if icon then
icon:SetAttribute("src", is_playing and "../../icons/pause.tga" or "../../icons/play.tga")
end
end
print("[Music] " .. (is_playing and "Playing" or "Paused"))
if showToast then
showToast(is_playing and "Playing" or "Paused")
end
end
function toggleLike()
print("[Music] Liked")
if showToast then
showToast("Added to Liked Songs")
end
function playSong(id)
print("[Music] Playing: " .. id)
if showToast then showToast("Now playing") end
end
function openPlaylist(id)
print("[Music] Opening playlist: " .. id)
if showToast then
showToast("Playlist: " .. id)
end
end
function openNowPlaying()
print("[Music] Now playing")
if showToast then
showToast("Now Playing: " .. current_track.title)
end
end
function showAllRecent()
print("[Music] Show all recent")
if showToast then
showToast("Recently played")
end
end
function showAllMixes()
print("[Music] Show all mixes")
if showToast then
showToast("Made for you")
end
end
function openMusicSettings()
print("[Music] Settings")
if showToast then
showToast("Music settings")
end
if showToast then showToast("Playlist: " .. id) end
end
print("[Music] Content loaded")