feat(appearance): left stripe by default, with fill and strength as choices
The first version filled the whole row at 24%, and in a real log that meant every row was painted: nearly every contact has SOME QSL state, so colour was present everywhere and stopped being information — a striped background with the data behind it. The default is now a 3px stripe down the left edge. Same signal, nothing lost to read it. A filled row is still offered, with a strength slider, for operators who want the block — and the rule cards in Settings preview whichever is chosen, so the decision is made by looking rather than by imagining. Drawn as an inset shadow rather than a border: a border would shift the cells three pixels on coloured rows only, and the columns would stop lining up. Style and strength are normalised rather than rejected — a value out of range is a slider that got away, not a reason to reset the operator's colours.
This commit is contained in:
@@ -5,11 +5,16 @@
|
||||
// "sent, awaiting reply".
|
||||
|
||||
export type RowColorRule = { id: string; color: string; enabled: boolean };
|
||||
export type RowColorSettings = { enabled: boolean; rules: RowColorRule[] };
|
||||
export type RowColorSettings = {
|
||||
enabled: boolean;
|
||||
style?: 'bar' | 'tint' | 'both';
|
||||
intensity?: number;
|
||||
rules: RowColorRule[];
|
||||
};
|
||||
|
||||
// ADIF QSL fields are single letters. Y is the only one that means "yes";
|
||||
// R (requested) and Q (queued) mean a card is owed, which is a different state
|
||||
// and the one an operator is looking for when deciding what to post.
|
||||
// R (requested) and Q (queued) mean it has not gone out yet, which is a
|
||||
// different state and the one an operator looks for when deciding what to send.
|
||||
const yes = (v: any) => String(v ?? '').trim().toUpperCase() === 'Y';
|
||||
const owed = (v: any) => {
|
||||
const s = String(v ?? '').trim().toUpperCase();
|
||||
@@ -22,20 +27,35 @@ export function matchRowRule(q: any): string | null {
|
||||
if (yes(q.qsl_rcvd) || yes(q.eqsl_rcvd)) return 'confirmed_paper';
|
||||
if (yes(q.qsl_sent) || yes(q.lotw_sent) || yes(q.eqsl_sent)) return 'sent_waiting';
|
||||
// Any route still queued, not just the paper card. LoTW marks a pending upload
|
||||
// as R, which is the commonest "not gone out yet" state in a digital log and
|
||||
// was matching nothing at all while this only looked at qsl_sent.
|
||||
// as R, which is the commonest "not gone out yet" state in a digital log.
|
||||
if (owed(q.qsl_sent) || owed(q.lotw_sent) || owed(q.eqsl_sent)) return 'to_send';
|
||||
return null;
|
||||
}
|
||||
|
||||
// The colour is applied as a TINT, not a fill. The grid is dark and a solid
|
||||
// user-picked colour behind white text is unreadable at exactly the moment it
|
||||
// matters — Logger32 gets away with it because its grid is white.
|
||||
export function rowStyleFor(q: any, cfg: RowColorSettings | null): { backgroundColor: string } | undefined {
|
||||
// The colour is never a fill.
|
||||
//
|
||||
// A log where nearly every contact has SOME QSL state ends up with every row
|
||||
// painted, and colour that is always present stops being information — it
|
||||
// becomes a striped background with the data behind it. The default is a stripe
|
||||
// down the left edge: same signal, nothing lost to read it. A tint is offered
|
||||
// for operators who want the block, at a strength they choose.
|
||||
export function rowStyleFor(q: any, cfg: RowColorSettings | null): Record<string, string> | undefined {
|
||||
if (!cfg?.enabled) return undefined;
|
||||
const id = matchRowRule(q);
|
||||
if (!id) return undefined;
|
||||
const rule = cfg.rules?.find((r) => r.id === id);
|
||||
if (!rule?.enabled || !rule.color) return undefined;
|
||||
return { backgroundColor: `color-mix(in srgb, ${rule.color} 24%, transparent)` };
|
||||
|
||||
const style = cfg.style ?? 'bar';
|
||||
const pct = Math.max(5, Math.min(45, cfg.intensity ?? 12));
|
||||
const out: Record<string, string> = {};
|
||||
if (style === 'tint' || style === 'both') {
|
||||
out.backgroundColor = `color-mix(in srgb, ${rule.color} ${pct}%, transparent)`;
|
||||
}
|
||||
if (style === 'bar' || style === 'both') {
|
||||
// inset shadow rather than a border: a border would shift the cell layout by
|
||||
// three pixels on coloured rows only, and the columns would no longer line up.
|
||||
out.boxShadow = `inset 3px 0 0 ${rule.color}`;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user