557 Commits

Author SHA1 Message Date
Lucas 'Paperboy' Rose-Winters f560bb543b feat(ui): add tab navigation system for desktop and mobile
Desktop (2 tabs):
- Status tab: User Stats + Info Box + Character Thoughts
- Inventory tab: Inventory system (dedicated space)

Mobile (3 tabs):
- Stats tab: User Stats only
- Info tab: Info Box + Character Thoughts
- Inventory tab: Inventory only

Features:
- Created desktop.js module for desktop tab management
- Updated mobile.js to use 3-tab structure (more breathing room on small screens)
- Added CSS styling for desktop tabs (hover states, active indicators)
- Implemented viewport transition handlers (desktop ↔ mobile)
- Tabs replace dividers (cleaner visual separation)
- Character thoughts can now expand to fill vertical space

This resolves the cramped 4-section panel issue by organizing content into logical tabs on both desktop and mobile.
2025-10-17 16:18:47 +11:00
Lucas 'Paperboy' Rose-Winters abd3ade30e fix(inventory): refactor renderInventory() to match other render functions
Root cause: renderInventory() signature mismatch - was expecting parameters
but called without any, resulting in empty/broken rendering.

Changes:
- Rename renderInventory(inventory, options) → generateInventoryHTML() (internal)
- Create new renderInventory() with no parameters (like renderUserStats, etc.)
- New function gets container from state, data from settings, updates DOM directly
- Import getInventoryRenderOptions() to get current tab/collapse state
- Keep updateInventoryDisplay() for use by inventoryActions module

Now matches the pattern used by all other render modules, fixing the bug where
inventory section appeared empty in the panel.
2025-10-17 15:46:13 +11:00
Lucas 'Paperboy' Rose-Winters 2566d97dfb feat(inventory): add mobile tab support for inventory section
- Include inventory in mobile tab system alongside user stats
- Add inventory to Stats tab (grouped with user stats)
- Update setupMobileTabs() to detect and organize inventory section
- Update removeMobileTabs() to restore inventory in correct order
- Handle inventory show/hide in mobile tab transitions

Inventory now works seamlessly on mobile viewports with proper tab organization.
2025-10-17 15:38:11 +11:00
Lucas 'Paperboy' Rose-Winters 1f948cd5d8 feat(inventory): wire up v2 system to main panel with full interactivity
- Add inventory section to template.html between Thoughts and bottom controls
- Wire up renderInventory() to all event handlers (message received, character changed, swipes)
- Initialize inventory container reference and event listeners in index.js
- Add showInventory toggle checkbox to settings with visibility control
- Update layout.js to handle inventory section and divider visibility
- Add renderInventory parameter to updateRPGData for separate mode support
- Update state.js and config.js with inventory container and showInventory setting

Inventory is now fully integrated as a visible, interactive panel section that persists across all user interactions.
2025-10-17 15:36:15 +11:00
Lucas 'Paperboy' Rose-Winters 60e4a6c2cc feat(inventory): add interaction handlers for v2 system
Create comprehensive inventory interaction module:

**NEW: inventoryActions.js (286 lines)**
- editOnPerson() - Edit items currently carried/worn
- editStoredLocation() - Edit items at specific storage location
- editAssets() - Edit vehicles, property, major possessions
- addStorageLocation() - Create new storage location with validation
- removeStorageLocation() - Delete location with confirmation
- toggleLocationCollapse() - Collapsible sections with persistent state
- switchInventoryTab() - Handle sub-tab switching
- initInventoryEventListeners() - Event delegation for dynamic content
- updateLastGeneratedDataInventory() - Keep AI context synced

**Interaction Patterns:**
- Uses native prompt() and confirm() for user input
- Event delegation: .on() for dynamic elements
- Full persistence: saveSettings() + saveChatData() + updateMessageSwipeData()
- Auto re-render after every mutation
- Maintains UI state (activeSubTab, collapsedLocations)

**State Management:**
- Tracks collapsed locations across sessions
- Persists in extensionSettings.collapsedInventoryLocations
- Current tab state maintained in module scope

**Data Flow:**
User Action → Handler → Update inventory → Update lastGeneratedData
→ Persist (settings + chat + swipe) → Re-render UI

Part of Epic 7.6: Inventory interactions
Next: Wire into main panel and initialize event listeners
2025-10-17 15:28:59 +11:00
Lucas 'Paperboy' Rose-Winters 790cf995b4 feat(inventory): add v2 UI rendering with tabbed interface
Create complete inventory UI rendering system:

**NEW: inventory.js rendering module (252 lines):**
- renderInventorySubTabs() - Navigation tabs (On Person, Stored, Assets)
- renderOnPersonView() - Display items currently carried/worn
- renderStoredView() - Collapsible storage locations with edit/remove actions
- renderAssetsView() - Vehicles, property, and major possessions
- renderInventory() - Main rendering function with v1/v2 compatibility
- updateInventoryDisplay() - DOM update helper
- Includes HTML escaping for XSS prevention

**Tab System:**
- Three sub-tabs: On Person, Stored, Assets
- Smooth tab switching with active state highlighting
- Each view shows relevant inventory section

**On Person View:**
- Shows items currently carried/worn
- Edit button to modify items
- Clean text display

**Stored View:**
- Collapsible location sections
- Each location shows: name, items, edit/remove buttons
- "Add Location" button for new storage spots
- Empty state message when no locations exist
- Toggle icons (chevron-down/chevron-right)

