Есть программные ошибки, в которых пользователи винят себя. Нажали не ту клавишу, заметка пропала, и первая мысль не «приложение должно было это предусмотреть», а «надо было быть внимательнее».
Быть внимательнее вы не обязаны. Приложение для заметок нужно ровно для того, чтобы перестать держать всё в голове. Если оно иногда теряет заметку, оно нарушает своё единственное обещание.
В Notez четыре отдельных механизма восстановления. Они не дублируют друг друга: каждый закрывает сбой, который не закрывают остальные, и работает на своём отрезке времени.
Первый уровень: отмена, если ошиблись секунды назад
⌘Z — уровень, которым пользуются не задумываясь. Он отменяет пять конкретных действий:
Удаление — вы переместили заметку в корзину
Перемещение карточки — вы перетащили карточку в другую колонку доски
Изменение свойства — вы задали или очистили значение пользовательского свойства
Быстрое сохранение — вы что-то сохранили и сразу пожалели
Перенос напоминания — вы перетащили напоминание на другой день в календаре
Стек хранит двадцать действий. Каждая запись содержит ровно то, что нужно для отмены: для перемещения карточки — колонку и позицию, откуда она пришла, в том числе если карточка лежала в «Без колонки».
Три детали в поведении отмены сделаны намеренно.
Удаление и сохранение показывают всплывающее уведомление, перемещение карточек — нет. Если показывать уведомление на каждое перетаскивание, с доской станет невозможно работать. Перемещение по-прежнему отменяется, просто молча.
Изменение свойства, которое ничего не изменило, не записывается. Если открыть список и выбрать значение, которое уже стояло, место в стеке не тратится. Иначе пустое событие заняло бы ячейку, а действие, которое вы как раз хотели отменить, незаметно выпало бы из конца стека.
В уведомлении о сохранении две кнопки: «Отменить» и «Открыть». Чаще всего после сохранения хочется не отменить его, а посмотреть, что сохранилось.
Главное ограничение: стек отмены живёт в сессии браузера. Перезагрузите страницу, и он пуст. Это быстрый способ исправить ошибку, которую вы только что сделали, а не постоянная история. Постоянная история — это следующие два уровня.
Второй уровень: история версий за последние 30 дней
У каждой заметки своя история версий, она хранится 30 дней.
Снимок делается при сохранении, но не при каждом — не чаще одного раза в пять минут. Исключение — правка через ИИ-чат или подключённого ассистента: перед ней всегда сохраняется снимок заметки в прежнем виде. Причина в арифметике. Редактор сохраняет текст прямо по ходу набора, и без этого ограничения за полдня работы получились бы сотни почти одинаковых версий, а список из четырёхсот версий историей уже не назовёшь. С шагом в пять минут список можно прочитать.
Снимок хранит не только текст заметки, но и её теги. Это важно при восстановлении: вернув версию прошлого вторника, вы получите и теги прошлого вторника, а не старый текст в заметке, теги которой с тех пор незаметно поменялись.
История версий нужна для того, до чего отмена не дотягивается: не «секунду назад что-то пошло не так», а «за последние две недели заметка стала хуже, и непонятно, когда именно». Вы просматриваете версии и восстанавливаете нужную.
Третий уровень: корзина, где удалённое лежит 30 дней
Удаление заметки её не удаляет. Заметка помечается удалённой, получает отметку времени и 30 дней остаётся в корзине: её можно открыть и восстановить.
Интереснее, что происходит с вложенными заметками.
Удаление заметки удаляет всё её поддерево. Удалите заметку проекта, и вместе с ней уйдут все вложенные в неё заметки. Другое поведение не имеет смысла: дочерняя заметка, оставшаяся без родителя, — это утечка, а не спасение.
Восстановление аккуратнее удаления. Когда вы восстанавливаете заметку, вместе с ней возвращаются и вложенные, но только те, у которых время удаления в точности совпадает с её временем. По этому признаку видно, что они удалены в том же каскаде.
Посмотрим, что сделала бы наивная версия. Допустим, в марте вы удалили одну устаревшую заметку о встрече. В августе удаляете весь проект, потом передумываете и восстанавливаете его. Наивное восстановление вернёт всё поддерево, включая мартовскую заметку, которую вы сознательно выбросили пять месяцев назад. Вам пришлось бы найти её и удалить снова — если бы вы вообще это заметили.
Раз восстановление сверяет время удаления, оно отменяет ровно одно удаление и не трогает ни одного прежнего решения.
Четвёртый уровень: отклонённое сохранение
Первые три уровня исправляют ваши ошибки. Четвёртый нужен потому, что в рабочем пространстве может быть несколько человек, а там сбой выглядит иначе: никто не ошибается, а работа всё равно пропадает.
Два человека открывают одну заметку. Оба правят. Оба сохраняют. Кто сохранил вторым, перезаписывает первого — без ошибки, без предупреждения и без следа того, что другая версия вообще была. Первый автор узнаёт об этом через несколько дней, если узнаёт вообще.
Notez такую запись отклоняет.
У каждой заметки есть счётчик версий содержимого, он растёт с каждым сохранением текста. Сохраняя заметку, редактор отправляет номер версии, с которой вы начали. Если заметка с тех пор изменилась, сохранение не применяется, а отклоняется как конфликт, и вы видите сообщение: заметку изменили в другом месте, перезагрузите её, чтобы продолжить.
Проверка идёт дважды: сначала по прочитанной заметке, потом как условие самого обновления. Это не паранойя «на всякий случай»: между чтением строки и записью есть реальное окно, в которое может попасть чужое сохранение, и закрывает его только проверка в самой записи.
Вы теряете несколько секунд с последнего сохранения. Другой человек не теряет полдня работы.
Это сознательная замена совместному редактированию в реальном времени. Автоматически слить две одновременные правки форматированного текста можно, и именно так появляется абзац, который не писал ни один из авторов. Отклонить вторую запись — решение грубое, зато всегда понятное: один из вас перезагружает заметку, и обе версии на месте.
Как уровни делят работу
Отрезок времени | Механизм | Переживает перезагрузку? |
|---|---|---|
Секунды | Стек отмены | Нет |
От минут до 30 дней | История версий, снимки раз в 5 минут | Да |
До 30 дней | Корзина с восстановлением по каскаду | Да |
Сразу | Защита от конфликта сохранений | Да |
Чего здесь нет, чтобы вы знали границы:
Отмена работает в пределах сессии. Закрыли вкладку — стека больше нет.
История версий и корзина хранят данные 30 дней. Ни то ни другое не резервная копия.
Отмена не касается правок текста заметки: для них есть история версий.
Офлайн-редактирования нет, поэтому нет и офлайн-конфликтов, которые пришлось бы разрешать.
Зачем это нужно
Ни одна из четырёх функций не сложная. Стек отмены, мягкое удаление, таблица снимков и счётчик версий — давно известные инженерные приёмы.
И всё же их пропускают, потому что каждая окупается только в тот день, когда что-то сломалось, а в остальные дни её не видно. Так появляется целый класс приложений для заметок, которые прекрасно выглядят на демо и на четвёртый месяц теряют чьи-то полдня работы.
Записывают, чтобы перестать держать в голове. Это работает, только если можно перестать и беспокоиться о записанном.
Читайте также
Совместная работа без конфликтов слияния — почему общее рабочее пространство отклоняет второе из двух конфликтующих сохранений, а не сливает их.
Фоновая задача, которая чуть не удалила ваш аватар — как ежедневная задача, удаляющая непривязанные файлы, едва не стёрла аватары рабочих пространств, которые были в ходу.
Notez: приложение для заметок, созданное для разработчиков — что такое Notez, какими путями в него попадают заметки и что входит в каждый план.