diff --git a/src/api/offlineNotesApi.ts b/src/api/offlineNotesApi.ts index 4858784..125d121 100644 --- a/src/api/offlineNotesApi.ts +++ b/src/api/offlineNotesApi.ts @@ -239,10 +239,62 @@ export const offlineNotesApi = { store.dispatch(addNote(noteWithSyncStatus)); return noteWithSyncStatus; - } catch (error) { - console.error("Error creating note, falling back to local:", error); - // Fallback на локальное создание - return offlineNotesApi.create(note); + } catch (error: any) { + // Проверяем, является ли это сетевой ошибкой + const isNetworkError = + !error.response && + (error.code === 'ERR_NETWORK' || + error.message === 'Network Error' || + error.message?.includes('ERR_INTERNET_DISCONNECTED') || + error.message?.includes('Failed to fetch')); + + if (isNetworkError) { + console.error("Network error creating note, falling back to local:", error); + + // Принудительно обновляем статус сети при ошибке + lastNetworkCheck = { time: Date.now(), status: false }; + store.dispatch(setOfflineMode(true)); + + // Fallback на локальное создание напрямую, без рекурсии + console.log("[Offline] Creating note locally after network error"); + + const tempId = generateTempId(); + const now = new Date().toISOString(); + const newNote: Note = { + ...note, + id: tempId, + user_id: userId || 0, + created_at: now, + updated_at: now, + is_pinned: 0, + is_archived: 0, + images: [], + files: [], + syncStatus: "pending", + }; + + // Сохраняем в IndexedDB + await dbManager.saveNote(newNote); + + // Добавляем в очередь синхронизации + await dbManager.addToSyncQueue({ + type: "create", + noteId: tempId, + data: note, + timestamp: Date.now(), + retries: 0, + }); + + // Обновляем UI + store.dispatch(addNote(newNote)); + await updatePendingSyncCount(); + + return newNote; + } else { + // Если это не сетевая ошибка, пробрасываем её дальше + console.error("Error creating note (not a network error):", error); + throw error; + } } }, diff --git a/src/main.tsx b/src/main.tsx index bce2974..aa6a96b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -24,7 +24,29 @@ async function initOfflineMode() { console.log('[Init] IndexedDB initialized'); // Проверка состояния сети - const isOnline = await checkNetworkStatus(); + // Сначала проверяем navigator.onLine для быстрой проверки + let isOnline: boolean = navigator.onLine; + + // Если navigator.onLine = false, точно оффлайн (не нужно делать fetch) + if (!navigator.onLine) { + isOnline = false; + } else { + // Если navigator.onLine = true, делаем дополнительную проверку через fetch + try { + isOnline = await checkNetworkStatus(); + } catch (error) { + // Если проверка сети упала с ошибкой, скорее всего мы оффлайн + console.warn('[Init] Network status check failed, assuming offline:', error); + isOnline = false; + } + } + + // Финальная проверка: если navigator.onLine = false, точно оффлайн + // Это важно, так как navigator.onLine может обновиться во время проверки + if (!navigator.onLine) { + isOnline = false; + } + store.dispatch(setOfflineMode(!isOnline)); console.log(`[Init] Network status: ${isOnline ? 'online' : 'offline'}`); diff --git a/src/utils/offlineManager.ts b/src/utils/offlineManager.ts index 5bfb948..066741f 100644 --- a/src/utils/offlineManager.ts +++ b/src/utils/offlineManager.ts @@ -47,6 +47,7 @@ export async function checkNetworkStatus(): Promise { } // Дополнительная проверка через fetch с коротким таймаутом + // Используем короткий таймаут для быстрого определения оффлайна try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 2000); @@ -61,9 +62,36 @@ export async function checkNetworkStatus(): Promise { clearTimeout(timeoutId); return response.ok; - } catch (error) { - // Если запрос не удался, но navigator.onLine = true, считаем что онлайн - // (возможно, просто таймаут или другая проблема) + } catch (error: any) { + // Если запрос не удался, проверяем тип ошибки + const isAbortError = error.name === 'AbortError'; // Таймаут + const isNetworkError = + error.message === 'Failed to fetch' || + error.message?.includes('NetworkError') || + error.message?.includes('ERR_INTERNET_DISCONNECTED') || + error.message?.includes('ERR_NETWORK') || + error.message?.includes('network request failed'); + + // Если это явная сетевая ошибка (не таймаут), точно оффлайн + if (isNetworkError && !isAbortError) { + return false; + } + + // Если это таймаут, проверяем navigator.onLine + // Таймаут может быть как из-за оффлайна, так и из-за медленного соединения + if (isAbortError) { + // Если navigator.onLine = false, точно оффлайн + if (!navigator.onLine) { + return false; + } + // Если navigator.onLine = true, но таймаут - возможно медленное соединение + // Но для безопасности считаем оффлайном, так как запрос не прошел + return false; + } + + // Если это не сетевая ошибка и не таймаут (например, CORS или другая проблема), + // но navigator.onLine = true, считаем что онлайн + // (возможно, просто другая проблема, но сеть есть) return navigator.onLine; } }