**Assets View:**
- Display of vehicles, property, equipment
- Edit button to modify assets
- Helpful hint text explaining asset categories

**Removed old inventory UI from userStats.js:**
- Deleted rpg-inventory-box HTML (5 lines)
- Deleted inventory editing event listener (13 lines)
- Inventory now has dedicated tab instead of inline display
- Maintains backward compatibility for data tracking

**NEW: Inventory CSS styles (242 lines):**
- .rpg-inventory-container - Main layout
- .rpg-inventory-subtabs - Tab navigation styling
- .rpg-inventory-section - Content area styling
- .rpg-storage-location - Collapsible location cards
- Button styles (edit, add, remove) with hover states
- Mobile responsive breakpoints for touch-friendly UI
- Theme-aware using SillyTavern CSS variables
- Font size: 0.9rem for readability

**Design Features:**
- Clean, modern card-based layout
- Smooth transitions and hover effects
- Collapsible sections to reduce clutter
- Consistent with existing RPG Companion theme system
- Mobile-first responsive design
- Touch-friendly button sizes on mobile

Changes:
- NEW: src/systems/rendering/inventory.js (252 lines)
- MODIFIED: src/systems/rendering/userStats.js (-18 lines, removed old UI)
- MODIFIED: style.css (+242 lines, inventory styles)

Part of inventory system v2 implementation
Dependencies: v2 types, migration, parsing, generation
2025-10-17 15:14:02 +11:00
Lucas 'Paperboy' Rose-Winters b00bae905f feat(inventory): add v2 parsing and generation support
Add full AI integration for inventory v2 format:

**Parsing (NEW: inventoryParser.js, 125 lines):**
- extractInventoryData() - Parse multi-line v2 format from AI responses
  - Extracts "On Person: ..." section
  - Extracts multiple "Stored - [Location]: ..." sections
  - Extracts "Assets: ..." section
  - Returns InventoryV2 object
- extractLegacyInventory() - Fallback parser for old v1 format
- extractInventory() - Main function that tries v2 first, falls back to v1

**Parsing Integration (parser.js):**
- Import extractInventory() from inventoryParser
- Replace old single-line regex with v2-aware extraction
- Use feature flag to switch between v1/v2 parsing modes
- Maintains backward compatibility with FEATURE_FLAGS.useNewInventory

**Generation (promptBuilder.js, 60 lines changed):**
- NEW: buildInventorySummary() - Converts v2 object to multi-line text
  - Formats "On Person: ..." line
  - Formats multiple "Stored - [Location]: ..." lines
  - Formats "Assets: ..." line
  - Handles legacy v1 string format for backward compat
- Update generateTrackerInstructions() with v2 format spec:
  - Shows AI how to format inventory in multi-line v2 structure
  - Includes note about multiple storage locations
  - Falls back to v1 format when feature flag disabled
- Update generateContextualSummary() to use buildInventorySummary()
  - Converts v2 inventory to readable context for separate mode

**Format Examples:**

AI Output (v2 format):
```
On Person: Sword (equipped), 3x Health Potions, Leather Armor
Stored - Home: Spare clothes, Tools, 50 gold coins
Stored - Bank: Family heirloom, Important documents
Assets: Motorcycle (garage), Downtown apartment (owned)
```

Parsed Result:
```js
{
  version: 2,
  onPerson: "Sword (equipped), 3x Health Potions, Leather Armor",
  stored: {
    "Home": "Spare clothes, Tools, 50 gold coins",
    "Bank": "Family heirloom, Important documents"
  },
  assets: "Motorcycle (garage), Downtown apartment (owned)"
}
```

Changes:
- NEW: src/systems/generation/inventoryParser.js (125 lines)
- MODIFIED: src/systems/generation/parser.js (+14 lines)
- MODIFIED: src/systems/generation/promptBuilder.js (+60 lines)

Part of inventory system v2 implementation
Dependencies: v2 types, migration utility, persistence integration
2025-10-17 15:10:31 +11:00
Lucas 'Paperboy' Rose-Winters 39ec36f105 feat(inventory): add automatic v1→v2 migration on settings/chat load
Integrate inventory migration into persistence layer:
- Call migrateInventory() automatically when loading settings
- Call migrateInventory() automatically when loading chat data
- Save migrated data back to persistence immediately
- Update default reset inventory to v2 format
- Add console logging for migration status

Migration behavior:
- Only runs when FEATURE_FLAGS.useNewInventory is true
- Automatically detects v1 string format and converts to v2
- Handles null/undefined/empty/malformed data gracefully
- Logs migration source (v1, null, default) to console
- Persists migrated inventory immediately after conversion
- Migration runs once per load - subsequent loads see v2

Migration scenarios:
1. Old save with v1 string → migrates to v2.onPerson, saves
2. No save data → uses v2 defaults from state.js
3. Already v2 → no migration, no save
4. Chat data with v1 → migrates to v2, updates chat metadata

Changes:
- MODIFIED: src/core/persistence.js (+29 lines)
  - Updated loadSettings() with migration hook
  - Updated loadChatData() with migration hook
  - Changed default reset inventory from 'None' to v2 object

Part of inventory system v2 implementation
Dependencies: inventory types and migration utility
2025-10-17 15:06:53 +11:00
Lucas 'Paperboy' Rose-Winters 110bdb3b64 feat(inventory): implement v2 data structure and JSDoc types (Epic 7.1)
Create structured inventory system with categorized storage:
- Add JSDoc type definitions (InventoryV2, InventoryV1, MigrationResult)
- Implement migration utility for v1 → v2 conversion
- Update state.js with v2 inventory structure and feature flag
- Update config.js to match new inventory defaults

