Блог Calcup · Конвертеры
Как мы делали шеринг расчётов в Calcup
Заметка о том, зачем калькуляторам понадобились ссылки с состоянием, какие ограничения всплыли в браузере и как мы пришли к общей схеме шеринга
В этой заметке
Коротко
- Потребность появилась из обычного сценария
- Первый неприятный вопрос — что именно класть в ссылку
- Главное ограничение — не доверять ссылке
- UI пришлось делать незаметным
В статье
Потребность появилась из обычного сценария
Калькулятор редко живёт только внутри одной вкладки. Человек подбирает параметры, получает число, а потом хочет отправить результат в чат, вернуться к нему вечером или показать кому-то не пустую форму, а именно свой расчёт.
Обычная ссылка на страницу здесь не помогает: она открывает калькулятор, но теряет введённые значения. Скриншот тоже не решает задачу, потому что по нему нельзя продолжить расчёт. Поэтому шерингу понадобилось не просто «скопировать URL», а аккуратно переносить состояние формы.
Первый неприятный вопрос — что именно класть в ссылку
Самый простой путь — разложить каждое поле по query-параметрам. Для пары чисел это терпимо, но у разных калькуляторов быстро появляются режимы, единицы измерения, списки и значения с разной валидацией. URL начинает разрастаться и становится привязанным к конкретной форме.
Мы выбрали общий payload: версия схемы, идентификатор калькулятора и входные данные. Такой объект кодируется в `state`, а сам калькулятор уже решает, как проверить и применить свой input. Получилась одна общая механика без попытки сделать универсальную модель всех форм.
Главное ограничение — не доверять ссылке
Ссылка может быть старой, битой, вручную изменённой или просто предназначенной для другого калькулятора. Поэтому восстановление состояния работает осторожно: декодируем Base64URL, проверяем версию, сверяем `calculatorId`, ограничиваем размер JSON и только после этого отдаём данные в локальную валидацию.
Это оказалось важнее, чем кажется на старте. Например, старые ссылки должны тихо игнорироваться, а не ломать страницу. А если человек открыл ссылку на конвертер длины, состояние ипотечного калькулятора не должно внезапно попасть в форму только потому, что структура похожа.
UI пришлось делать незаметным
Кнопка шеринга не должна спорить с главным результатом. Она появляется рядом с рассчитанным ответом, использует нативный `navigator.share`, когда браузер умеет делиться ссылкой, и откатывается к копированию в буфер обмена, когда нативного сценария нет.
Отдельной мелочью стали иконки. На iOS, Android и обычном вебе люди ожидают немного разные символы действия, поэтому компонент выбирает вариант по платформе. Это не ключевая логика, но такие детали делают функцию понятнее без лишнего текста в интерфейсе.
Чему научились по дороге
Самое полезное решение — держать общий транспорт отдельно от логики конкретного калькулятора. Общий слой умеет собрать ссылку, сохранить существующие query-параметры, скопировать URL и восстановить payload. А каждый калькулятор сам знает, какие поля для него валидны.
Второй вывод проще: шеринг лучше проектировать как часть расчёта, а не как кнопку в конце. Если заранее понятно, какие входные данные стабильны, как будет выглядеть обратная совместимость и что делать с ошибочной ссылкой, функция получается спокойной и не превращается в отдельный источник странных багов.