feat: more settings
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
* Extracts v2 inventory data from AI-generated text
|
||||
*/
|
||||
|
||||
import { extensionSettings } from '../../core/state.js';
|
||||
|
||||
// Type imports
|
||||
/** @typedef {import('../../types/inventory.js').InventoryV2} InventoryV2 */
|
||||
|
||||
@@ -101,30 +103,84 @@ export function extractLegacyInventory(text) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts simplified inventory data (single "Inventory:" line).
|
||||
* Used when useSimplifiedInventory setting is enabled.
|
||||
*
|
||||
* Expected format: "Inventory: Sword, Shield, 3x Potions, Gold coins"
|
||||
*
|
||||
* @param {string} text - Text that may contain simplified inventory
|
||||
* @returns {InventoryV2|null} Parsed inventory or null
|
||||
*/
|
||||
export function extractSimplifiedInventory(text) {
|
||||
if (!text || typeof text !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Match simplified format: "Inventory: ..."
|
||||
const match = text.match(/Inventory:\s*(.+?)(?:\n|$)/i);
|
||||
if (match && match[1]) {
|
||||
const inventoryText = match[1].trim();
|
||||
// Return null for empty values like "None" or ""
|
||||
if (!inventoryText || inventoryText.toLowerCase() === 'none') {
|
||||
return null;
|
||||
}
|
||||
// Return v2 format with items stored in both 'items' (for simplified display)
|
||||
// and 'onPerson' (for backward compatibility)
|
||||
return {
|
||||
version: 2,
|
||||
onPerson: inventoryText,
|
||||
stored: {},
|
||||
assets: "None",
|
||||
items: inventoryText, // Simplified inventory storage
|
||||
simplified: true // Flag to indicate this is simplified format
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main inventory extraction function that tries v2 format first, then falls back to v1.
|
||||
* Converts v1 format to v2 automatically if found.
|
||||
* When useSimplifiedInventory is enabled, prioritizes simple "Inventory:" format.
|
||||
*
|
||||
* @param {string} statsText - Raw stats text from AI response
|
||||
* @returns {InventoryV2|null} Parsed inventory in v2 format or null
|
||||
*/
|
||||
export function extractInventory(statsText) {
|
||||
// If simplified inventory mode is enabled, try simplified format first
|
||||
if (extensionSettings.useSimplifiedInventory) {
|
||||
const simplifiedData = extractSimplifiedInventory(statsText);
|
||||
if (simplifiedData) {
|
||||
return simplifiedData;
|
||||
}
|
||||
}
|
||||
|
||||
// Try v2 format first
|
||||
const v2Data = extractInventoryData(statsText);
|
||||
if (v2Data) {
|
||||
return v2Data;
|
||||
}
|
||||
|
||||
// Fallback to v1 format and convert to v2
|
||||
// Fallback to v1/simplified format and convert to v2
|
||||
const v1Data = extractLegacyInventory(statsText);
|
||||
if (v1Data) {
|
||||
// Convert v1 string to v2 format (place in onPerson)
|
||||
return {
|
||||
const result = {
|
||||
version: 2,
|
||||
onPerson: v1Data,
|
||||
stored: {},
|
||||
assets: "None"
|
||||
};
|
||||
|
||||
// If simplified mode, also store in items field
|
||||
if (extensionSettings.useSimplifiedInventory) {
|
||||
result.items = v1Data;
|
||||
result.simplified = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// No inventory data found
|
||||
|
||||
@@ -16,6 +16,12 @@ import { extensionSettings, committedTrackerData, FEATURE_FLAGS } from '../../co
|
||||
*/
|
||||
export const DEFAULT_HTML_PROMPT = `If appropriate, include inline HTML, CSS, and JS segments whenever they enhance visual storytelling (e.g., for in-world screens, posters, books, letters, signs, crests, labels, etc.). Style them to match the setting's theme (e.g., fantasy, sci-fi), keep the text readable, and embed all assets directly (using inline SVGs only with no external scripts, libraries, or fonts). Use these elements freely and naturally within the narrative as characters would encounter them, including animations, 3D effects, pop-ups, dropdowns, websites, and so on. Do not wrap the HTML/CSS/JS in code fences!`;
|
||||
|
||||
/**
|
||||
* Default tracker instruction prompt text
|
||||
* Use {{user}} as placeholder for the user's name (will be replaced at runtime)
|
||||
*/
|
||||
export const DEFAULT_TRACKER_PROMPT = `At the start of every reply, you must attach an update to the trackers in EXACTLY the same format as below, enclosed in separate Markdown code fences. Replace X with actual numbers (e.g., 69) and replace all [placeholders] with concrete in-world details that {{user}} perceives about the current scene and the present characters. Do NOT keep the brackets or placeholder text in your response. For example: [Location] becomes Forest Clearing, [Mood Emoji] becomes 😊. Consider the last trackers in the conversation (if they exist). Manage them accordingly and realistically; raise, lower, change, or keep the values unchanged based on the user's actions, the passage of time, and logical consequences (0% if the time progressed only by a few minutes, 1-5% normally, and above 5% only if a major time-skip/event occurs).`;
|
||||
|
||||
/**
|
||||
* Gets character card information for current chat (handles both single and group chats)
|
||||
* @returns {string} Formatted character information
|
||||
@@ -91,11 +97,18 @@ async function getCharacterCardsInfo() {
|
||||
export function buildInventorySummary(inventory) {
|
||||
// Handle legacy v1 string format
|
||||
if (typeof inventory === 'string') {
|
||||
return inventory;
|
||||
return `Inventory: ${inventory}`;
|
||||
}
|
||||
|
||||
// Handle v2 object format
|
||||
if (inventory && typeof inventory === 'object' && inventory.version === 2) {
|
||||
// Check for simplified inventory mode
|
||||
if (inventory.simplified || extensionSettings.useSimplifiedInventory) {
|
||||
const items = inventory.items || inventory.onPerson || 'None';
|
||||
return `Inventory: ${items}`;
|
||||
}
|
||||
|
||||
// Full categorized format
|
||||
let summary = '';
|
||||
|
||||
// Add On Person section
|
||||
@@ -204,9 +217,9 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon
|
||||
|
||||
// Only add tracker instructions if at least one tracker is enabled
|
||||
if (hasAnyTrackers) {
|
||||
// Universal instruction header
|
||||
instructions += `\nAt the start of every reply, you must attach an update to the trackers in EXACTLY the same format as below, enclosed in separate Markdown code fences. Replace X with actual numbers (e.g., 69) and replace all [placeholders] with concrete in-world details that ${userName} perceives about the current scene and the present characters. Do NOT keep the brackets or placeholder text in your response. For example: [Location] becomes Forest Clearing, [Mood Emoji] becomes 😊. Consider the last trackers in the conversation (if they exist). Manage them accordingly and realistically; raise, lower, change, or keep the values unchanged based on the user's actions, the passage of time, and logical consequences (0% if the time progressed only by a few minutes, 1-5% normally, and above 5% only if a major time-skip/event occurs).
|
||||
`;
|
||||
// Universal instruction header - use custom prompt if set, otherwise use default
|
||||
const trackerPrompt = (extensionSettings.customTrackerPrompt || DEFAULT_TRACKER_PROMPT).replace(/\{\{user\}\}/g, userName);
|
||||
instructions += `\n${trackerPrompt}\n`;
|
||||
|
||||
// Add format specifications for each enabled tracker
|
||||
if (extensionSettings.showUserStats) {
|
||||
@@ -241,9 +254,13 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon
|
||||
instructions += `Skills: [${skillFieldsText || 'Skill1, Skill2, etc.'}]\n`;
|
||||
}
|
||||
|
||||
// Add inventory format based on feature flag - only if showInventory is enabled
|
||||
// Add inventory format - only if showInventory is enabled
|
||||
if (extensionSettings.showInventory) {
|
||||
if (FEATURE_FLAGS.useNewInventory) {
|
||||
if (extensionSettings.useSimplifiedInventory) {
|
||||
// Simplified single-line inventory format
|
||||
instructions += 'Inventory: [Items currently carried/worn/owned, or "None"]\n';
|
||||
} else if (FEATURE_FLAGS.useNewInventory) {
|
||||
// Full v2 categorized inventory format
|
||||
instructions += 'On Person: [Items currently carried/worn, or "None"]\n';
|
||||
instructions += 'Stored - [Location Name]: [Items stored at this location]\n';
|
||||
instructions += '(Add multiple "Stored - [Location]:" lines as needed for different storage locations)\n';
|
||||
@@ -254,9 +271,11 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon
|
||||
}
|
||||
}
|
||||
|
||||
// Add quests section
|
||||
instructions += 'Main Quests: [Short title of the currently active main quest (for example, "Save the world"), or "None"]\n';
|
||||
instructions += 'Optional Quests: [Short titles of the currently active optional quests (for example, "Find Zandik\'s book"), or "None"]\n';
|
||||
// Add quests section - only if showQuests is enabled
|
||||
if (extensionSettings.showQuests) {
|
||||
instructions += 'Main Quests: [Short title of the currently active main quest (for example, "Save the world"), or "None"]\n';
|
||||
instructions += 'Optional Quests: [Short titles of the currently active optional quests (for example, "Find Zandik\'s book"), or "None"]\n';
|
||||
}
|
||||
|
||||
instructions += '```\n\n';
|
||||
}
|
||||
@@ -484,8 +503,8 @@ export function generateRPGPromptText() {
|
||||
promptText += `Last ${userName}'s Stats:\nNone - this is the first update.\n\n`;
|
||||
}
|
||||
|
||||
// Add current quests to the previous data context
|
||||
if (extensionSettings.quests) {
|
||||
// Add current quests to the previous data context - only if showQuests is enabled
|
||||
if (extensionSettings.showQuests && extensionSettings.quests) {
|
||||
if (extensionSettings.quests.main && extensionSettings.quests.main !== 'None') {
|
||||
promptText += `Main Quests: ${extensionSettings.quests.main}\n`;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ let openForms = {
|
||||
addLocation: false,
|
||||
addItemOnPerson: false,
|
||||
addItemStored: {}, // { [locationName]: true/false }
|
||||
addItemAssets: false
|
||||
addItemAssets: false,
|
||||
addItemSimplified: false
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -54,7 +55,7 @@ function updateLastGeneratedDataInventory() {
|
||||
|
||||
/**
|
||||
* Shows the inline form for adding a new item.
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets')
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets', 'simplified')
|
||||
* @param {string} [location] - Location name (required for 'stored' field)
|
||||
*/
|
||||
export function showAddItemForm(field, location) {
|
||||
@@ -76,6 +77,8 @@ export function showAddItemForm(field, location) {
|
||||
openForms.addItemOnPerson = true;
|
||||
} else if (field === 'assets') {
|
||||
openForms.addItemAssets = true;
|
||||
} else if (field === 'simplified') {
|
||||
openForms.addItemSimplified = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +91,7 @@ export function showAddItemForm(field, location) {
|
||||
|
||||
/**
|
||||
* Hides the inline form for adding a new item.
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets')
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets', 'simplified')
|
||||
* @param {string} [location] - Location name (required for 'stored' field)
|
||||
*/
|
||||
export function hideAddItemForm(field, location) {
|
||||
@@ -111,6 +114,8 @@ export function hideAddItemForm(field, location) {
|
||||
openForms.addItemOnPerson = false;
|
||||
} else if (field === 'assets') {
|
||||
openForms.addItemAssets = false;
|
||||
} else if (field === 'simplified') {
|
||||
openForms.addItemSimplified = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +128,7 @@ export function hideAddItemForm(field, location) {
|
||||
|
||||
/**
|
||||
* Adds a new item to the inventory.
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets')
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets', 'simplified')
|
||||
* @param {string} [location] - Location name (required for 'stored' field)
|
||||
*/
|
||||
export function saveAddItem(field, location) {
|
||||
@@ -154,7 +159,10 @@ export function saveAddItem(field, location) {
|
||||
|
||||
// Get current items, add new one, serialize back
|
||||
let currentString;
|
||||
if (field === 'stored') {
|
||||
if (field === 'simplified') {
|
||||
// For simplified inventory, use items field or fall back to onPerson
|
||||
currentString = inventory.items || inventory.onPerson || 'None';
|
||||
} else if (field === 'stored') {
|
||||
currentString = inventory.stored[location] || 'None';
|
||||
} else {
|
||||
currentString = inventory[field] || 'None';
|
||||
@@ -165,7 +173,11 @@ export function saveAddItem(field, location) {
|
||||
const newString = serializeItems(items);
|
||||
|
||||
// Save back to inventory
|
||||
if (field === 'stored') {
|
||||
if (field === 'simplified') {
|
||||
// Update both items and onPerson for simplified mode
|
||||
inventory.items = newString;
|
||||
inventory.onPerson = newString;
|
||||
} else if (field === 'stored') {
|
||||
inventory.stored[location] = newString;
|
||||
} else {
|
||||
inventory[field] = newString;
|
||||
@@ -183,7 +195,7 @@ export function saveAddItem(field, location) {
|
||||
|
||||
/**
|
||||
* Removes an item from the inventory.
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets')
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets', 'simplified')
|
||||
* @param {number} itemIndex - Index of item to remove
|
||||
* @param {string} [location] - Location name (required for 'stored' field)
|
||||
*/
|
||||
@@ -194,7 +206,10 @@ export function removeItem(field, itemIndex, location) {
|
||||
|
||||
// Get current items, remove the one at index, serialize back
|
||||
let currentString;
|
||||
if (field === 'stored') {
|
||||
if (field === 'simplified') {
|
||||
// For simplified inventory, use items field or fall back to onPerson
|
||||
currentString = inventory.items || inventory.onPerson || 'None';
|
||||
} else if (field === 'stored') {
|
||||
currentString = inventory.stored[location] || 'None';
|
||||
} else {
|
||||
currentString = inventory[field] || 'None';
|
||||
@@ -212,7 +227,11 @@ export function removeItem(field, itemIndex, location) {
|
||||
// console.log('[RPG Companion] DEBUG newString after removal:', newString);
|
||||
|
||||
// Save back to inventory
|
||||
if (field === 'stored') {
|
||||
if (field === 'simplified') {
|
||||
// Update both items and onPerson for simplified mode
|
||||
inventory.items = newString;
|
||||
inventory.onPerson = newString;
|
||||
} else if (field === 'stored') {
|
||||
inventory.stored[location] = newString;
|
||||
} else {
|
||||
inventory[field] = newString;
|
||||
@@ -585,6 +604,15 @@ export function restoreFormStates() {
|
||||
}
|
||||
}
|
||||
|
||||
// Restore add item simplified form
|
||||
if (openForms.addItemSimplified) {
|
||||
const form = $('#rpg-add-item-form-simplified');
|
||||
const input = $('#rpg-new-item-simplified');
|
||||
if (form.length > 0) {
|
||||
form.show();
|
||||
}
|
||||
}
|
||||
|
||||
// Restore add item stored forms (for each location)
|
||||
// Clean up orphaned states for deleted locations (Bug #3 fix)
|
||||
if (openForms.addItemStored && typeof openForms.addItemStored === 'object') {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { sanitizeItemName } from '../../utils/security.js';
|
||||
* Updates an existing inventory item's name.
|
||||
* Validates, sanitizes, and persists the change.
|
||||
*
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets')
|
||||
* @param {string} field - Field name ('onPerson', 'stored', 'assets', 'simplified')
|
||||
* @param {number} index - Index of item in the array
|
||||
* @param {string} newName - New name for the item
|
||||
* @param {string} [location] - Location name (required for 'stored' field)
|
||||
@@ -33,7 +33,10 @@ export function updateInventoryItem(field, index, newName, location) {
|
||||
|
||||
// Get current items for the field
|
||||
let currentString;
|
||||
if (field === 'stored') {
|
||||
if (field === 'simplified') {
|
||||
// For simplified inventory, use items field or fall back to onPerson
|
||||
currentString = inventory.items || inventory.onPerson || 'None';
|
||||
} else if (field === 'stored') {
|
||||
if (!location) {
|
||||
console.error('[RPG Companion] Location required for stored items');
|
||||
return;
|
||||
@@ -59,7 +62,11 @@ export function updateInventoryItem(field, index, newName, location) {
|
||||
const newItemString = serializeItems(items);
|
||||
|
||||
// Update the inventory
|
||||
if (field === 'stored') {
|
||||
if (field === 'simplified') {
|
||||
// Update both items and onPerson for simplified mode
|
||||
inventory.items = newItemString;
|
||||
inventory.onPerson = newItemString;
|
||||
} else if (field === 'stored') {
|
||||
inventory.stored[location] = newItemString;
|
||||
} else {
|
||||
inventory[field] = newItemString;
|
||||
|
||||
@@ -444,6 +444,85 @@ export function updateInventoryDisplay(containerId, options = {}) {
|
||||
restoreFormStates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the simplified (single-list) inventory view
|
||||
* Used when useSimplifiedInventory setting is enabled
|
||||
* @param {string} itemsString - All items as a comma-separated string
|
||||
* @param {string} viewMode - View mode ('list' or 'grid')
|
||||
* @returns {string} HTML for simplified inventory view
|
||||
*/
|
||||
export function renderSimplifiedInventoryView(itemsString, viewMode = 'list') {
|
||||
const items = parseItems(itemsString);
|
||||
|
||||
let itemsHtml = '';
|
||||
if (items.length === 0) {
|
||||
itemsHtml = `<div class="rpg-inventory-empty" data-i18n-key="inventory.simplified.empty">${i18n.getTranslation('inventory.simplified.empty')}</div>`;
|
||||
} else {
|
||||
if (viewMode === 'grid') {
|
||||
// Grid view: card-style items
|
||||
itemsHtml = items.map((item, index) => `
|
||||
<div class="rpg-item-card" data-field="simplified" data-index="${index}">
|
||||
<button class="rpg-item-remove" data-action="remove-item" data-field="simplified" data-index="${index}" title="${i18n.getTranslation('inventory.simplified.removeTitle')}">
|
||||
<i class="fa-solid fa-times"></i>
|
||||
</button>
|
||||
<span class="rpg-item-name rpg-editable" contenteditable="true" data-field="simplified" data-index="${index}" title="Click to edit">${escapeHtml(item)}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
} else {
|
||||
// List view: full-width rows
|
||||
itemsHtml = items.map((item, index) => `
|
||||
<div class="rpg-item-row" data-field="simplified" data-index="${index}">
|
||||
<span class="rpg-item-name rpg-editable" contenteditable="true" data-field="simplified" data-index="${index}" title="Click to edit">${escapeHtml(item)}</span>
|
||||
<button class="rpg-item-remove" data-action="remove-item" data-field="simplified" data-index="${index}" title="${i18n.getTranslation('inventory.simplified.removeTitle')}">
|
||||
<i class="fa-solid fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
}
|
||||
|
||||
const listViewClass = viewMode === 'list' ? 'rpg-item-list-view' : 'rpg-item-grid-view';
|
||||
|
||||
return `
|
||||
<div class="rpg-inventory-container">
|
||||
<div class="rpg-inventory-section" data-section="simplified">
|
||||
<div class="rpg-inventory-header">
|
||||
<h4 data-i18n-key="inventory.simplified.title">${i18n.getTranslation('inventory.simplified.title')}</h4>
|
||||
<div class="rpg-inventory-header-actions">
|
||||
<div class="rpg-view-toggle">
|
||||
<button class="rpg-view-btn ${viewMode === 'list' ? 'active' : ''}" data-action="switch-view" data-field="simplified" data-view="list" title="${i18n.getTranslation('global.listView')}">
|
||||
<i class="fa-solid fa-list"></i>
|
||||
</button>
|
||||
<button class="rpg-view-btn ${viewMode === 'grid' ? 'active' : ''}" data-action="switch-view" data-field="simplified" data-view="grid" title="${i18n.getTranslation('global.gridView')}">
|
||||
<i class="fa-solid fa-th"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button class="rpg-inventory-add-btn" data-action="add-item" data-field="simplified" title="Add new item">
|
||||
<i class="fa-solid fa-plus"></i> <span data-i18n-key="inventory.simplified.addItemButton">${i18n.getTranslation('inventory.simplified.addItemButton')}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rpg-inventory-content">
|
||||
<div class="rpg-inline-form" id="rpg-add-item-form-simplified" style="display: none;">
|
||||
<input type="text" class="rpg-inline-input" id="rpg-new-item-simplified" placeholder="${i18n.getTranslation('inventory.simplified.addItemPlaceholder')}" data-i18n-placeholder-key="inventory.simplified.addItemPlaceholder" />
|
||||
<div class="rpg-inline-buttons">
|
||||
<button class="rpg-inline-btn rpg-inline-cancel" data-action="cancel-add-item" data-field="simplified">
|
||||
<i class="fa-solid fa-times"></i> <span data-i18n-key="global.cancel">${i18n.getTranslation('global.cancel')}</span>
|
||||
</button>
|
||||
<button class="rpg-inline-btn rpg-inline-save" data-action="save-add-item" data-field="simplified">
|
||||
<i class="fa-solid fa-check"></i> <span data-i18n-key="global.add">${i18n.getTranslation('global.add')}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rpg-item-list ${listViewClass}">
|
||||
${itemsHtml}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main inventory rendering function (matches pattern of other render functions)
|
||||
* Gets data from state/settings and updates DOM directly.
|
||||
@@ -458,11 +537,25 @@ export function renderInventory() {
|
||||
// Get inventory data from settings
|
||||
const inventory = extensionSettings.userStats.inventory;
|
||||
|
||||
// Get current render options (active tab, collapsed locations)
|
||||
const options = getInventoryRenderOptions();
|
||||
let html;
|
||||
|
||||
// Check if we should render simplified inventory
|
||||
if (extensionSettings.useSimplifiedInventory) {
|
||||
// For simplified mode, combine all items into a single string
|
||||
// Use the 'items' field if available (from simplified parsing),
|
||||
// otherwise fall back to onPerson
|
||||
const itemsString = inventory.items || inventory.onPerson || 'None';
|
||||
// Get view mode from settings (use 'simplified' key or fall back to 'onPerson')
|
||||
const viewModes = extensionSettings.inventoryViewModes || {};
|
||||
const viewMode = viewModes.simplified || viewModes.onPerson || 'list';
|
||||
html = renderSimplifiedInventoryView(itemsString, viewMode);
|
||||
} else {
|
||||
// Full categorized inventory
|
||||
// Get current render options (active tab, collapsed locations)
|
||||
const options = getInventoryRenderOptions();
|
||||
html = generateInventoryHTML(inventory, options);
|
||||
}
|
||||
|
||||
// Generate HTML and update DOM
|
||||
const html = generateInventoryHTML(inventory, options);
|
||||
$inventoryContainer.html(html);
|
||||
|
||||
// Restore form states after re-rendering (fixes Bug #1)
|
||||
|
||||
@@ -160,7 +160,7 @@ export function renderOptionalQuestsView(optionalQuests) {
|
||||
* Main render function for quests
|
||||
*/
|
||||
export function renderQuests() {
|
||||
if (!extensionSettings.showInventory || !$questsContainer) {
|
||||
if (!extensionSettings.showQuests || !$questsContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+15
-10
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import { i18n } from '../../core/i18n.js';
|
||||
import { extensionSettings } from '../../core/state.js';
|
||||
|
||||
/**
|
||||
* Sets up desktop tab navigation for organizing content.
|
||||
@@ -31,21 +32,25 @@ export function setupDesktopTabs() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create tab navigation
|
||||
// Create tab navigation - conditionally show inventory and quests tabs based on settings
|
||||
const inventoryTabHtml = extensionSettings.showInventory ? `
|
||||
<button class="rpg-tab-btn" data-tab="inventory">
|
||||
<i class="fa-solid fa-box"></i>
|
||||
<span data-i18n-key="global.inventory">Inventory</span>
|
||||
</button>` : '';
|
||||
|
||||
const questsTabHtml = extensionSettings.showQuests ? `
|
||||
<button class="rpg-tab-btn" data-tab="quests">
|
||||
<i class="fa-solid fa-scroll"></i>
|
||||
<span data-i18n-key="global.quests">Quests</span>
|
||||
</button>` : '';
|
||||
|
||||
const $tabNav = $(`
|
||||
<div class="rpg-tabs-nav">
|
||||
<button class="rpg-tab-btn active" data-tab="status">
|
||||
<i class="fa-solid fa-chart-simple"></i>
|
||||
<span data-i18n-key="global.status">Status</span>
|
||||
</button>
|
||||
<button class="rpg-tab-btn" data-tab="inventory">
|
||||
<i class="fa-solid fa-box"></i>
|
||||
<span data-i18n-key="global.inventory">Inventory</span>
|
||||
</button>
|
||||
<button class="rpg-tab-btn" data-tab="quests">
|
||||
<i class="fa-solid fa-scroll"></i>
|
||||
<span data-i18n-key="global.quests">Quests</span>
|
||||
</button>
|
||||
</button>${inventoryTabHtml}${questsTabHtml}
|
||||
</div>
|
||||
`);
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
$userStatsContainer,
|
||||
$infoBoxContainer,
|
||||
$thoughtsContainer,
|
||||
$inventoryContainer
|
||||
$inventoryContainer,
|
||||
$questsContainer
|
||||
} from '../../core/state.js';
|
||||
import { i18n } from '../../core/i18n.js';
|
||||
|
||||
@@ -230,22 +231,30 @@ export function updateSectionVisibility() {
|
||||
if ($inventoryContainer) {
|
||||
$inventoryContainer.toggle(extensionSettings.showInventory);
|
||||
}
|
||||
if ($questsContainer) {
|
||||
$questsContainer.toggle(extensionSettings.showQuests);
|
||||
}
|
||||
|
||||
// Show/hide dividers intelligently
|
||||
// Divider after User Stats: shown if User Stats is visible AND at least one section after it is visible
|
||||
const showDividerAfterStats = extensionSettings.showUserStats &&
|
||||
(extensionSettings.showInfoBox || extensionSettings.showCharacterThoughts || extensionSettings.showInventory);
|
||||
(extensionSettings.showInfoBox || extensionSettings.showCharacterThoughts || extensionSettings.showInventory || extensionSettings.showQuests);
|
||||
$('#rpg-divider-stats').toggle(showDividerAfterStats);
|
||||
|
||||
// Divider after Info Box: shown if Info Box is visible AND at least one section after it is visible
|
||||
const showDividerAfterInfo = extensionSettings.showInfoBox &&
|
||||
(extensionSettings.showCharacterThoughts || extensionSettings.showInventory);
|
||||
(extensionSettings.showCharacterThoughts || extensionSettings.showInventory || extensionSettings.showQuests);
|
||||
$('#rpg-divider-info').toggle(showDividerAfterInfo);
|
||||
|
||||
// Divider after Thoughts: shown if Thoughts is visible AND Inventory is visible
|
||||
// Divider after Thoughts: shown if Thoughts is visible AND Inventory or Quests is visible
|
||||
const showDividerAfterThoughts = extensionSettings.showCharacterThoughts &&
|
||||
extensionSettings.showInventory;
|
||||
(extensionSettings.showInventory || extensionSettings.showQuests);
|
||||
$('#rpg-divider-thoughts').toggle(showDividerAfterThoughts);
|
||||
|
||||
// Divider after Inventory: shown if Inventory is visible AND Quests is visible
|
||||
const showDividerAfterInventory = extensionSettings.showInventory &&
|
||||
extensionSettings.showQuests;
|
||||
$('#rpg-divider-inventory').toggle(showDividerAfterInventory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user