Changes:
- NEW: src/types/inventory.js (30 lines) - Type definitions
- NEW: src/utils/migration.js (84 lines) - Migration logic
- MODIFIED: src/core/state.js - v2 inventory + FEATURE_FLAGS
- MODIFIED: src/core/config.js - v2 inventory defaults

Inventory v2 structure:
{
  version: 2,
  onPerson: "Sword, 3x Potions",     // Plaintext string
  stored: {
    "Home": "Clothes, Tools",         // Location → items
    "Bank": "Gold, Documents"
  },
  assets: "Motorcycle, House"         // Plaintext string
}

Migration handles all edge cases:
- v1 string → v2.onPerson
- null/undefined → v2 defaults
- "None" → v2 defaults
- Already v2 → no changes

Context overhead: +40 chars (~5% increase) for organized multi-location storage

Part of Epic 7: New Inventory System
Implements: docs/IMPLEMENTATION_PLAN.md Epic 7.1
2025-10-17 14:58:07 +11:00
Lucas 'Paperboy' Rose-Winters 658b911d12 style: integrate upstream font-size and layout improvements
Folds in changes from commits 6d97992, cc53c69, 6987c0c:
- Update stat label/value font sizes (clamp 0.9-1vw → 0.5-0.7vw)
- Update inventory items font size (clamp 0.4-0.6vw → 0.7-0.6vw)
- Center dice save button with auto margins
- Add debug console.log for committedTrackerData
- Comment out verbose console logs for plot progression and persona avatar
- Clarify prompt instruction to remove brackets
2025-10-17 14:35:55 +11:00
Lucas 'Paperboy' Rose-Winters 0764bc63a1 feat(integration): extract SillyTavern event handlers to dedicated module
- Create src/systems/integration/sillytavern.js with all event handlers
- Move commitTrackerData() (deferred from Epic 1)
- Move sendPlotProgression() to plotProgression.js
- Move updateGenerationModeUI() to layout.js
- Add registerAllEvents() and unregisterAllEvents() to events.js
- Centralize event registration in index.js initialization

This completes Epic 6: Integration Layer Extraction
~340 lines extracted from index.js
index.js reduced from ~783 lines to 423 lines
2025-10-17 14:20:58 +11:00
Lucas 'Paperboy' Rose-Winters 175ff9560c refactor(features): extract HTML cleaning regex setup to standalone module
Extract ensureHtmlCleaningRegex into src/systems/features/htmlCleaning.js.
This module automatically imports the HTML cleaning regex script that
strips HTML tags from outgoing prompts to prevent formatting issues.

Passes SillyTavern imports (st_extension_settings, saveSettingsDebounced)
as parameters to avoid deep module import path issues.

- Create htmlCleaning.js with regex import logic
- Update index.js to import and use the new module with parameters
- Maintain backward compatibility with existing functionality
2025-10-17 13:48:49 +11:00
Lucas 'Paperboy' Rose-Winters 3473f2ac44 refactor(features): extract classic stats controls to standalone module
Extract setupClassicStatsButtons into src/systems/features/classicStats.js.
This module handles the delegated event listeners for classic RPG stat
+/- buttons (STR, DEX, CON, INT, WIS, CHA).

- Create classicStats.js with event delegation for stat buttons
- Update index.js to import and use the new module
- Maintain backward compatibility with existing functionality
2025-10-17 13:45:36 +11:00
Lucas 'Paperboy' Rose-Winters ba50fc5bdc refactor(features): extract plot progression UI to standalone module
Extract plot progression button setup from index.js into dedicated
feature module at src/systems/features/plotProgression.js.

Due to ES6 module import path limitations in deeply nested modules,
the generation logic (sendPlotProgression) remains in index.js where
it can properly import from SillyTavern's script.js. The UI setup
function accepts the generation function as a callback parameter.

Creates plotProgression.js with 62 lines of UI setup code.
Index.js increases from 800 to 869 lines (+69 for generation logic).
2025-10-17 13:39:24 +11:00
Lucas 'Paperboy' Rose-Winters f4dfd368e1 refactor(features): extract dice system to standalone module
Extract dice rolling functionality from modals.js into dedicated
feature module at src/systems/features/dice.js. This includes:
- rollDice() - core rolling logic with animation
- executeRollCommand() - dice notation parser
- updateDiceDisplay() - sidebar display updates
- clearDiceRoll() - clear last roll
- addDiceQuickReply() - quick reply integration

Also fixes ES6 module binding issue with pendingDiceRoll by adding
getPendingDiceRoll() getter function in state.js to ensure correct
value retrieval across module boundaries.

Reduces modals.js from 568 to 499 lines (-69 lines).
Creates dice.js with 113 lines of focused dice functionality.
2025-10-17 13:25:38 +11:00
Lucas 'Paperboy' Rose-Winters bb952aecec fix(ui): correct dice roller 'Save Roll' button positioning
The Save Roll button was appearing at the bottom left of the container
instead of being centered below the result.

Added flexbox layout to .rpg-dice-result container:
- display: flex
- flex-direction: column
- align-items: center

