Казалось бы, сколько их уже есть, зачем еще один? Но случилось совпадение многих вещей - у меня было свободное время, желание что-то сделать, неудовлетворенность работой официального клиента и нежелание изучать существующие альтернативные версии и перечень их отличий. В результате я реализовал свой Луна-парк, с нужными мне фичами. Подробнее под катом.


Минутка философии

Я прекрасно понимаю, что нельзя угодить всем. И, разрабатывая массовый программный продукт, можно все время добавлять и усложнять настройки, определяющие его работу. Но это экстенсивный путь, по большому счету. Кому-то подавай темную тему, кому-то выбор звуков оповещений, кому-то кастомные эмодзи и анимации... И я подозреваю, что подобные решения принимаются не просто так от настроения менеджера как он встал с утра, а набирается фокус-группа репрезентативных пользователей продукта, выясняются их приоритеты, потом анализируются временнЫе и финансовые затраты на реализацию и т.п. И в результате продукт обрастает новыми фичами и настройками, постепенно превращаясь в неповоротливиго трудноподдерживаемого монстра.

Мне никогда не было нужно 90% свистелок и фичей Телеграм. Более того, наличие и невозможность отключить некоторые из них мне откровенно не нравится. Но меня никто не спрашивал, я не член фокус группы. С другой стороны, меня не устраивает работа приложения в определенных моментах, но опять же, никто не спешит реализовывать мои хотелки. И тут самое время вспомнить слова великого селекционера Ивана Мичурина: "Если гора не идет к Магомету..." нет, вроде у него было по-другому, но суть та же: "Мы не можем ждать милостей от природы. Взять их у нее – наша задача." И такое решение принимают многие пользователи, насколько я могу судить по обилию кастомных клиентов этого апи. Вот и я решил пополнить их ряды.

Ближе к делу

Одна из моих претензий к Телеграм в том, что мы по-разному понимаем термин "заблокированный пользователь". Мне хочется, чтобы если я заблокировал пользователя, то мне не приходили уведомления о его действиях (я знаю, что есть отдельная галочка "Отключить уведомления"), чтобы не появлялись картинки с новыми упоминаниями и реакциями от него, чтобы не появлялись новые истории (!) от него (я знаю, что можно удалить из ��писка контактов или скрыть истории персонально), чтобы были не видны сообщения от него во всех чатах и группах (с возможностью просмотра при желании), чтобы.... Короче, чтобы эмулировалось его полное и абсолютное отсутствие в природе.

Телеграм даже идет мне навстречу в части моих пожеланий - например, если заблокированный пользователь упомянет меня в группе или чате, то клиент не покажет, что появилось новое упоминание. Подозреваю, потому что сервер (!) не пошлет флаг MentionMe в наборе флагов этого сообщения. Думаете, у заблокированного пользователя теперь нет возможности упомянуть меня? Оказывается, есть - если он будет цитировать или отвечать на мои сообщения, упоминания прекрасно будут показываться клиентом. Я думаю, что это баг на стороне сервера, но кто я такой, чтобы давать такие оценки :) Участников фокус-группы, видимо, такая логика работы приложения устраивает, или они считают это не настолько важным, как анимация реакций, к примеру. Тут уже вспоминаются слова великого поэта Владимира Маяковского (в переложении Де Моргана): "Если на небе не зажигаются звезды, значит это никому не нужно!"

Технические детали и возникшие трудности

