mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-12 11:43:03 +02:00
Clear out old migration logic and replace with thin shim for favorites; sort order is lost
This commit is contained in:
@@ -14,8 +14,6 @@ import type {
|
||||
MaintenanceResult,
|
||||
Message,
|
||||
MessagesAroundResponse,
|
||||
MigratePreferencesRequest,
|
||||
MigratePreferencesResponse,
|
||||
RawPacket,
|
||||
RadioAdvertMode,
|
||||
RadioConfig,
|
||||
@@ -342,13 +340,6 @@ export const api = {
|
||||
body: JSON.stringify({ type, id }),
|
||||
}),
|
||||
|
||||
// Preferences migration (one-time, from localStorage to database)
|
||||
migratePreferences: (request: MigratePreferencesRequest) =>
|
||||
fetchJson<MigratePreferencesResponse>('/settings/migrate', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(request),
|
||||
}),
|
||||
|
||||
// Fanout
|
||||
getFanoutConfigs: () => fetchJson<FanoutConfig[]>('/fanout'),
|
||||
createFanoutConfig: (config: {
|
||||
|
||||
@@ -2,17 +2,8 @@ import { useState, useCallback, useEffect, useRef } from 'react';
|
||||
import { api } from '../api';
|
||||
import { takePrefetchOrFetch } from '../prefetch';
|
||||
import { toast } from '../components/ui/sonner';
|
||||
import {
|
||||
initLastMessageTimes,
|
||||
loadLocalStorageLastMessageTimes,
|
||||
loadLocalStorageSortOrder,
|
||||
clearLocalStorageConversationState,
|
||||
} from '../utils/conversationState';
|
||||
import {
|
||||
isFavorite,
|
||||
loadLocalStorageFavorites,
|
||||
clearLocalStorageFavorites,
|
||||
} from '../utils/favorites';
|
||||
import { initLastMessageTimes } from '../utils/conversationState';
|
||||
import { isFavorite } from '../utils/favorites';
|
||||
import type { AppSettings, AppSettingsUpdate, Favorite } from '../types';
|
||||
|
||||
export function useAppSettings() {
|
||||
@@ -153,59 +144,35 @@ export function useAppSettings() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
// One-time migration of localStorage preferences to server
|
||||
// Legacy favorites migration: if pre-server-side favorites exist in
|
||||
// localStorage, toggle each one via the existing API and clear the key.
|
||||
useEffect(() => {
|
||||
if (!appSettings || hasMigratedRef.current) return;
|
||||
|
||||
if (appSettings.preferences_migrated) {
|
||||
clearLocalStorageFavorites();
|
||||
clearLocalStorageConversationState();
|
||||
hasMigratedRef.current = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const localFavorites = loadLocalStorageFavorites();
|
||||
const localSortOrder = loadLocalStorageSortOrder();
|
||||
const localLastMessageTimes = loadLocalStorageLastMessageTimes();
|
||||
|
||||
const hasLocalData =
|
||||
localFavorites.length > 0 ||
|
||||
localSortOrder !== 'recent' ||
|
||||
Object.keys(localLastMessageTimes).length > 0;
|
||||
|
||||
if (!hasLocalData) {
|
||||
hasMigratedRef.current = true;
|
||||
return;
|
||||
}
|
||||
|
||||
hasMigratedRef.current = true;
|
||||
|
||||
const migratePreferences = async () => {
|
||||
const FAVORITES_KEY = 'remoteterm-favorites';
|
||||
let localFavorites: Favorite[] = [];
|
||||
try {
|
||||
const stored = localStorage.getItem(FAVORITES_KEY);
|
||||
if (stored) localFavorites = JSON.parse(stored);
|
||||
} catch {
|
||||
// corrupt or unavailable
|
||||
}
|
||||
if (localFavorites.length === 0) return;
|
||||
|
||||
const migrate = async () => {
|
||||
try {
|
||||
const result = await api.migratePreferences({
|
||||
favorites: localFavorites,
|
||||
sort_order: localSortOrder,
|
||||
last_message_times: localLastMessageTimes,
|
||||
});
|
||||
|
||||
if (result.migrated) {
|
||||
toast.success('Preferences migrated', {
|
||||
description: `Migrated ${localFavorites.length} favorites to server`,
|
||||
});
|
||||
for (const f of localFavorites) {
|
||||
await api.toggleFavorite(f.type, f.id);
|
||||
}
|
||||
|
||||
setAppSettings(result.settings);
|
||||
initLastMessageTimes(result.settings.last_message_times ?? {});
|
||||
|
||||
clearLocalStorageFavorites();
|
||||
clearLocalStorageConversationState();
|
||||
localStorage.removeItem(FAVORITES_KEY);
|
||||
await fetchAppSettings();
|
||||
} catch (err) {
|
||||
console.error('Failed to migrate preferences:', err);
|
||||
console.error('Failed to migrate legacy favorites:', err);
|
||||
}
|
||||
};
|
||||
|
||||
migratePreferences();
|
||||
}, [appSettings]);
|
||||
migrate();
|
||||
}, [appSettings, fetchAppSettings]);
|
||||
|
||||
return {
|
||||
appSettings,
|
||||
|
||||
@@ -24,7 +24,6 @@ const mocks = vi.hoisted(() => ({
|
||||
requestTrace: vi.fn(),
|
||||
updateRadioConfig: vi.fn(),
|
||||
setPrivateKey: vi.fn(),
|
||||
migratePreferences: vi.fn(),
|
||||
},
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
@@ -191,7 +190,7 @@ const baseSettings = {
|
||||
favorites: [] as Array<{ type: 'channel' | 'contact'; id: string }>,
|
||||
auto_decrypt_dm_on_advert: false,
|
||||
last_message_times: {},
|
||||
preferences_migrated: false,
|
||||
|
||||
advert_interval: 0,
|
||||
last_advert_time: 0,
|
||||
flood_scope: '',
|
||||
|
||||
@@ -11,7 +11,6 @@ const mocks = vi.hoisted(() => ({
|
||||
getUndecryptedPacketCount: vi.fn(),
|
||||
getChannels: vi.fn(),
|
||||
getContacts: vi.fn(),
|
||||
migratePreferences: vi.fn(),
|
||||
},
|
||||
useConversationMessagesCalls: vi.fn(),
|
||||
}));
|
||||
@@ -219,7 +218,7 @@ describe('App search jump target handling', () => {
|
||||
favorites: [],
|
||||
auto_decrypt_dm_on_advert: false,
|
||||
last_message_times: {},
|
||||
preferences_migrated: true,
|
||||
|
||||
advert_interval: 0,
|
||||
last_advert_time: 0,
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ const mocks = vi.hoisted(() => ({
|
||||
getUndecryptedPacketCount: vi.fn(),
|
||||
getChannels: vi.fn(),
|
||||
getContacts: vi.fn(),
|
||||
migratePreferences: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -170,7 +169,7 @@ describe('App startup hash resolution', () => {
|
||||
favorites: [],
|
||||
auto_decrypt_dm_on_advert: false,
|
||||
last_message_times: {},
|
||||
preferences_migrated: true,
|
||||
|
||||
advert_interval: 0,
|
||||
last_advert_time: 0,
|
||||
});
|
||||
|
||||
@@ -62,7 +62,7 @@ const baseSettings: AppSettings = {
|
||||
favorites: [],
|
||||
auto_decrypt_dm_on_advert: false,
|
||||
last_message_times: {},
|
||||
preferences_migrated: false,
|
||||
|
||||
advert_interval: 0,
|
||||
last_advert_time: 0,
|
||||
flood_scope: '',
|
||||
|
||||
@@ -333,7 +333,6 @@ export interface AppSettings {
|
||||
favorites: Favorite[];
|
||||
auto_decrypt_dm_on_advert: boolean;
|
||||
last_message_times: Record<string, number>;
|
||||
preferences_migrated: boolean;
|
||||
advert_interval: number;
|
||||
last_advert_time: number;
|
||||
flood_scope: string;
|
||||
@@ -360,17 +359,6 @@ export interface TrackedTelemetryResponse {
|
||||
names: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface MigratePreferencesRequest {
|
||||
favorites: Favorite[];
|
||||
sort_order: string;
|
||||
last_message_times: Record<string, number>;
|
||||
}
|
||||
|
||||
export interface MigratePreferencesResponse {
|
||||
migrated: boolean;
|
||||
settings: AppSettings;
|
||||
}
|
||||
|
||||
/** Contact type constants */
|
||||
export const CONTACT_TYPE_REPEATER = 2;
|
||||
export const CONTACT_TYPE_ROOM = 3;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
* across devices - see useUnreadCounts hook.
|
||||
*/
|
||||
|
||||
const LAST_MESSAGE_KEY = 'remoteterm-lastMessageTime';
|
||||
const SORT_ORDER_KEY = 'remoteterm-sortOrder';
|
||||
const SIDEBAR_SECTION_SORT_ORDERS_KEY = 'remoteterm-sidebar-section-sort-orders';
|
||||
|
||||
@@ -72,30 +71,6 @@ export function getStateKey(type: 'channel' | 'contact', id: string): string {
|
||||
return `${type}-${id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load last message times from localStorage (for migration only)
|
||||
*/
|
||||
export function loadLocalStorageLastMessageTimes(): ConversationTimes {
|
||||
try {
|
||||
const stored = localStorage.getItem(LAST_MESSAGE_KEY);
|
||||
return stored ? JSON.parse(stored) : {};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load sort order from localStorage (for migration only)
|
||||
*/
|
||||
export function loadLocalStorageSortOrder(): SortOrder {
|
||||
try {
|
||||
const stored = localStorage.getItem(SORT_ORDER_KEY);
|
||||
return stored === 'alpha' ? 'alpha' : 'recent';
|
||||
} catch {
|
||||
return 'recent';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the legacy single sidebar sort order from localStorage, if present.
|
||||
*/
|
||||
@@ -149,15 +124,3 @@ export function saveLocalStorageSidebarSectionSortOrders(orders: SidebarSectionS
|
||||
// localStorage might be disabled
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear conversation state from localStorage (after migration)
|
||||
*/
|
||||
export function clearLocalStorageConversationState(): void {
|
||||
try {
|
||||
localStorage.removeItem(LAST_MESSAGE_KEY);
|
||||
localStorage.removeItem(SORT_ORDER_KEY);
|
||||
} catch {
|
||||
// localStorage might be disabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
/**
|
||||
* Favorites utilities.
|
||||
*
|
||||
* Favorites are now stored server-side in the database.
|
||||
* This file provides helper functions for checking favorites
|
||||
* and loading legacy localStorage data for migration.
|
||||
* Favorites are stored server-side in the database.
|
||||
*/
|
||||
|
||||
import type { Favorite } from '../types';
|
||||
|
||||
const FAVORITES_KEY = 'remoteterm-favorites';
|
||||
|
||||
/**
|
||||
* Check if a conversation is favorited (from provided favorites array)
|
||||
*/
|
||||
@@ -20,26 +16,3 @@ export function isFavorite(
|
||||
): boolean {
|
||||
return favorites.some((f) => f.type === type && f.id === id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load favorites from localStorage (for migration only)
|
||||
*/
|
||||
export function loadLocalStorageFavorites(): Favorite[] {
|
||||
try {
|
||||
const stored = localStorage.getItem(FAVORITES_KEY);
|
||||
return stored ? JSON.parse(stored) : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear favorites from localStorage (after migration)
|
||||
*/
|
||||
export function clearLocalStorageFavorites(): void {
|
||||
try {
|
||||
localStorage.removeItem(FAVORITES_KEY);
|
||||
} catch {
|
||||
// localStorage might be disabled
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user