This ensures the button is properly centered and positioned below
the dice result value and details.
2025-10-17 13:05:41 +11:00
Lucas 'Paperboy' Rose-Winters 23fc9fdc9a refactor(ui): extract UI systems into modular architecture
Extracted ~920 lines of UI management code from index.js into 4 specialized modules to improve maintainability and organization.

Modules Created:
- src/systems/ui/theme.js (100 lines) - Theme management and custom colors
- src/systems/ui/modals.js (568 lines) - DiceModal and SettingsModal ES6 classes
- src/systems/ui/layout.js (254 lines) - Panel visibility, positioning, and collapse toggle
- src/systems/ui/mobile.js (694 lines) - Mobile FAB, tabs, keyboard handling, and viewport management

Changes:
- Extracted theme application and custom color management
- Extracted modal classes with proper state management
- Extracted layout management (visibility, sections, positioning)
- Extracted mobile-specific UI (FAB dragging with touch/mouse, tab navigation, keyboard handling)
- Removed unused import (closeMobilePanelWithAnimation only used internally by mobile.js)
- Updated imports in index.js to use new module structure
- Added comprehensive documentation comments

Result:
- index.js reduced from 1606 to 921 lines (-685 lines)
- All UI systems properly modularized with clean dependencies
- Maintains 100% backward compatibility
- All modules pass syntax validation

Dependencies:
- All modules import from src/core/state.js for shared state
- Mobile module imports layout functions for panel animation
- Layout module properly manages DOM element state
2025-10-17 13:02:11 +11:00
Lucas 'Paperboy' Rose-Winters ed4506dc68 fix(dice): replace const assignments with setter function calls
After modular refactor, `pendingDiceRoll` is imported as const from
state module and cannot be reassigned. Replace three direct assignments
with `setPendingDiceRoll()` setter function calls:
- DiceModal.close() method (line 572)
- Save roll button handler (line 691)
- rollDice() function (line 773)

Fixes "Assignment to constant variable" errors preventing dice rolls.
2025-10-17 12:26:40 +11:00
Lucas 'Paperboy' Rose-Winters 871f187f40 fix(mobile): improve Settings UI and button readability
Convert Settings UI font sizes from viewport units to responsive clamp()
values with pixel minimums. Desktop vw values (1.1-1.85vw) were rendering
as 4-7px on 390px mobile screens, making settings controls unreadable.

UI Buttons (2 overrides):
- Settings button: clamp(14px, 3.6vw, 18px) - was 1.1vw (4.29px)
- Mobile toggle dice icon: clamp(20px, 5.1vw, 26px) - was 1.85vw (7.22px)

Settings Popup (6 overrides):
- Popup title (h3): clamp(16px, 4.1vw, 20px) - was ~5.85px
- Group headers (h4): clamp(14px, 3.6vw, 18px) - was 1.5vw (5.85px)
- Setting labels: clamp(12px, 3.1vw, 16px) - was 1.2vw (4.68px)
- Dropdowns/inputs: clamp(13px, 3.3vw, 17px) - was 1.3vw (5.07px)
- Helper text (small): clamp(10px, 2.6vw, 13px) - was ~3.9px
- Clear cache button: clamp(13px, 3.3vw, 17px) - was 1.2vw (4.68px)

Mobile toggle button size remains unchanged (44px), only icon scaled up.
2025-10-17 12:18:50 +11:00
Lucas 'Paperboy' Rose-Winters 8b6ae6e68d fix(mobile): improve Info dashboard, stat bars, and dice display
Convert mobile font sizes from viewport units to responsive clamp() values
with pixel minimums to ensure readability on small screens. Desktop vw values
(0.4-1.3vw) were rendering as 1.5-5px on 390px mobile screens.

Info Screen Improvements:
- Calendar: month (8-10px), weekday (11-14px), year (7-10px)
- Weather forecast: 9-11px
- Temperature value: 10-13px
- Clock time: 10-13px
- Location text: 11-14px (unchanged)
- Map marker emoji: 16-20px

Stats Screen Improvements:
- Stats grid: min-height 180px for better vertical fill
- Stat labels: clamp(11px, 2.8vw, 14px)
- Stat values: clamp(12px, 3.1vw, 16px)
- Increased gap between stat rows: clamp(8px, 2vw, 12px)

Dice Display Improvements:
- Container text: clamp(12px, 3.1vw, 16px)
- Dice icon: clamp(18px, 4.6vw, 24px)
- Clear button: clamp(18px, 4.6vw, 24px) text, 28-36px size
- Min-height: 44px (touch-friendly)
- Increased padding and gap for better visibility

All improvements maintain desktop appearance while ensuring mobile usability.
2025-10-17 12:06:05 +11:00
Lucas 'Paperboy' Rose-Winters 0aee477b52 fix(mobile): improve text readability and layout on mobile devices
Convert mobile font sizes from fixed pixels to responsive viewport units
with pixel minimums using clamp() to ensure readability on small screens.
Previously, desktop vw values (0.4-0.8vw) rendered as 1.5-3px on mobile,
making text unreadable.

Mobile Font Size Updates:
- Collapse toggle icon: clamp(20px, 5.1vw, 24px)
- Mobile tab buttons: clamp(14px, 3.6vw, 18px)
- Mobile tab icons: clamp(16px, 4.1vw, 20px)
- Classic stat labels: clamp(9px, 2.3vw, 12px)
- Classic stat values: clamp(14px, 3.6vw, 18px)
- Stat +/- buttons: clamp(14px, 3.6vw, 18px)
- Relationship badges: clamp(10px, 2.6vw, 13px)
- Inventory items: clamp(11px, 2.8vw, 14px)
- Mood conditions: clamp(11px, 2.8vw, 14px)
- Character emoji: clamp(16px, 4.1vw, 20px)
- Character names: clamp(12px, 3.1vw, 16px)
- Character traits: clamp(11px, 2.8vw, 14px)

