mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-03-28 17:43:05 +01:00
Add scroll to repeater infobox on visualizer
This commit is contained in:
@@ -52,6 +52,7 @@ import { getStateKey } from './utils/conversationState';
|
||||
import { appendRawPacketUnique } from './utils/rawPacketIdentity';
|
||||
import { messageContainsMention } from './utils/messageParser';
|
||||
import { mergeContactIntoList } from './utils/contactMerge';
|
||||
import { getLocalLabel, getContrastTextColor } from './utils/localLabel';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { Contact, Conversation, HealthStatus, Message, MessagePath, RawPacket } from './types';
|
||||
|
||||
@@ -66,6 +67,7 @@ export function App() {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const [showCracker, setShowCracker] = useState(false);
|
||||
const [crackerRunning, setCrackerRunning] = useState(false);
|
||||
const [localLabel, setLocalLabel] = useState(getLocalLabel);
|
||||
|
||||
// Defer CrackerPanel mount until first opened (lazy-loaded, but keep mounted after for state)
|
||||
const crackerMounted = useRef(false);
|
||||
@@ -467,6 +469,17 @@ export function App() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
{localLabel.text && (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: localLabel.color,
|
||||
color: getContrastTextColor(localLabel.color),
|
||||
}}
|
||||
className="px-4 py-1 text-center text-sm font-medium"
|
||||
>
|
||||
{localLabel.text}
|
||||
</div>
|
||||
)}
|
||||
<StatusBar
|
||||
health={health}
|
||||
config={config}
|
||||
@@ -621,6 +634,7 @@ export function App() {
|
||||
onAdvertise={handleAdvertise}
|
||||
onHealthRefresh={handleHealthRefresh}
|
||||
onRefreshAppSettings={fetchAppSettings}
|
||||
onLocalLabelChange={setLocalLabel}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
setReopenLastConversationEnabled,
|
||||
} from '../utils/lastViewedConversation';
|
||||
import { RADIO_PRESETS } from '../utils/radioPresets';
|
||||
import { getLocalLabel, setLocalLabel, type LocalLabel } from '../utils/localLabel';
|
||||
|
||||
import { SETTINGS_SECTION_LABELS, type SettingsSection } from './settingsConstants';
|
||||
|
||||
@@ -42,6 +43,7 @@ interface SettingsModalBaseProps {
|
||||
onAdvertise: () => Promise<void>;
|
||||
onHealthRefresh: () => Promise<void>;
|
||||
onRefreshAppSettings: () => Promise<void>;
|
||||
onLocalLabelChange?: (label: LocalLabel) => void;
|
||||
}
|
||||
|
||||
type SettingsModalProps = SettingsModalBaseProps &
|
||||
@@ -65,6 +67,7 @@ export function SettingsModal(props: SettingsModalProps) {
|
||||
onAdvertise,
|
||||
onHealthRefresh,
|
||||
onRefreshAppSettings,
|
||||
onLocalLabelChange,
|
||||
} = props;
|
||||
const externalSidebarNav = props.externalSidebarNav === true;
|
||||
const desktopSection = props.externalSidebarNav ? props.desktopSection : undefined;
|
||||
@@ -118,6 +121,8 @@ export function SettingsModal(props: SettingsModalProps) {
|
||||
const [reopenLastConversation, setReopenLastConversation] = useState(
|
||||
getReopenLastConversationEnabled
|
||||
);
|
||||
const [localLabelText, setLocalLabelText] = useState(() => getLocalLabel().text);
|
||||
const [localLabelColor, setLocalLabelColor] = useState(() => getLocalLabel().color);
|
||||
|
||||
// Advertisement interval state (displayed in hours, stored as seconds in DB)
|
||||
const [advertIntervalHours, setAdvertIntervalHours] = useState('0');
|
||||
@@ -1104,6 +1109,40 @@ export function SettingsModal(props: SettingsModalProps) {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-3">
|
||||
<Label>Local Label</Label>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
value={localLabelText}
|
||||
onChange={(e) => {
|
||||
const text = e.target.value;
|
||||
setLocalLabelText(text);
|
||||
setLocalLabel(text, localLabelColor);
|
||||
onLocalLabelChange?.({ text, color: localLabelColor });
|
||||
}}
|
||||
placeholder="e.g. Home Base, Field Radio 2"
|
||||
className="flex-1"
|
||||
/>
|
||||
<input
|
||||
type="color"
|
||||
value={localLabelColor}
|
||||
onChange={(e) => {
|
||||
const color = e.target.value;
|
||||
setLocalLabelColor(color);
|
||||
setLocalLabel(localLabelText, color);
|
||||
onLocalLabelChange?.({ text: localLabelText, color });
|
||||
}}
|
||||
className="w-10 h-9 rounded border border-input cursor-pointer bg-transparent p-0.5"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Display a colored banner at the top of the page to identify this instance. This
|
||||
applies only to this device/browser.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{getSectionError('database') && (
|
||||
<div className="text-sm text-destructive">{getSectionError('database')}</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user