refactor: make zap split sliders independent using weights

- Changed from percentage-based to weight-based zap splits
- All three sliders (highlighter, author, Boris) are now independent
- Weights are normalized to calculate actual percentages
- UI shows both weight value and calculated percentage
- Added migration logic for users with old percentage-based settings
- Each slider can be adjusted without affecting the others
- Prevents interdependent slider behavior that was confusing

Breaking change: Settings now use zapSplitHighlighterWeight,
zapSplitAuthorWeight, and zapSplitBorisWeight instead of
zapSplitPercentage and borisSupportPercentage
This commit is contained in:
Gigi
2025-10-08 07:06:42 +01:00
parent 9b97715274
commit f6d2f98eae
4 changed files with 113 additions and 53 deletions

View File

@@ -7,34 +7,53 @@ interface ZapSettingsProps {
}
const ZapSettings: React.FC<ZapSettingsProps> = ({ settings, onUpdate }) => {
const highlighterPercentage = settings.zapSplitPercentage ?? 50
const borisPercentage = settings.borisSupportPercentage ?? 2.1
const authorPercentage = Math.max(0, 100 - highlighterPercentage - borisPercentage)
const highlighterWeight = settings.zapSplitHighlighterWeight ?? 50
const borisWeight = settings.zapSplitBorisWeight ?? 2.1
const authorWeight = settings.zapSplitAuthorWeight ?? 50
// Calculate actual percentages from weights
const totalWeight = highlighterWeight + borisWeight + authorWeight
const highlighterPercentage = totalWeight > 0 ? (highlighterWeight / totalWeight) * 100 : 0
const borisPercentage = totalWeight > 0 ? (borisWeight / totalWeight) * 100 : 0
const authorPercentage = totalWeight > 0 ? (authorWeight / totalWeight) * 100 : 0
return (
<div className="settings-section">
<h3 className="section-title">Zap Splits</h3>
<div className="setting-group">
<label className="setting-label">Split Percentage for Highlights</label>
<label className="setting-label">Your Share</label>
<div className="zap-split-container">
<div className="zap-split-labels">
<span className="zap-split-label">You: {highlighterPercentage}%</span>
<span className="zap-split-label">Author(s): {authorPercentage.toFixed(1)}%</span>
<span className="zap-split-label">Boris: {borisPercentage}%</span>
<span className="zap-split-label">Weight: {highlighterWeight}</span>
<span className="zap-split-label">({highlighterPercentage.toFixed(1)}%)</span>
</div>
<input
type="range"
min="0"
max="100"
value={highlighterPercentage}
onChange={(e) => onUpdate({ zapSplitPercentage: parseInt(e.target.value) })}
value={highlighterWeight}
onChange={(e) => onUpdate({ zapSplitHighlighterWeight: parseInt(e.target.value) })}
className="zap-split-slider"
/>
<div className="zap-split-description">
When you highlight nostr-native content, zaps will be split between you (curator) and the author(s).
If the content has multiple authors, their share is divided proportionally.
</div>
</div>
<div className="setting-group">
<label className="setting-label">Author(s) Share</label>
<div className="zap-split-container">
<div className="zap-split-labels">
<span className="zap-split-label">Weight: {authorWeight}</span>
<span className="zap-split-label">({authorPercentage.toFixed(1)}%)</span>
</div>
<input
type="range"
min="0"
max="100"
value={authorWeight}
onChange={(e) => onUpdate({ zapSplitAuthorWeight: parseInt(e.target.value) })}
className="zap-split-slider"
/>
</div>
</div>
@@ -42,22 +61,25 @@ const ZapSettings: React.FC<ZapSettingsProps> = ({ settings, onUpdate }) => {
<label className="setting-label">Support Boris</label>
<div className="zap-split-container">
<div className="zap-split-labels">
<span className="zap-split-label">{borisPercentage.toFixed(1)}%</span>
<span className="zap-split-label">Weight: {borisWeight.toFixed(1)}</span>
<span className="zap-split-label">({borisPercentage.toFixed(1)}%)</span>
</div>
<input
type="range"
min="0"
max="10"
step="0.1"
value={borisPercentage}
onChange={(e) => onUpdate({ borisSupportPercentage: parseFloat(e.target.value) })}
value={borisWeight}
onChange={(e) => onUpdate({ zapSplitBorisWeight: parseFloat(e.target.value) })}
className="zap-split-slider"
/>
<div className="zap-split-description">
Optional: Include a small percentage for Boris development and maintenance.
</div>
</div>
</div>
<div className="zap-split-description">
Weights determine zap splits when highlighting nostr-native content.
If the content has multiple authors, their share is divided proportionally.
</div>
</div>
)
}