Mobile Layout Improvements:
- Expand inventory box horizontally using flex: 1 to fill available space
- Force avatar+inventory flex container to full width in grid cell
- Reposition mood section to align with attributes top (grid-row: 4/6)
- Update grid structure to 5 rows for better vertical organization
- Remove desktop width restrictions on inventory box

These changes follow IDeathByte's commit 733c606 approach of using
viewport-responsive units, adapted specifically for mobile screen sizes.
2025-10-17 11:48:36 +11:00
Lucas 'Paperboy' Rose-Winters d2d5593e00 refactor: extract rendering systems
Extract rendering logic from index.js into modular system:
- src/utils/avatars.js: Safe thumbnail URL generation with error handling
- src/systems/rendering/userStats.js: User stats panel with progress bars and classic RPG stats
- src/systems/rendering/infoBox.js: Info box dashboard with weather, date, time, and location widgets
- src/systems/rendering/thoughts.js: Character thoughts panel and floating chat bubbles

Reduces index.js from 3,829 to 2,430 lines (-1,399 lines, -36.5%)
All rendering functions now properly modularized with full JSDoc documentation
Event listeners preserved in render functions for interactive fields
2025-10-17 11:16:29 +11:00
Lucas 'Paperboy' Rose-Winters 17736d9140 feat: extract generation and parsing systems into modules
Extract AI generation and parsing logic from monolithic index.js into
modular architecture under src/systems/generation/.

**Modules Created:**
- promptBuilder.js (319 lines) - AI prompt generation functions
- parser.js (152 lines) - Response parsing and stats extraction
- apiClient.js (154 lines) - Separate mode API call handler
- injector.js (216 lines) - Prompt injection for both modes

**Changes:**
- All functions preserve exact behavior from original
- Import paths calculated for browser module resolution
- Zero functionality changes, pure code organization

Reduces index.js by ~700 lines when combined with function removal
(to be committed separately).
2025-10-17 10:38:35 +11:00
Spicy Marinara 6987c0ced4 Merge pull request #9 from IDeathByte/main
Fix for fix for browser height scalability
2025-10-17 00:15:29 +02:00
Lucas 'Paperboy' Rose-Winters 5c34407d2c refactor(core): extract core modules (state, persistence, config, events)
Extract core system modules from monolithic index.js into modular architecture:

- src/core/state.js: All extension state variables with controlled setters
- src/core/persistence.js: Settings and chat data persistence functions
- src/core/config.js: Extension metadata and default configuration
- src/core/events.js: SillyTavern event system wrapper

Updated index.js to import and use new core modules.
Removed ~220 lines of state/persistence code from index.js.

Part of Epic 1: Foundation & Core Systems (Phase 1.1-1.2)
2025-10-17 09:13:19 +11:00
Spicy_Marinara cc53c69af8 Fix Save Roll button centering in dice popup
- Added margin-left and margin-right auto to center the button in desktop view
- Button now properly centers within the popup window when max-width is applied
2025-10-17 00:11:24 +02:00
IDeathByte 6d979920a2 Fix for fix for browser height scalability
Little smaller text for stats bar without high price for readability - should work better on chrome etc.

Also should work correct on ultrawide (21:9) screens now. I hope =\
2025-10-17 02:26:30 +05:00
Spicy Marinara 84d2bad5ef Revise acknowledgments in README.md
Updated acknowledgments for Paperboy and IDeathByte.
2025-10-16 18:31:52 +02:00
Spicy Marinara dac648f729 Merge pull request #8 from paperboygold/main
fix: resolve avatar loading issues and prevent 400 Bad Request errors
2025-10-16 18:30:26 +02:00
Spicy Marinara 3df06508f7 Merge pull request #7 from IDeathByte/main
replace all font-size properties to vw for normal screen scaling
2025-10-16 18:29:50 +02:00
Lucas 'Paperboy' Rose-Winters 1db709693d fix: use base64-encoded SVG for avatar fallback to prevent HTML parsing errors
The previous URL-encoded SVG had unencoded quotes that broke HTML attribute parsing.
The browser would misinterpret xmlns="http://www.w3.org/2000/svg" as separate HTML
attributes, causing broken image rendering.

Changes:
- Add FALLBACK_AVATAR_DATA_URI constant with base64-encoded SVG
- Replace all instances of broken inline transparentPixel variable (3 locations)
- Update comparison check to use the new constant

The base64 encoding ensures the data URI is safely embedded in HTML src attributes
without any quote-escaping issues.
2025-10-17 03:15:23 +11:00
Lucas 'Paperboy' Rose-Winters 66712382d5 fix: eliminate 400 Bad Request errors for persona avatar thumbnails
- Add getSafeThumbnailUrl() helper function with comprehensive error handling
- Replace all getThumbnailUrl() calls with safe wrapper that validates results
- Use SVG data URI placeholder instead of 'img/user-default.png' to avoid 400 errors
- Update img onerror handlers to fade opacity instead of trying invalid fallback paths
- Add detailed console logging for debugging avatar loading issues
- Improve updatePersonaAvatar() to only update src when valid URL is available

