Копия данных
Один файл JSON со всем, что у вас накоплено. Делается и восстанавливается в настройках.
Когда это нужно
- Синхронизация не работает — строка «Только это устройство» в настройках. Копия остаётся единственным способом перенести историю на другое устройство.
- Меняется бот. Тот же адрес приложения под новым ботом — это новое пустое хранилище.
- Перед сбросом. Отката у сброса нет.
- Просто на всякий случай. Пока вы не вошли, второй копии нет нигде, кроме этого устройства.
Что внутри
Всё: список приоритетов с архивом, настройки, вся история кликов, весь журнал заряда, каталог навыков с их часами и достижения. Каталог навыков выгружается в обычном читаемом виде, а не в компактной форме, в которой хранится.
Как сделать копию
Кнопка «Скачать копию данных». Дальше — те же три способа, что у обоев, плюс четвёртый:
Если клиент не умеет сохранять файлы, копия уходит в буфер обмена. Долгое нажатие спасает картинку, но не текст, а потерять единственный экземпляр данных нельзя. Приложение прямо предлагает вставить копию сообщением в «Избранное» — оттуда её всегда можно достать.
Как восстановить
Кнопка «Восстановить из копии» и выбор файла. Будет подтверждение: текущие приоритеты и вся история заменяются содержимым файла, а не дополняются им.
После успешного восстановления приложение скажет, сколько приоритетов и дней истории приехало.
Восстановление заменяет, а не сливает
Слияния двух историй нет и не будет: у одного дня два разных числа блоков, и выбрать между ними может только человек, а спрашивать про каждый день — хуже, чем не уметь сливать вовсе.
Что может пойти не так
| Сообщение | Что случилось |
|---|---|
| «Файл не читается: это не JSON» | Выбран не тот файл, или он повреждён |
| «Это копия не от „Моих Приоритетов“» | JSON корректный, но чужой |
| «В копии нет списка приоритетов» | Файл от приложения, но пустой или обрезанный |
| «Не удалось прочитать копию» | Всё остальное |
Совместимость старых копий
Копии, сделанные до появления навыков и достижений, читаются без ошибок: недостающие разделы читаются как пустые.
При восстановлении такой копии каталог навыков и достижения в облаке перезаписываются пустыми, а не остаются от прежнего состояния. Иначе восстановление старой копии оставило бы в приложении навыки, которых в ней нет, — и это выглядело бы как сбой.
Пределы и предупреждения
- Копия — это снимок, а не поток. Всё, отмеченное после её создания, в неё не попадёт.
- Восстановление стирает месяцы, которых в копии нет, и в облаке тоже: иначе они вернулись бы при следующей загрузке.
- Кнопки экспорта, импорта и сброса заблокированы, пока идёт другая операция.
- Экспорт выдаёт достижение «Копия сделана», восстановление — «Восстановление».
Рядом
Настройки · Данные и синхронизация · Сброс
Как это работает внутри
- Формат —
Snapshotвsrc/domain/snapshot.ts:{app: 'my-priorities', version: 2, exportedAt, …}. Версия 1 — копии до навыков. Это формат домена, а не хранилища: смена бэкенда копию не затрагивает вовсе. parseSnapshotбросаетSnapshotError, который несёт ключ строки, а не готовый текст: сообщение видит пользователь, значит переводит его тот, кто рисует, а не слой хранения.- Перед восстановлением гасятся все отложенные записи (
dropPendingWrites), иначе взведённый последним кликом таймер дописал бы месяц обратно поверх восстановленного. - Дальше идёт
clearHistory()и только потомwriteAll(restored).writeAllпишетmp:kиmp:aдаже пустыми — это и есть защита от «остался старый каталог навыков». - Покрыто
src/domain/snapshot.test.ts: круговой рейс, отказ на чужом файле, чтение копии версии 1.