Check Point
Rolling release / release (push) Successful in 6m36s

This commit is contained in:
2026-09-12 09:07:09 -04:00
parent e9040d110a
commit a4073b9020
63 changed files with 2459 additions and 632 deletions
@@ -0,0 +1,43 @@
// Shared by GNOME preferences and the daemon; no platform-specific imports.
export function normalizeSettings(source, fields, { strict = false } = {}) {
const config = source && typeof source === 'object' && !Array.isArray(source) ? source : {};
const result = {};
for (const field of fields) {
let value = config[field.key];
if (value == null) {
for (const alias of field.aliases || []) if (config[alias] != null) { value = config[alias]; break; }
}
if (value == null) value = field.default;
if (field.type === 'boolean' && typeof value === 'string') {
const flag = value.trim().toLowerCase();
if (['false', '0', 'off', 'no'].includes(flag)) value = false;
else if (['true', '1', 'on', 'yes'].includes(flag)) value = true;
}
if (field.type === 'number' && typeof value === 'string' && value.trim()) value = Number(value);
if (field.type === 'list' && typeof value === 'string') value = value.split(',').map(v => v.trim()).filter(Boolean);
if (field.key === 'asrLanguage' && typeof value === 'string') value = value.toLowerCase().split(/[-_]/)[0];
if (['string', 'file'].includes(field.type) && typeof value === 'string') value = value.trim();
const valid = field.type === 'boolean' ? typeof value === 'boolean'
: field.type === 'number' ? Number.isFinite(value) && value >= field.min && value <= field.max && (field.step < 1 || Number.isInteger(value))
: field.type === 'choice' ? field.options.some(option => option.value === value)
: field.type === 'list' ? Array.isArray(value) && value.every(item => typeof item === 'string')
: typeof value === 'string' && value.length <= 4096;
if (!valid && strict) throw new Error(`Invalid value for ${field.title}`);
result[field.key] = valid ? value : field.default;
}
if (result.vadMinSpeechMs > result.vadMaxSpeechSeconds * 1000) throw new Error('Minimum speech must be shorter than the maximum recording');
return result;
}
export function mergeSettings(source, changes, fields) {
const merged = { ...source, ...changes };
// Remove obsolete aliases only for settings actually changed by this window.
for (const field of fields) if (Object.hasOwn(changes, field.key)) {
for (const alias of field.aliases || []) delete merged[alias];
}
return merged;
}
export function settingVisible(field, values) {
return !field.when || Object.entries(field.when).every(([key, choices]) => choices.includes(values[key]));
}