This fixes persistent 400 errors on some Ubuntu systems where directory names
with spaces (e.g., "User Avatars") caused thumbnail URL construction to fail.

Affected functions:
- getSafeThumbnailUrl() (new)
- updatePersonaAvatar()
- renderUserStats()
- renderCharacterThoughts()
2025-10-17 03:05:37 +11:00
IDeathByte 733c6060bd replace all font-size properties to vw for normal screen scaling 2025-10-16 19:32:53 +05:00
Spicy_Marinara 74e76ff224 Fix multiple issues: persona avatar loading, together mode tracker persistence, CSS responsive scaling, and weather widget
- Fixed persona avatar loading for custom user profile folders with fallback
- Added dynamic persona avatar updates when user switches personas
- Fixed together mode bug where committedTrackerData wasn't persisting after first generation
- Together mode now mirrors separate mode logic for swipes vs new messages
- Converted all CSS font-sizes from rem to vw for proper responsive scaling
- Fixed weather widget scaling issues at high zoom levels
- Added image generation detection to skip tracker injection for quietImage requests
- Removed CHARACTER_MESSAGE_RENDERED listener to fix race condition in together mode
2025-10-16 14:50:52 +02:00
Spicy Marinara a97b3a0f26 Update README for mobile support and feature enhancements
Removed mobile device limitation note and added mobile support feature.
2025-10-16 12:27:36 +02:00
Spicy Marinara a8a3b40b95 Merge pull request #6 from paperboygold/feat/mobile-ux-improvements
Feat/mobile ux improvements
2025-10-16 12:23:59 +02:00
Lucas 'Paperboy' Rose-Winters 9b17624385 fix: increase classic stats max value from 20 to 100 for superhero-level characters 2025-10-16 14:46:34 +11:00
Paperboy 54ead0ed0c Merge branch 'main' into feat/mobile-ux-improvements 2025-10-16 14:45:26 +11:00
Lucas 'Paperboy' Rose-Winters 58b7ea4d21 feat: add mobile keyboard handling to prevent layout squashing
Implemented Visual Viewport API integration to detect and handle mobile
keyboard appearance, preventing contenteditable fields from squashing
the panel layout when the keyboard appears.

**JavaScript Changes (index.js:1886-1948, 522-523):**
- Created setupMobileKeyboardHandling() function:
  * Uses Visual Viewport API to monitor viewport height changes
  * Detects keyboard appearance (viewport < 75% of window height)
  * Adds .rpg-keyboard-visible class when keyboard shows
  * Removes class when keyboard dismisses
  * Gracefully falls back if API not supported
- Created setupContentEditableScrolling() function:
  * Uses event delegation for all contenteditable fields
  * Automatically scrolls focused field into view with 300ms delay
  * Centers field in viewport using scrollIntoView with 'center' block
  * Smooth scrolling animation for better UX
- Added both function calls to initUI() for automatic setup

**CSS Changes (style.css:3232-3252):**
- Added .rpg-keyboard-visible state styling:
  * 20px bottom padding to prevent content being pushed too far up
  * Compact section padding (8px 12px) for stats/info/thoughts
  * Reduced stat bar gap (4px) to maintain layout integrity
- Scoped to mobile viewport only (@media max-width: 1000px)

**Benefits:**
- No layout squashing when keyboard appears on mobile
- Stat bars and charts remain intact and visible
- Focused fields automatically scroll into view
- Smooth animations for professional UX
- Works with all contenteditable fields:
  * Stats (health, energy, hygiene, sustenance, arousal)
  * Inventory and mood/conditions
  * Info box widgets (date, weather, time, location, temperature)
  * Character traits and relationship badges
  * Character thoughts
- Backward compatible (graceful fallback)
- Desktop users completely unaffected

**How It Works:**
1. Visual Viewport API monitors viewport height changes
2. When height drops below 75% threshold, keyboard detected
3. Panel gets .rpg-keyboard-visible class for compact styling
4. Tapped contenteditable field smoothly scrolls to center
5. When keyboard dismisses, layout returns to normal

**Testing Completed:**
- Inventory field editing works without squashing
- Stat values editable with keyboard visible
- Info box widget editing maintains layout
- Character traits and thoughts remain accessible
- No layout breaks or chart distortion
- Smooth scrolling and transitions verified
2025-10-16 14:37:43 +11:00
Lucas 'Paperboy' Rose-Winters 644e893a3d fix: redesign attributes as ultra-compact 2x3 grid for mobile
Completely redesigned the classic stats (STR, DEX, CON, INT, WIS, CHA)
section for mobile with 1/3 size reduction and vertical stack layout.

**CSS Changes (style.css:3510-3587):**
- Changed from vertical flex list to 2x3 CSS grid layout
- Reduced all dimensions by ~66% for ultra-compact mobile view:
  * Labels: 9px (was 12px)
  * Values: 14px (was 20px)
  * Buttons: 24x24px (was 36x36px)
  * Padding: 4px 6px (was 8px 10px)
  * Gaps: 2-4px (was 6-8px)
- Vertical stack layout within each stat box:
  * Row 1: Label (left) | Value (right)
  * Row 2: Minus button (left) | Plus button (right)
- Fixed button visibility:
  * Added explicit background, border, and color styles
  * Added display: flex !important to ensure rendering
  * Added hover and active states
- Fixed right-side cutoff:
  * Added 5px padding-right to stats grid
  * Adjusted margins for proper spacing