В общем, решил я допилить существующий клиент под мои хотелки. Начал с десктопного, мобильный в планах. Благо продукт опенсорсный, лицензия позволяет, апи открытое и документация доступна. И столкнулся с некоторыми сложностями - существующее апи не предусматривает мои пожелания. Это было предсказуемо, но не пугало - я решил, что сделаю максимум из того, что смогу в рамках этих непреодолимых ограничений. Например, при старте приложения (а также при других событиях, но это не важно) идет запрос к апи за некоторым саммари по группам и каналам пользователя, для демонстрации наличия/отсутствия упоминаний в канале, новых реакций, количества новых сообщений и т.п. Разумеется, сервер не хочет думать, какие упоминания были от заблокированных пользователей, а какие нет. То же касается и сообщений с реакциями. В результате, я вынужден в фоне запрашивать детализацию по всем непрочитанным упоминаниям и реакциям, анализировать из авторов, и все только ради того, чтобы принять бинарное решение - показать или нет пиктограммку с наличием упоминаний в группе. С реакциями ситуация еще сложнее - помимо списка собственно сообщений с непрочитанными реакциями, я запрашиваю еще детализацию всех непрочитанных реакций каждого сообщения в разрезе реакторов (кто реагировал) с целью принятия решения - есть ли непрочитанные реакции к данному сообщению от незаблокированных пользователей или нет. Благо, соответствующие методы присутствуют в апи, и это радует. Но если бы сервер был последователен, и не считал упоминаниями от заблокированных пользователей не только написание моего ника в тексте, а еще и ответы и цитаты моих сообщений, жить было бы немного проще )

В онлайн режиме возникают подобные описанным выше проблемы - например, при событии от сервера "появились новые реакции" точно так же нужно детально запрашивать и проверять их авторов. И в определенных случаях отправлять на сервер уведомления о том, что контент сообщения прочитан, иначе сервер будет наивно полагать, что нам надо все время напоминать о том, что у нас есть важные непрочитанные сообщения, и заботливо это делать при каждом удобном случае.

Также были и чисто клиентские моменты: например, группировка "пузырей" отдельных сообщений от одного пользователя в пачки, где аватар и вытянутый к нему носик пузыря показываются только у самого нижнего сообщения в пачке, а большие радиусы закруглений у самого верхнего, создавая иллюзию одного общего мульти-пузыря всей пачки. Или, например, жесткая ориентация на строго определенную высоту превью сообщений в списке результатов поиска - вплоть до того, что метод Repaint определяет область своей перерисовки исключительно по номеру сообщения в списке, рассчитывая смещение как номер (количество элементов выше него) умноженный на жестко заданную высоту каждого виджета, что не облегчает задачу пропуска и скрытия из результатов поиска сообщений от заблокированных пользователей. Но тут хоть проблема не в апи, а значит в принципе решаемая.

Но я считаю, что в большой мере мне удалось реализовать мои идеи и пожелания, даже в рамках подобных ограничений. В некоторых моментах пришлось пойти на компромиссы, но работа не закончена, может еще реализую получше.

Отдельный вопрос был со сборкой релизного бинарника. Я на Убунте, и как ни странно, это добавило проблем и неочевидных моментов при сборке. Продакшен билды официальных релизов разумеется никто собирать у себя на коленке не разрешит, а скрипты и сценарии катомных билдов в проекте обновляются и актуализируются далеко не каждый раз, ибо разработчиками самого Телеграма очевидно не используются. В довершение это��о, инструкция по сборке даже кастомного релизного бинарника просто отсутствует в документации официального клиента, есть только версия для дебага. В результате пришлось спрашивать некоторые моменты у гуру, которые, к их чести, помогли.

Счастливый (надеюсь, не) конец

В итоге, я в данный момент имею рабочую альфа версию пре-релиза моего кастомного клиента, который я назвал Kilogram. Примеров кода в статье не было, но они в изобилии представлениы в репозитории проекта на гитхабе: https://github.com/Ivana-/kilogram-desktop

Там кратко перечислены изменения в интерфейсе и фичи, реализованные на текущий момент.

Кому просто покритиковать код, репозитория достаточно.
Кому сбилдить свою версию - в ридми написано как.
Кому скачать и попробовать - там же на закладке Релизы готовый бинарник под Убунту. Вирусов и троянов не добавлял, никакие либы в проект не тащил, стучать майору и колонелу будет не больше чем официальный Телеграм клиент. Но если у вас взорвется компьютер или за вами придут, то я ни при чем )