feat(ItemSettingsModal): enhance settings UI with improved input styling and dynamic field handling

This commit is contained in:
alexsparkes
2026-02-03 21:31:50 +00:00
parent ede1615ab8
commit 5246455aca
3 changed files with 78 additions and 13 deletions

View File

@@ -44,13 +44,14 @@ export async function fetchFromMUE(packId, settings) {
*/
export async function fetchFromUnsplash(packId, settings) {
const { collections } = settings;
const trimmedCollections = collections?.trim();
const params = new URLSearchParams({
quality: 'high',
});
if (collections) {
params.append('collections', collections);
if (trimmedCollections) {
params.append('collections', trimmedCollections);
}
try {

View File

@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from 'react';
import Modal from 'react-modal';
import variables from 'config/variables';
import EventBus from 'utils/eventbus';
import { Dropdown, Text, Switch, Slider, ChipSelect } from 'components/Form/Settings';
import { Dropdown, Switch, Slider, ChipSelect } from 'components/Form/Settings';
import { Button } from 'components/Elements';
import { refreshAPIPackCache } from 'features/background/api/photoPackAPI';
import { MdRefresh, MdWarning, MdClose, MdCheckCircle, MdCancel } from 'react-icons/md';
@@ -78,11 +78,24 @@ const ItemSettingsModal = ({ pack, isOpen, onClose, isEnabled }) => {
validateSettings();
}, [settings, validateSettings, pack.settings_schema]);
const handleSettingChange = (key, value, secure = false) => {
const handleSettingChange = async (key, value, secure = false) => {
const processedValue = secure ? btoa(value) : value;
const newSettings = { ...settings, [key]: processedValue };
setSettings(newSettings);
localStorage.setItem(`photopack_settings_${pack.id}`, JSON.stringify(newSettings));
// Clear cache and immediately refresh when settings change
const apiPackCache = JSON.parse(localStorage.getItem('api_pack_cache') || '{}');
if (apiPackCache[pack.id]) {
delete apiPackCache[pack.id];
localStorage.setItem('api_pack_cache', JSON.stringify(apiPackCache));
}
// Trigger immediate refresh with new settings
setIsRefreshing(true);
await refreshAPIPackCache(pack.id);
setIsRefreshing(false);
EventBus.emit('refresh', 'background');
};
const handleManualRefresh = async () => {
@@ -130,15 +143,19 @@ const ItemSettingsModal = ({ pack, isOpen, onClose, isEnabled }) => {
case 'text':
return (
<Text
title={field.label}
placeholder={field.placeholder}
value={value}
name={`${pack.id}_${field.key}`}
type={field.secure ? 'password' : 'text'}
onChange={(e) => handleSettingChange(field.key, e.target.value, field.secure)}
subtitle={field.help_text}
/>
<div className="itemSettings-field-group">
<label className="itemSettings-field-label">{field.label}</label>
<input
type={field.secure ? 'password' : 'text'}
value={value}
onChange={(e) => handleSettingChange(field.key, e.target.value, field.secure)}
placeholder={field.placeholder || ''}
className="itemSettings-field-input"
/>
{field.help_text && (
<p className="itemSettings-field-description">{field.help_text}</p>
)}
</div>
);
case 'switch':

View File

@@ -1,3 +1,5 @@
@use 'scss/variables' as *;
.itemSettingsModal {
max-width: 600px;
width: 90%;
@@ -149,6 +151,51 @@
width: 100%;
}
.itemSettings-field-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.itemSettings-field-label {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--subtitle-color, rgba(255, 255, 255, 0.5));
font-weight: 600;
}
.itemSettings-field-description {
font-size: 0.7rem;
color: var(--subtitle-color, rgba(255, 255, 255, 0.4));
margin: 0;
line-height: 1.4;
}
.itemSettings-field-input {
height: 56px;
padding: 0 16px;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
transition: all 0.2s;
font-size: 1rem;
@include themed() {
background: t($modal-sidebar);
border: 1px solid t($modal-sidebarActive);
border-radius: t($borderRadius);
color: t($color);
&:hover,
&:focus {
border-color: t($color);
}
&::placeholder {
color: t($subColor);
}
}
}
.itemSettings-actions {
display: flex;
justify-content: flex-end;