mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-06-27 05:21:27 +02:00
Move to server side preference and read indicator management
This commit is contained in:
@@ -96,6 +96,7 @@ export function SettingsModal({
|
||||
// Database maintenance state
|
||||
const [retentionDays, setRetentionDays] = useState('14');
|
||||
const [cleaning, setCleaning] = useState(false);
|
||||
const [autoDecryptOnAdvert, setAutoDecryptOnAdvert] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (config) {
|
||||
@@ -113,6 +114,7 @@ export function SettingsModal({
|
||||
useEffect(() => {
|
||||
if (appSettings) {
|
||||
setMaxRadioContacts(String(appSettings.max_radio_contacts));
|
||||
setAutoDecryptOnAdvert(appSettings.auto_decrypt_dm_on_advert);
|
||||
}
|
||||
}, [appSettings]);
|
||||
|
||||
@@ -314,6 +316,19 @@ export function SettingsModal({
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleAutoDecrypt = async () => {
|
||||
const newValue = !autoDecryptOnAdvert;
|
||||
setAutoDecryptOnAdvert(newValue); // Optimistic update
|
||||
|
||||
try {
|
||||
await onSaveAppSettings({ auto_decrypt_dm_on_advert: newValue });
|
||||
} catch (err) {
|
||||
console.error('Failed to save auto-decrypt setting:', err);
|
||||
setAutoDecryptOnAdvert(!newValue); // Revert on error
|
||||
toast.error('Failed to save setting');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
|
||||
<DialogContent className="sm:max-w-[500px] max-h-[90vh] overflow-y-auto">
|
||||
@@ -638,6 +653,31 @@ export function SettingsModal({
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-3">
|
||||
<Label>DM Decryption</Label>
|
||||
<div
|
||||
className="flex items-center gap-3 cursor-pointer"
|
||||
onClick={handleToggleAutoDecrypt}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={autoDecryptOnAdvert}
|
||||
readOnly
|
||||
className="w-4 h-4 rounded border-input accent-primary pointer-events-none"
|
||||
/>
|
||||
<span className="text-sm">
|
||||
Auto-decrypt historical DMs when new contact advertises
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
When enabled, the server will automatically try to decrypt stored DM packets when
|
||||
a new contact sends an advertisement. This may cause brief delays on large packet
|
||||
backlogs.
|
||||
</p>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
{/* Advertise Tab */}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useState } from 'react';
|
||||
import type { Contact, Channel, Conversation } from '../types';
|
||||
import type { Contact, Channel, Conversation, Favorite } from '../types';
|
||||
import { getStateKey, type ConversationTimes } from '../utils/conversationState';
|
||||
import { getPubkeyPrefix, getContactDisplayName } from '../utils/pubkey';
|
||||
import { ContactAvatar } from './ContactAvatar';
|
||||
import { CONTACT_TYPE_REPEATER } from '../utils/contactAvatar';
|
||||
import { isFavorite, type Favorite } from '../utils/favorites';
|
||||
import { isFavorite } from '../utils/favorites';
|
||||
import { UNREAD_FETCH_LIMIT } from '../api';
|
||||
import { Input } from './ui/input';
|
||||
import { Button } from './ui/button';
|
||||
@@ -27,6 +27,10 @@ interface SidebarProps {
|
||||
onToggleCracker: () => void;
|
||||
onMarkAllRead: () => void;
|
||||
favorites: Favorite[];
|
||||
/** Sort order from server settings */
|
||||
sortOrder?: SortOrder;
|
||||
/** Callback when sort order changes */
|
||||
onSortOrderChange?: (order: SortOrder) => void;
|
||||
}
|
||||
|
||||
/** Format unread count, showing "X+" if at the fetch limit (indicating there may be more) */
|
||||
@@ -34,25 +38,6 @@ function formatUnreadCount(count: number): string {
|
||||
return count >= UNREAD_FETCH_LIMIT ? `${count}+` : `${count}`;
|
||||
}
|
||||
|
||||
// Load sort preference from localStorage (default to 'recent')
|
||||
function loadSortOrder(): SortOrder {
|
||||
try {
|
||||
const stored = localStorage.getItem('remoteterm-sortOrder');
|
||||
return stored === 'alpha' ? 'alpha' : 'recent';
|
||||
} catch {
|
||||
return 'recent';
|
||||
}
|
||||
}
|
||||
|
||||
// Save sort preference to localStorage
|
||||
function saveSortOrder(order: SortOrder): void {
|
||||
try {
|
||||
localStorage.setItem('remoteterm-sortOrder', order);
|
||||
} catch {
|
||||
// localStorage might be full or disabled
|
||||
}
|
||||
}
|
||||
|
||||
export function Sidebar({
|
||||
contacts,
|
||||
channels,
|
||||
@@ -67,14 +52,15 @@ export function Sidebar({
|
||||
onToggleCracker,
|
||||
onMarkAllRead,
|
||||
favorites,
|
||||
sortOrder: sortOrderProp = 'recent',
|
||||
onSortOrderChange,
|
||||
}: SidebarProps) {
|
||||
const [sortOrder, setSortOrder] = useState<SortOrder>(loadSortOrder);
|
||||
const sortOrder = sortOrderProp;
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const handleSortToggle = () => {
|
||||
const newOrder = sortOrder === 'alpha' ? 'recent' : 'alpha';
|
||||
setSortOrder(newOrder);
|
||||
saveSortOrder(newOrder);
|
||||
onSortOrderChange?.(newOrder);
|
||||
};
|
||||
|
||||
const handleSelectConversation = (conversation: Conversation) => {
|
||||
|
||||
Reference in New Issue
Block a user