- Centered all elements using justify-self: center
- Removed conflicting @media (max-width: 768px) rule that enlarged buttons

**JavaScript Changes (index.js:518, 985-1011):**
- Created setupClassicStatsButtons() function with delegated event listeners
- Moved event handlers from renderUserStats() to setup function
- Used jQuery .on() delegation to persist across re-renders
- Prevents duplicate handlers and ensures buttons always work
- Called in initUI() during extension initialization

**Benefits:**
- Attributes take up 1/3 the vertical space on mobile
- No vertical overflow in mobile Stats tab
- All 6 attributes fit comfortably in 2x3 grid
- +/- buttons visible and properly aligned
- Buttons fully functional with delegation pattern
- Desktop layout completely unaffected (>1000px)

**Layout:**
```
┌────────────┐ ┌────────────┐
│ STR    13  │ │ DEX    16  │
│  -      +  │ │  -      +  │
└────────────┘ └────────────┘
┌────────────┐ ┌────────────┐
│ CON    14  │ │ INT    18  │
│  -      +  │ │  -      +  │
└────────────┘ └────────────┘
┌────────────┐ ┌────────────┐
│ WIS    13  │ │ CHA    15  │
│  -      +  │ │  -      +  │
└────────────┘ └────────────┘
```
2025-10-16 14:15:44 +11:00
Lucas 'Paperboy' Rose-Winters f70ac827aa feat: redesign settings popup modal for mobile compatibility
Completely refactored the RPG Companion settings popup with professional
ES6 architecture and mobile-first CSS, matching the dice roller redesign.

**CSS Changes (style.css:2585-2773):**
- Mobile-first responsive design with clamp() and min() functions
- CSS custom properties for fluid scaling across viewports
- min-height: 0 on flex children for proper max-height constraints
- ::before pseudo-element for backdrop (removed overlay div)
- State-based animations with .is-open and .is-closing classes
- 75vh max-height with proper viewport centering
- Touch-friendly 44px minimum tap targets
- Neutral 80% opaque background for visibility

**HTML Changes (template.html:71-214):**
- Added ARIA attributes: role="dialog", aria-modal="true", aria-labelledby
- Semantic <header> element for settings header
- aria-hidden="true" on all decorative icons
- Removed .rpg-settings-popup-overlay div (now CSS ::before)
- Improved accessibility throughout

**JavaScript Changes (index.js:985-1142):**
- Created SettingsModal ES6 class with state management
- open() and close() methods with animation control
- updateTheme() for real-time theme switching
- Private _applyCustomTheme() and _clearCustomTheme() methods
- isAnimating flag prevents double-clicks
- Focus management for accessibility
- Backwards compatible wrapper functions preserve existing API
- Updated event handlers with backdrop click support
- Removed obsolete overlay click handler

**Benefits:**
- Settings modal now fully functional on mobile devices
- Proper scrolling with content overflow
- Smooth open/close animations
- Professional class-based architecture
- Complete accessibility support
- Theme support maintained
- No breaking changes to existing code
2025-10-16 13:59:41 +11:00
Lucas 'Paperboy' Rose-Winters 7971056440 refactor: complete professional redesign of dice roller modal for mobile
BREAKING CHANGES: Dice roller now uses modern ES6 class architecture

Features:
- Mobile-first CSS with fluid responsive units (clamp, min, max)
- ES6 DiceModal class with proper state management (IDLE, ROLLING, SHOWING_RESULT)
- Semantic HTML with ARIA attributes for accessibility
- CSS state classes (.is-open, .is-closing, .is-animating)
- Touch-friendly 44px minimum tap targets
- Desktop enhancement with @media (min-width: 1001px)

Fixes:
- Fixed mobile viewport overflow with min-height: 0 on flex children
- Reduced max-height to 70vh for guaranteed mobile fit
- Removed all jQuery .show()/.hide() inline style injections
- Removed !important CSS hacks from mobile media query
- Fixed transparent modal background (80% opaque neutral gray)
- Darkened backdrop overlay (85% opaque black)

Technical:
- Backdrop uses ::before pseudo-element (no wrapper div needed)
- Flattened HTML structure with proper semantic elements
- Backwards compatible wrapper functions preserved
- Grid layout for inputs (stacked mobile, side-by-side desktop)
- Proper CSS specificity hierarchy (no !important needed)
- Removed .rpg-dice-popup-overlay div dependency

Accessibility:
- role="dialog" with aria-modal="true"
- aria-labelledby for dialog title
- aria-live regions for dynamic content
- aria-busy for loading states
- Proper focus management on open/close
2025-10-16 13:41:34 +11:00
Lucas 'Paperboy' Rose-Winters 3d32a04d57 feat: add smooth slide-out animation for mobile panel closing
Added matching slide-out animation when closing the mobile panel to
match the smooth slide-in animation on opening:

CSS changes (style.css):
- Add .rpg-mobile-closing class with rpgSlideOutToRight animation
- Create @keyframes rpgSlideOutToRight (0.3s ease-in-out)
- Panel slides smoothly off-screen to right before hiding

JavaScript changes (index.js):
- Add closeMobilePanelWithAnimation() helper function
- Use animationend event to wait for animation before hiding
- Replace all instant removeClass() calls with helper function
- Maintains smooth 0.3s animation timing matching slide-in

Implementation details:
- Helper function adds .rpg-mobile-closing class
- Waits for CSS animation to complete via animationend event
- Then removes closing class and overlay
- All close operations now use this helper for consistency

