mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-07 17:23:05 +02:00
Misc bugs around dm region scope + scope display, and flood-scope leak
This commit is contained in:
@@ -7,7 +7,7 @@ import { ChannelFloodScopeOverrideModal } from './ChannelFloodScopeOverrideModal
|
||||
import { ChannelPathHashModeOverrideModal } from './ChannelPathHashModeOverrideModal';
|
||||
import { handleKeyboardActivate } from '../utils/a11y';
|
||||
import { isPublicChannelKey } from '../utils/publicChannel';
|
||||
import { stripRegionScopePrefix } from '../utils/regionScope';
|
||||
import { stripRegionScopePrefix, floodScopeOverrideLabel } from '../utils/regionScope';
|
||||
import { isPrefixOnlyContact } from '../utils/pubkey';
|
||||
import { cn } from '../lib/utils';
|
||||
import { ContactAvatar } from './ContactAvatar';
|
||||
@@ -102,7 +102,9 @@ export function ChatHeader({
|
||||
const activeFloodScopeLabel = activeFloodScopeOverride
|
||||
? stripRegionScopePrefix(activeFloodScopeOverride)
|
||||
: null;
|
||||
const activeFloodScopeDisplay = activeFloodScopeOverride ? activeFloodScopeOverride : null;
|
||||
// Badge text: maps the raw override ("*", "#Region", null) to a friendly label
|
||||
// so the unscoped marker renders as "unscoped" instead of a bare "*".
|
||||
const activeFloodScopeBadge = floodScopeOverrideLabel(activeFloodScopeOverride);
|
||||
const activePathHashModeOverride =
|
||||
conversation.type === 'channel' ? (activeChannel?.path_hash_mode_override ?? null) : null;
|
||||
const showPathHashModeOverride =
|
||||
@@ -256,7 +258,7 @@ export function ChatHeader({
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
{conversation.type === 'channel' && activeFloodScopeDisplay && (
|
||||
{conversation.type === 'channel' && activeFloodScopeBadge && (
|
||||
<button
|
||||
className="mt-0.5 flex basis-full items-center gap-1 text-left sm:hidden"
|
||||
onClick={handleEditFloodScopeOverride}
|
||||
@@ -268,7 +270,7 @@ export function ChatHeader({
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span className="min-w-0 truncate text-[0.6875rem] font-medium text-[hsl(var(--region-override))]">
|
||||
{activeFloodScopeDisplay}
|
||||
{activeFloodScopeBadge}
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
@@ -445,9 +447,9 @@ export function ChatHeader({
|
||||
className={`h-4 w-4 ${activeFloodScopeLabel ? 'text-[hsl(var(--region-override))]' : 'text-muted-foreground'}`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{activeFloodScopeDisplay && (
|
||||
{activeFloodScopeBadge && (
|
||||
<span className="hidden text-[0.6875rem] font-medium text-[hsl(var(--region-override))] sm:inline">
|
||||
{activeFloodScopeDisplay}
|
||||
{activeFloodScopeBadge}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
@@ -513,7 +515,7 @@ export function ChatHeader({
|
||||
open={channelOverrideOpen}
|
||||
onClose={() => setChannelOverrideOpen(false)}
|
||||
roomName={conversation.name}
|
||||
currentOverride={activeFloodScopeDisplay}
|
||||
currentOverride={activeFloodScopeOverride}
|
||||
onSetOverride={(value) => onSetChannelFloodScopeOverride(conversation.id, value)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import {
|
||||
UNSCOPED_OVERRIDE_MARKER,
|
||||
isUnscopedMarker,
|
||||
stripRegionScopePrefix,
|
||||
floodScopeOverrideLabel,
|
||||
} from '../utils/regionScope';
|
||||
|
||||
describe('regionScope helpers', () => {
|
||||
describe('isUnscopedMarker', () => {
|
||||
it('recognizes the unscoped marker', () => {
|
||||
expect(isUnscopedMarker(UNSCOPED_OVERRIDE_MARKER)).toBe(true);
|
||||
expect(isUnscopedMarker('*')).toBe(true);
|
||||
});
|
||||
|
||||
it('rejects regions, null, undefined, and empty', () => {
|
||||
expect(isUnscopedMarker('#Esperance')).toBe(false);
|
||||
expect(isUnscopedMarker('Esperance')).toBe(false);
|
||||
expect(isUnscopedMarker(null)).toBe(false);
|
||||
expect(isUnscopedMarker(undefined)).toBe(false);
|
||||
expect(isUnscopedMarker('')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stripRegionScopePrefix', () => {
|
||||
it('strips a leading hash', () => {
|
||||
expect(stripRegionScopePrefix('#Esperance')).toBe('Esperance');
|
||||
});
|
||||
|
||||
it('leaves unprefixed values (incl. the marker) unchanged', () => {
|
||||
expect(stripRegionScopePrefix('Esperance')).toBe('Esperance');
|
||||
expect(stripRegionScopePrefix('*')).toBe('*');
|
||||
});
|
||||
|
||||
it('returns empty string for nullish input', () => {
|
||||
expect(stripRegionScopePrefix(null)).toBe('');
|
||||
expect(stripRegionScopePrefix(undefined)).toBe('');
|
||||
expect(stripRegionScopePrefix('')).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('floodScopeOverrideLabel', () => {
|
||||
it('returns null when there is no override (inherit)', () => {
|
||||
expect(floodScopeOverrideLabel(null)).toBeNull();
|
||||
expect(floodScopeOverrideLabel(undefined)).toBeNull();
|
||||
expect(floodScopeOverrideLabel('')).toBeNull();
|
||||
});
|
||||
|
||||
it('maps the unscoped marker to a friendly label, not a bare "*"', () => {
|
||||
expect(floodScopeOverrideLabel(UNSCOPED_OVERRIDE_MARKER)).toBe('unscoped');
|
||||
expect(floodScopeOverrideLabel('*')).toBe('unscoped');
|
||||
});
|
||||
|
||||
it('passes a region name through unchanged', () => {
|
||||
expect(floodScopeOverrideLabel('#Esperance')).toBe('#Esperance');
|
||||
expect(floodScopeOverrideLabel('Esperance')).toBe('Esperance');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -11,3 +11,12 @@ export function stripRegionScopePrefix(scope: string | null | undefined): string
|
||||
if (!scope) return '';
|
||||
return scope.startsWith('#') ? scope.slice(1) : scope;
|
||||
}
|
||||
|
||||
// Compact, human-readable label for a channel's persisted flood-scope override,
|
||||
// suitable for a header badge. Returns null when there is no override (inherit),
|
||||
// "unscoped" for the unscoped marker, and the region name as-is otherwise.
|
||||
export function floodScopeOverrideLabel(scope: string | null | undefined): string | null {
|
||||
if (!scope) return null;
|
||||
if (isUnscopedMarker(scope)) return 'unscoped';
|
||||
return scope;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user