mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-06 16:53:38 +02:00
Use better behavior on disconnected radio and allow deeplinking into settings. Closes #66.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { startTransition, useCallback, useState } from 'react';
|
||||
import { startTransition, useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { getLocalLabel, type LocalLabel } from '../utils/localLabel';
|
||||
import type { SettingsSection } from '../components/settings/settingsConstants';
|
||||
import { parseHashSettingsSection, updateSettingsHash } from '../utils/urlHash';
|
||||
|
||||
interface UseAppShellResult {
|
||||
showNewMessage: boolean;
|
||||
@@ -23,25 +24,47 @@ interface UseAppShellResult {
|
||||
}
|
||||
|
||||
export function useAppShell(): UseAppShellResult {
|
||||
const initialSettingsSection = typeof window === 'undefined' ? null : parseHashSettingsSection();
|
||||
const [showNewMessage, setShowNewMessage] = useState(false);
|
||||
const [showSettings, setShowSettings] = useState(false);
|
||||
const [settingsSection, setSettingsSection] = useState<SettingsSection>('radio');
|
||||
const [showSettings, setShowSettings] = useState(() => initialSettingsSection !== null);
|
||||
const [settingsSection, setSettingsSection] = useState<SettingsSection>(
|
||||
() => initialSettingsSection ?? 'radio'
|
||||
);
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const [showCracker, setShowCracker] = useState(false);
|
||||
const [crackerRunning, setCrackerRunning] = useState(false);
|
||||
const [localLabel, setLocalLabel] = useState(getLocalLabel);
|
||||
const previousHashRef = useRef('');
|
||||
|
||||
useEffect(() => {
|
||||
if (showSettings) {
|
||||
updateSettingsHash(settingsSection);
|
||||
}
|
||||
}, [settingsSection, showSettings]);
|
||||
|
||||
const handleCloseSettingsView = useCallback(() => {
|
||||
if (typeof window !== 'undefined' && parseHashSettingsSection() !== null) {
|
||||
window.history.replaceState(null, '', previousHashRef.current || window.location.pathname);
|
||||
}
|
||||
startTransition(() => setShowSettings(false));
|
||||
setSidebarOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleToggleSettingsView = useCallback(() => {
|
||||
if (showSettings) {
|
||||
handleCloseSettingsView();
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
previousHashRef.current =
|
||||
parseHashSettingsSection() === null ? window.location.hash : previousHashRef.current;
|
||||
}
|
||||
startTransition(() => {
|
||||
setShowSettings((prev) => !prev);
|
||||
setShowSettings(true);
|
||||
});
|
||||
setSidebarOpen(false);
|
||||
}, []);
|
||||
}, [handleCloseSettingsView, showSettings]);
|
||||
|
||||
const handleOpenNewMessage = useCallback(() => {
|
||||
setShowNewMessage(true);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useCallback, useEffect, useRef, type MutableRefObject } from 'react';
|
||||
import {
|
||||
parseHashConversation,
|
||||
parseHashSettingsSection,
|
||||
updateUrlHash,
|
||||
resolveChannelFromHashToken,
|
||||
resolveContactFromHashToken,
|
||||
@@ -18,6 +19,7 @@ interface UseConversationRouterArgs {
|
||||
channels: Channel[];
|
||||
contacts: Contact[];
|
||||
contactsLoaded: boolean;
|
||||
suspendHashSync: boolean;
|
||||
setSidebarOpen: (open: boolean) => void;
|
||||
pendingDeleteFallbackRef: MutableRefObject<boolean>;
|
||||
hasSetDefaultConversation: MutableRefObject<boolean>;
|
||||
@@ -27,6 +29,7 @@ export function useConversationRouter({
|
||||
channels,
|
||||
contacts,
|
||||
contactsLoaded,
|
||||
suspendHashSync,
|
||||
setSidebarOpen,
|
||||
pendingDeleteFallbackRef,
|
||||
hasSetDefaultConversation,
|
||||
@@ -34,7 +37,9 @@ export function useConversationRouter({
|
||||
const [activeConversation, setActiveConversationState] = useState<Conversation | null>(null);
|
||||
const activeConversationRef = useRef<Conversation | null>(null);
|
||||
const hashSyncEnabledRef = useRef(
|
||||
typeof window !== 'undefined' ? window.location.hash.length > 0 : false
|
||||
typeof window !== 'undefined'
|
||||
? window.location.hash.length > 0 && parseHashSettingsSection() === null
|
||||
: false
|
||||
);
|
||||
|
||||
const setActiveConversation = useCallback((conv: Conversation | null) => {
|
||||
@@ -58,7 +63,7 @@ export function useConversationRouter({
|
||||
if (hasSetDefaultConversation.current || activeConversation) return;
|
||||
if (channels.length === 0) return;
|
||||
|
||||
const hashConv = parseHashConversation();
|
||||
const hashConv = parseHashSettingsSection() ? null : parseHashConversation();
|
||||
|
||||
// Handle non-data views immediately
|
||||
if (hashConv?.type === 'raw') {
|
||||
@@ -141,7 +146,7 @@ export function useConversationRouter({
|
||||
useEffect(() => {
|
||||
if (hasSetDefaultConversation.current || activeConversation) return;
|
||||
|
||||
const hashConv = parseHashConversation();
|
||||
const hashConv = parseHashSettingsSection() ? null : parseHashConversation();
|
||||
if (hashConv?.type === 'contact') {
|
||||
if (!contactsLoaded) return;
|
||||
|
||||
@@ -203,14 +208,14 @@ export function useConversationRouter({
|
||||
useEffect(() => {
|
||||
activeConversationRef.current = activeConversation;
|
||||
if (activeConversation) {
|
||||
if (hashSyncEnabledRef.current) {
|
||||
if (hashSyncEnabledRef.current && !suspendHashSync) {
|
||||
updateUrlHash(activeConversation);
|
||||
}
|
||||
if (getReopenLastConversationEnabled() && activeConversation.type !== 'search') {
|
||||
saveLastViewedConversation(activeConversation);
|
||||
}
|
||||
}
|
||||
}, [activeConversation]);
|
||||
}, [activeConversation, suspendHashSync]);
|
||||
|
||||
// If a delete action left us without an active conversation, recover to Public
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user