This guide provides a systematic approach to diagnosing and fixing common issues in MuteSky.
Symptoms:
- Keywords muted in advanced mode show as "to unmute" in simple mode
- Checkboxes in advanced mode check then uncheck after half second
- State inconsistency between modes
Diagnostic Steps:
- Check mode state:
console.debug('[Mode] Current mode:', state.mode);
console.debug('[Mode] Active keywords:', state.activeKeywords.size);
console.debug('[Mode] Original muted:', state.originalMutedKeywords.size);
- Verify state hierarchy:
// Advanced mode should be source of truth
console.debug('[State] Advanced selections:', {
activeKeywords: Array.from(state.activeKeywords),
manuallyUnchecked: Array.from(state.manuallyUnchecked)
});
// Simple mode should derive from this
console.debug('[State] Simple mode state:', {
selectedContexts: Array.from(state.selectedContexts),
selectedExceptions: Array.from(state.selectedExceptions)
});
Symptoms:
- Inconsistent state across mode switches
- Lost preferences after operations
- Unexpected state changes
Diagnostic Steps:
- Check state relationships:
console.debug('[State] State relationships:', {
activeKeywords: state.activeKeywords.size,
originalMuted: state.originalMutedKeywords.size,
sessionMuted: state.sessionMutedKeywords.size,
manuallyUnchecked: state.manuallyUnchecked.size
});
- Verify state persistence:
// Check storage key
const storageKey = getStorageKey();
console.debug('[Storage] Current key:', storageKey);
// Check saved state
const savedState = localStorage.getItem(storageKey);
console.debug('[Storage] Saved state exists:', !!savedState);
Symptoms:
- Keywords not matching case variants
- Duplicate keywords with different cases
- Large payload sizes to Bluesky
Diagnostic Steps:
- Check case handling:
// Log case variants
const keyword = 'Example';
console.debug('[Case] Variants:', {
original: keyword,
lower: keyword.toLowerCase(),
stored: state.originalMutedKeywords.has(keyword.toLowerCase()),
active: state.activeKeywords.has(keyword)
});
- Check payload size:
// Log unique keywords
const uniqueKeywords = new Set(
Array.from(state.activeKeywords).map(k => k.toLowerCase())
);
console.debug('[Payload] Unique keywords:', uniqueKeywords.size);
Symptoms:
- "No DID set in state" errors
- Inconsistent auth state
- Session refresh problems
Diagnostic Steps:
- Check auth state:
console.debug('[Auth] State:', {
authenticated: state.authenticated,
did: state.did,
hasSession: !!session
});
- Verify DID consistency:
// Check DID across components
console.debug('[DID] Storage key:', getStorageKey());
console.debug('[DID] State DID:', state.did);
console.debug('[DID] Session DID:', session?.did);
export async function updateSimpleModeState() {
if (!state.authenticated) return;
// Only rebuild in simple mode
if (state.mode === 'simple') {
// Your mode-specific logic here
}
await debouncedUpdate(async () => {
renderInterface();
await saveState();
});
}
function saveState() {
if (!state.did) {
console.error('[State] Cannot save - no DID');
return;
}
const key = getStorageKey();
try {
localStorage.setItem(key, JSON.stringify({
// Your state here
}));
} catch (error) {
console.error('[State] Save failed:', error);
}
}
// Store lowercase for comparison
const lowerKeyword = keyword.toLowerCase();
state.originalMutedKeywords.add(lowerKeyword);
// Preserve original case for display
const originalCase = ourKeywordsMap.get(lowerKeyword);
if (originalCase) {
state.activeKeywords.add(originalCase);
}
function isAuthenticated() {
return state.authenticated && state.did;
}
// Use consistently across all files
if (!isAuthenticated()) {
console.error('[Auth] Not authenticated');
return;
}
- Verify mode before state rebuilds
- Respect mode hierarchy
- Test mode transitions
- Log state changes
- Check DID before operations
- Verify state relationships
- Test persistence
- Handle errors gracefully
- Use lowercase for comparisons
- Preserve original case
- Check payload sizes
- Implement deduplication
- Verify DID consistency
- Handle session refresh
- Test auth flows
- Log auth state changes
function inspectState() {
return {
mode: state.mode,
auth: {
authenticated: state.authenticated,
did: state.did
},
keywords: {
active: state.activeKeywords.size,
original: state.originalMutedKeywords.size,
session: state.sessionMutedKeywords.size,
unchecked: state.manuallyUnchecked.size
},
contexts: {
selected: state.selectedContexts.size,
exceptions: state.selectedExceptions.size
}
};
}
function validateStorage() {
const key = getStorageKey();
try {
const saved = localStorage.getItem(key);
const parsed = JSON.parse(saved);
return {
valid: true,
data: parsed
};
} catch (error) {
return {
valid: false,
error: error.message
};
}
}
- Always log state changes:
console.debug('[State] Before:', inspectState());
// Make changes
console.debug('[State] After:', inspectState());
- Verify auth state consistently:
if (!isAuthenticated()) {
console.error('[Auth] Operation failed - not authenticated');
return;
}
- Handle errors gracefully:
try {
await operation();
} catch (error) {
console.error('[Error]', {
operation: 'name',
error: error.message,
state: inspectState()
});
}
- Test mode transitions thoroughly:
async function testModeTransition() {
console.debug('[Test] Before switch:', inspectState());
await switchMode(newMode);
console.debug('[Test] After switch:', inspectState());
}