Result: Panel now smoothly slides in AND out with matching 0.3s
animations. No more jarring instant disappearance on close.
2025-10-16 12:33:07 +11:00
Lucas 'Paperboy' Rose-Winters a6bc021148 refactor: use display toggle instead of transform for mobile panel
Replaced transform-based off-screen positioning with display toggle
for cleaner, simpler mobile panel behavior:

CSS changes:
- Replace transform: translateX(100%) with display: none (closed state)
- Panel completely removed from layout when closed
- Add display: block when rpg-mobile-open class applied
- Use CSS animation for smooth slide-in effect on open
- Create @keyframes rpgSlideInFromRight for 0.3s ease-in-out

Benefits:
1. Panel doesn't affect viewport/layout when closed
2. No need for overflow-x: hidden hacks
3. Simpler implementation - just toggle display property
4. Better performance - browser doesn't track hidden element
5. Still has smooth slide-in animation via CSS @keyframes

JavaScript:
- No changes needed - already toggles rpg-mobile-open class correctly
- Display changes happen automatically via CSS

Trade-off:
- Slide-out animation on close is instant (could add if desired)
- But this is acceptable and matches many mobile UX patterns

Result: Mobile panel cleanly appears/disappears without viewport issues
or layout side effects. Much simpler and more robust solution.
2025-10-16 12:29:40 +11:00
Lucas 'Paperboy' Rose-Winters c756704abc chore: simplify mobile tab label from 'Info & Characters' to 'Info' 2025-10-16 12:17:43 +11:00
Lucas 'Paperboy' Rose-Winters aef9cf812d feat: add smooth animation to thought icon scroll tracking
Improved thought icon behavior on mobile with smooth 60fps animations
matching the FAB button drag experience:

CSS changes:
- Add transition properties for top/left position changes
- Use 0.2s ease-out timing for smooth, natural movement
- Add will-change: top, left for browser rendering optimization
- Applied in mobile media query (@media max-width: 1000px)

JavaScript changes:
- Wrap position updates in requestAnimationFrame()
- Cancel pending RAF before scheduling new update (debouncing)
- Sync position updates with display refresh rate
- Same pattern as FAB button smooth drag implementation

Technical details:
- RAF throttling prevents layout thrashing
- CSS transitions handle the actual animation
- Combined approach gives 60fps smooth tracking
- Icon follows avatar smoothly during scroll on mobile

Result: Thought icon smoothly tracks avatar position during scroll
instead of jumping around, with buttery smooth 60fps animation.
2025-10-16 12:16:43 +11:00
Lucas 'Paperboy' Rose-Winters 9219fe3f19 feat: add smooth animation to mobile FAB drag behavior
Improved the mobile floating action button (FAB) drag experience with
smooth, performant animations:

- Use requestAnimationFrame to throttle position updates during drag
- Add will-change CSS property to optimize rendering performance
- Add dragging class to disable transitions during active drag
- Change cursor to grab/grabbing for better visual feedback
- Remove janky direct CSS updates in favor of RAF-based updates

Technical improvements:
- Position updates now synced to display refresh rate (~60fps)
- Prevents layout thrashing from excessive DOM manipulation
- Smooth transition animations when drag ends

Result: Dragging the FAB button now feels fluid and responsive on
mobile devices instead of laggy and jumpy.
2025-10-16 11:39:15 +11:00
Lucas 'Paperboy' Rose-Winters e342f4d100 fix: improve mobile UX for relationship badge and thought panel
Fixed two mobile UI issues:

1. Relationship badge sizing on mobile:
   - Badge was stretching vertically due to .rpg-editable mobile styles
   - Override padding, min-height, and line-height for badge on mobile
   - Keep badge at compact 18px × 18px to prevent covering avatar

2. Thought panel initial state:
   - Panel was showing by default instead of the icon
   - Fixed initialization: hide panel, show icon
   - Users now click the 💭 icon to open the dialogue as intended

Changes ensure proper mobile experience with appropriately sized UI
elements and correct initial visibility states.
2025-10-16 11:33:59 +11:00
Lucas 'Paperboy' Rose-Winters 60e371c726 fix: reposition 'Show thoughts' button above avatar on mobile
Previously, the thought icon button was positioned to the left of the
character avatar on mobile, causing it to appear partially off-screen
due to lack of left padding around avatars.

Changes:
- Add mobile-specific positioning logic in index.js to detect viewport
  width <= 1000px and calculate centered horizontal position
- Add CSS transform in mobile media query to shift icon 50px right
  and 45px upward from calculated position
- Center thought panel horizontally on mobile when opened
- Add debug logging to verify mobile detection

Result: On mobile, the thought icon now appears above and to the right
of the avatar, fully visible and accessible.
2025-10-16 11:25:38 +11:00
Lucas 'Paperboy' Rose-Winters f4f0ab1484 feat: add smart viewport constraint for mobile FAB button
- Add constrainFabToViewport() function with top-bar awareness
- Only constrains when mobileFabPosition exists (user has dragged button)
- Respects SillyTavern's top bar height via CSS variable
- Prevents button from being hidden behind UI elements
- Applies constraint after drag operations and window resize
- Remove verbose debug logging from drag/touch event handlers

This implements a state-driven approach where the constraint only activates
for user-positioned buttons, allowing CSS defaults to work naturally while
protecting custom positions from viewport changes.
2025-10-16 10:52:09 +11:00