fix: copy mobile toggle pattern for refresh button
- Moved refresh button creation from template.html to index.js (appended to body) - Created new CSS class .rpg-mobile-refresh (exact copy of .rpg-mobile-toggle pattern) - Uses opacity for show/hide instead of display (CSS controls visibility based on panel state) - Show when panel open (body:has(.rpg-panel.rpg-mobile-open)) - Hide when panel closed (opacity: 0, pointer-events: none) - Updated constrainFabToViewport() to accept optional button parameter - Automatically detects which button and uses correct settings (mobileFabPosition or mobileRefreshPosition) - Simplified updateGenerationModeUI() - CSS handles visibility - Kept full drag functionality with touch and mouse support - Button positioned via JavaScript with saved position - z-index: 1001 (above panel, below toggle at 10002)
This commit is contained in:
@@ -210,6 +210,14 @@ async function initUI() {
|
||||
`;
|
||||
$('body').append(mobileToggleHtml);
|
||||
|
||||
// Add mobile refresh button (same pattern as toggle button)
|
||||
const mobileRefreshHtml = `
|
||||
<button id="rpg-manual-update-mobile" class="rpg-mobile-refresh" title="Refresh RPG Info">
|
||||
<i class="fa-solid fa-sync"></i>
|
||||
</button>
|
||||
`;
|
||||
$('body').append(mobileRefreshHtml);
|
||||
|
||||
// Cache UI elements using state setters
|
||||
setPanelContainer($('#rpg-companion-panel'));
|
||||
setUserStatsContainer($('#rpg-user-stats'));
|
||||
|
||||
@@ -273,12 +273,12 @@ export function applyPanelPosition() {
|
||||
*/
|
||||
export function updateGenerationModeUI() {
|
||||
if (extensionSettings.generationMode === 'together') {
|
||||
// In "together" mode, both update buttons are hidden
|
||||
// In "together" mode, hide both update buttons
|
||||
$('#rpg-manual-update').hide();
|
||||
$('#rpg-manual-update-mobile').hide();
|
||||
} else {
|
||||
// In "separate" mode, both update buttons are visible
|
||||
// (CSS media queries will control which one is displayed)
|
||||
// In "separate" mode, show both buttons
|
||||
// (CSS media queries control which one is visible based on viewport)
|
||||
$('#rpg-manual-update').show();
|
||||
$('#rpg-manual-update-mobile').show();
|
||||
}
|
||||
|
||||
+31
-31
@@ -440,32 +440,41 @@ export function setupMobileToggle() {
|
||||
* Constrains the mobile FAB button to viewport bounds with top-bar awareness.
|
||||
* Only runs when button is in user-controlled state (mobileFabPosition exists).
|
||||
* Ensures button never goes behind the top bar or outside viewport edges.
|
||||
* @param {jQuery} $button - Optional button element (defaults to mobile toggle)
|
||||
*/
|
||||
export function constrainFabToViewport() {
|
||||
export function constrainFabToViewport($button = null) {
|
||||
// Default to mobile toggle if no button specified
|
||||
if (!$button) {
|
||||
$button = $('#rpg-mobile-toggle');
|
||||
}
|
||||
|
||||
if ($button.length === 0) return;
|
||||
|
||||
// Determine which position setting to check based on button ID
|
||||
const isRefreshButton = $button.attr('id') === 'rpg-manual-update-mobile';
|
||||
const positionSetting = isRefreshButton ? 'mobileRefreshPosition' : 'mobileFabPosition';
|
||||
|
||||
// Only constrain if user has set a custom position
|
||||
if (!extensionSettings.mobileFabPosition) {
|
||||
if (!extensionSettings[positionSetting]) {
|
||||
console.log('[RPG Mobile] Skipping viewport constraint - using CSS defaults');
|
||||
return;
|
||||
}
|
||||
|
||||
const $mobileToggle = $('#rpg-mobile-toggle');
|
||||
if ($mobileToggle.length === 0) return;
|
||||
|
||||
// Skip if button is not visible
|
||||
if (!$mobileToggle.is(':visible')) {
|
||||
if (!$button.is(':visible')) {
|
||||
console.log('[RPG Mobile] Skipping viewport constraint - button not visible');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current position
|
||||
const offset = $mobileToggle.offset();
|
||||
const offset = $button.offset();
|
||||
if (!offset) return;
|
||||
|
||||
let currentX = offset.left;
|
||||
let currentY = offset.top;
|
||||
|
||||
const buttonWidth = $mobileToggle.outerWidth();
|
||||
const buttonHeight = $mobileToggle.outerHeight();
|
||||
const buttonWidth = $button.outerWidth();
|
||||
const buttonHeight = $button.outerHeight();
|
||||
|
||||
// Get top bar height from CSS variable (fallback to 50px if not set)
|
||||
const topBarHeight = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--topBarBlockSize')) || 50;
|
||||
@@ -491,15 +500,15 @@ export function constrainFabToViewport() {
|
||||
});
|
||||
|
||||
// Apply new position
|
||||
$mobileToggle.css({
|
||||
$button.css({
|
||||
left: newX + 'px',
|
||||
top: newY + 'px',
|
||||
right: 'auto',
|
||||
bottom: 'auto'
|
||||
});
|
||||
|
||||
// Save corrected position
|
||||
extensionSettings.mobileFabPosition = {
|
||||
// Save corrected position to appropriate setting
|
||||
extensionSettings[positionSetting] = {
|
||||
left: newX + 'px',
|
||||
top: newY + 'px'
|
||||
};
|
||||
@@ -725,43 +734,34 @@ export function setupContentEditableScrolling() {
|
||||
|
||||
/**
|
||||
* Sets up the mobile refresh button with drag functionality.
|
||||
* Button is only visible when panel is open, and can be dragged to reposition.
|
||||
* Same pattern as mobile toggle button.
|
||||
* Tap = refresh, drag = reposition
|
||||
*/
|
||||
export function setupRefreshButtonDrag() {
|
||||
const $refreshBtn = $('#rpg-manual-update-mobile');
|
||||
const $panel = $('#rpg-companion-panel');
|
||||
|
||||
if ($refreshBtn.length === 0) {
|
||||
console.warn('[RPG Mobile] Refresh button not found in DOM');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[RPG Mobile] setupRefreshButtonDrag called');
|
||||
|
||||
// Load and apply saved position
|
||||
if (extensionSettings.mobileRefreshPosition) {
|
||||
const pos = extensionSettings.mobileRefreshPosition;
|
||||
if (pos.left) $refreshBtn.css('left', pos.left);
|
||||
console.log('[RPG Mobile] Loading saved refresh button position:', pos);
|
||||
|
||||
// Apply saved position
|
||||
if (pos.top) $refreshBtn.css('top', pos.top);
|
||||
if (pos.right) $refreshBtn.css('right', pos.right);
|
||||
if (pos.bottom) $refreshBtn.css('bottom', pos.bottom);
|
||||
if (pos.left) $refreshBtn.css('left', pos.left);
|
||||
|
||||
// Constrain to viewport after position is applied
|
||||
requestAnimationFrame(() => constrainFabToViewport($refreshBtn));
|
||||
}
|
||||
|
||||
// Show/hide button based on panel state
|
||||
const updateButtonVisibility = () => {
|
||||
if ($panel.hasClass('rpg-mobile-open')) {
|
||||
$refreshBtn.show();
|
||||
} else {
|
||||
$refreshBtn.hide();
|
||||
}
|
||||
};
|
||||
|
||||
// Initial visibility check
|
||||
updateButtonVisibility();
|
||||
|
||||
// Listen for panel state changes (attach to panel toggle events)
|
||||
// This will be triggered by setupMobileToggle
|
||||
$(document).on('rpg-panel-toggled', updateButtonVisibility);
|
||||
|
||||
// Touch/drag state
|
||||
let isDragging = false;
|
||||
let touchStartTime = 0;
|
||||
|
||||
@@ -2708,62 +2708,51 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
REFRESH ICON BUTTON (Mobile - Floating & Draggable)
|
||||
MOBILE REFRESH BUTTON (FAB - Same pattern as toggle)
|
||||
============================================ */
|
||||
.rpg-refresh-icon-btn {
|
||||
display: none; /* Hidden by default, shown on mobile when panel open */
|
||||
position: fixed; /* Fixed for dragging anywhere on viewport */
|
||||
bottom: 80px; /* Above FAB toggle, below screen edge */
|
||||
right: 20px;
|
||||
width: 44px; /* Touch-friendly size */
|
||||
height: 44px;
|
||||
padding: 0;
|
||||
background: var(--rpg-highlight);
|
||||
border: 2px solid var(--rpg-highlight);
|
||||
border-radius: 50%;
|
||||
color: var(--rpg-text);
|
||||
font-size: 1rem;
|
||||
cursor: grab;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease, opacity 0.3s ease;
|
||||
.rpg-mobile-refresh {
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||
z-index: 1001; /* Above panel (1000) but below mobile FAB (10002) */
|
||||
|
||||
/* Fix sticky tap highlight */
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-touch-callout: none;
|
||||
position: fixed;
|
||||
/* Position set by JavaScript based on saved settings */
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
background: var(--SmartThemeBlurTintColor);
|
||||
border: 2px solid var(--SmartThemeBorderColor);
|
||||
color: var(--rpg-text, #ecf0f1);
|
||||
font-size: 1.85vw;
|
||||
cursor: grab;
|
||||
z-index: 1001; /* Above panel (1000) but below mobile toggle (10002) */
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||
transition: opacity 0.3s ease, transform 0.2s ease, top 0.3s ease, left 0.3s ease, right 0.3s ease, bottom 0.3s ease;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
/* Remove focus outline (prevents black state) */
|
||||
.rpg-refresh-icon-btn:focus {
|
||||
outline: none;
|
||||
will-change: top, left;
|
||||
}
|
||||
|
||||
/* Disable transitions while actively dragging */
|
||||
.rpg-refresh-icon-btn.dragging {
|
||||
.rpg-mobile-refresh.dragging {
|
||||
transition: none;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.rpg-refresh-icon-btn:hover {
|
||||
.rpg-mobile-refresh:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 4px 12px var(--rpg-highlight);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.rpg-refresh-icon-btn:active {
|
||||
.rpg-mobile-refresh:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* Spinning animation when refreshing */
|
||||
.rpg-refresh-icon-btn.spinning i {
|
||||
.rpg-mobile-refresh.spinning i {
|
||||
animation: rpg-spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
.rpg-refresh-icon-btn i {
|
||||
.rpg-mobile-refresh i {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -3361,14 +3350,28 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
|
||||
|
||||
/* Mobile-specific panel behavior - matches SillyTavern's 1000px breakpoint */
|
||||
/* CACHE BUST v2025-01-16 */
|
||||
/* Mobile: Show icon button, hide desktop button */
|
||||
/* Mobile refresh button visibility - opposite of toggle */
|
||||
@media (max-width: 1000px) {
|
||||
.rpg-refresh-icon-btn {
|
||||
display: flex !important; /* Show mobile icon button */
|
||||
/* Show mobile refresh button */
|
||||
.rpg-mobile-refresh {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Hide desktop refresh button */
|
||||
.rpg-manual-update-btn {
|
||||
display: none !important; /* Hide desktop button */
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Show refresh button when panel is open (opposite of toggle) */
|
||||
body:has(.rpg-panel.rpg-mobile-open) .rpg-mobile-refresh {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* Hide refresh button when panel is closed */
|
||||
.rpg-mobile-refresh {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4040,6 +4043,11 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
|
||||
font-size: clamp(20px, 5.1vw, 26px) !important;
|
||||
}
|
||||
|
||||
/* Larger mobile refresh icon (same as toggle) */
|
||||
.rpg-mobile-refresh {
|
||||
font-size: clamp(20px, 5.1vw, 26px) !important;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
MOBILE SETTINGS POPUP
|
||||
======================================== */
|
||||
|
||||
@@ -54,11 +54,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Floating Refresh Button (shown on all tabs) -->
|
||||
<button id="rpg-manual-update-mobile" class="rpg-refresh-icon-btn" title="Refresh RPG Info">
|
||||
<i class="fa-solid fa-sync"></i>
|
||||
</button>
|
||||
|
||||
<!-- HTML Prompt Toggle -->
|
||||
<div class="rpg-toggle-container">
|
||||
<label class="rpg-toggle-label">
|
||||
|
||||
Reference in New Issue
Block a user