Codestyle
=========

Version: 0.3.X,0.4.X,0.5.X

* Something that acts on chat buffer or any function that uses any
  chat buffer local variables should be named with `telega-chatbuf-`
  prefix
  - TODO: what about chat buffer commands?

* Functions that implements any (semi)direct call to tdlib function
  should be named as `telega--<tdlibName>`, for example if you see
  "sendMessageAlbum" definition in `td_api.tl' file, then
  `telega--sendMessageAlbum` is the perfect name for the function

* General callback functions should be named as
  `telega--on-<tdlibName>`, unless you use this callback as argument
  to `telega-server--call`

* Do NOT create hook with default value, because its value will be
  shadowed if telega is not yet loaded and user added some hook.
  Add hooks you want in load time, i.e. after (provide 'telega-FEATURE)

Version: 0.6.X

* Put API related functions to telega-tdlib.el

Идеи
====

Вынуть заимплемченые методы:

   $ grep -h -r "on-update" *.el |grep defun | cut -c 19- | cut -d' ' -f 1 | sort -n
   $ egrep "^update" ~/dev/td/td/generate/scheme/td_api.tl | cut -d' ' -f 1 | sort -n

* Для location сообщений загружать асинхронно (с помощью
  `url-retrieve') картинки с яндекс maps static api -
  https://tech.yandex.ru/maps/doc/staticapi/1.x/dg/concepts/input_params-docpage/

  Для лайвух во времени (edited) писать сколько назад по времени. Типа
  - right now
  - 2 minutes ago
  - 3 hours ago

  Или использовать гугловые карты - https://developers.google.com/maps/documentation/maps-static/dev-guide
  в них можно использовать кастомные метки, например с аватарками

* [DONE] Зарефакторить button based вариант рендеринга буферов
  с использованием библиотеки ewoc.  В ewoc есть куча нужного Также,
  можно вместо форматеров использовать инсёртеры, тогда можно будет
  писать инсёртеры, которые знают о контексте предыдущих инсёртеров.
  Например, чтобы вставить дату, нужно лишь посмотреть на текущую
  колонку и вставить нужное число паддинга

* [TODO] Режим, в котором подсвечивается сообщение в котором курсор,
  аля show-paren-style=='expression

* [DONE] При редактировании/ответе на сообщение показывать help строку
  в echo area, в которой подсказать какой кнопкой отменить
  редактирование/ответ

* Посмотреть как можно включить flyspell в chat буферах
  Возможно заработает просто добавлением flyspell-mode в
  telega-chat-mode-hook

* Вести в 'Saved Messages' документ, в котором хранятся список
"<buffer-name> . <telegram-id>" таким образом можно будет хранить
файлы в телеграме.  Но нужно проверить можно ли пересохранять файлы с
тем же id.

* Иконки - all-the-icons package [NO PLEASE], используем unicode

* ! Аватарки можно разбивать на части, чтобы можно было отображать в
мультилайне. [DONE]

* Анимированые гифки через таймер, см.

* [WON'T DO] Показывать как изменялся Status, типа:
    Status:  Conn Ready <-- Connecting <-- Auth Checking...
  Использовать elide для обрезки

* Сделать опционально, чтобы при смене orderа чата в рут буфере и если
  курсор на этом чате, то курсор сохранял позицию на этом чате
  [DONE] см. telega-root-keep-cursor

Stickers
--------

$ sudo apt-get install webp  - чтобы была поддержка в imagemagick

File downloading/uploading
--------------------------

* Для загрузки/аплоада данных в cloud оформить подсистему со своими
  колбеками и тд

Async loading
~~~~~~~~~~~~~

- Если делается какой-до долгий запрос то можно вывести сначала
Loading.. (можно анимировать даже точки) и когда запрос завершён, то
удалить Loading и вызвать callback.  [DONE] для поиска по публичным
группам и сообщениям

Так, например, можно подгружать длинные списки members для супергрупп.
Или chats in common для юзера

============= Root buffer =============

Можно засетапить header/mode-line чтобы показывать состояние
telega-server, и самарайз то что происходит

Widget based buffer

State:  Connecting..
Search: [here is something to search]

Recent Chats
------------

[Saved Messages                  4]p
    14:15V some photo here
[Pig's Thursday               32@2]p
    17:15W @zevlg> last message in chatroom
|Vasya Pupkin                    1|
    11:11V hello there
#FBI leaks                    11@1#
    10.04.18V just wipe the file and forget
[Telegram Resistance             1]
    14:14V @vpupkin> Can you see it?
(Seliger                       4@1)
    MonW @vpupkin> I will not go

Количество сообщений (справа от title) - ВСЕГО[@MENTIONS]

|name    | - private chat with user
(name ...) - basic groups
[name ...] - super groups
#name    # - secret chat
<name ...> - channels
{name ...} - bots

[DONE] Символ о статусе доставки сообщения возле времени
O - В процессе доставки на сервер
V - Одна галка
W - Двойная галка

[DONE partly] Символы после title чата
p - pinned  -- Unicode Character 'PUSHPIN' (U+1F4CC) UTF-8 (hex): 0xF0 0x9F 0x93 0x8C (f09f938c)
m - muted
* - online
o - away
v - verified (+4277 for example)

[DONE] Дата:
- Если сегодня, то формат ЧАС:МИНУТА
- Eсли на этой неделе то трёхбуквенный ДЕНЬ НЕДЕЛИ
- Если другое то ДЕНЬ.МЕСЯЦ.ГОД (год двухбуквенный)

Bots
----

Same as in chats, but only bots

Users
-----

PIC Vasya Pupkin @vpupkin     2    last seen recently
   14:15V some photo here
PIC Evgeny Zajcev @zevlg           last seen long ago
   FriW message from me

Channels
--------

Same as in chats, but only channels

Tabbed design
=============

Pinned
------

[Saved Messages                  4]p
    14:15V some photo here
...

[Chats 10] [Secrets N] [Groups 10] [Bots 3] [Users 4] [Channels 4]
----------'           `-------------------------------------------

[Pig's Thursday               32@2]
    17:15W @zevlg> last message in chatroom
....

Жирным выделять активную вкладку

Filter based design ala ibuffer
===============================

Просто список чатов и накладывать на него всевозможные фильтры

Возможность создавать кастомные фильтры

Фильтр - предикат, который на вход получает чат и возвращает non-nil
если чат нужно включить в список

State: Conn Ready
Search: [search String]
Filter: (custom Groups&Users) (unread)
Custom: [All 10] [Groups&Users 10] [Secrets N]
        [Groups 10] [Bots 3] [Users 4] [Channels 4]

Тут список чатов,

Filters:
  (type CHAT-TYPE) - by telega-chat--type
  (custom FILTER-NAME) - by custom filter type
  title      - по title чата
  unread     - чаты с непрочитаными сообщениями
  mention    - чаты с упоминанием
  pin        - pinned chats


Вариант как может ещё выглядеть:   (самый нормальный и мощный)

    Status: Auth Closed

    [276  All          1940@1] [191  Groups&Users    568@1]
    [80   Groups        568@1] [27   Bots                 ]
    [58   Channels       1372]

    -------------------------((custom "Groups"))-------------------------

    [Saved Messages                  4]p
        14:15V some photo here
    [Pig's Thursday               32@2]p
        17:15W @zevlg> last message in chatroom
    ....
    ....

Кнопки фиксированой ширины, поэтому нет проблем с point если
обновляется контент кнопки.

В разрыве показывается активный фильтр.
При нажатии на кнопку, кастомный фильтр добавляется к текущему.
Однако, если нажимается с prefix-arg, то фильтр резетится, до того,
который указан на кнопке

Показывать только те кнопки с фильтрами, где есть хотя бы один чат.
Либо показывать всё, но где 0 чатов делать inactive

Поиск сделать как один из фильтров [НЕТ, поиск сделал по-другому]

Сделать общий форматтер аля как в ibuffer чтобы можно было
форматировать тайтлы для кастомных фильтров и чат-баттоны.  Может
можно будет этот форматтер использовать и в буферах чатов

Форматирование
==============

Формат - пара где car это функция, которая принимает объект и
возвращает alist локальных переменных для исполнения в body. Таким
образом в body могут быть всякие if, when, etc

Результат исполнения body - список объектов либо строк либо вида

Формат без локальных переменных - :format     (aka simple)
Формат с локальными переменными - :format-ext (aka extended)

(ELEM :min :max :elide :elide-trail :elide-string :align
      :fill :fill-prefix t :fill-column <NUM>
      :align-symbol :face)

Где ELEM может быть одним из:
  string - Используем как есть
  symbol - Ищем в дефинициях формата сответствующую функцию и вызываем
           её для получения строки
  list   - Форматируем его для получения строки

Аттрибуты
~~~~~~~~~
  :min           - минимальный размер
  :max           - максимальный размер
  :elide         - non-nil чтобы eliding вставлять
  :elide-string  - Строка для элидинга
  :elide-trail   - Сколько символов вконце оставлять (default=0), будет
                   выглядеть вот так: "Verylongstri...ail" если
                   :elide-trail = 3
  :align         - куда алигнить `left', `right', `center'
  :align-symbol  - каким символом паддить после алигна (SPACE по умолчанию)
  :face          - face которую использовать для этого ELEM
  :fill          - Как делать fill для строки
  :fill-prefix   - Вставлять префикс из пробелов

Сделать компилятор для форматов: компилятор принимает на вход функцию
для создания локальных переменных, формат и дефиниции для форматных
символов, а на выходы выдаёт функцию форматирования от одного аргумент
- объекта, который используется для форматирования

Searching in telega root
========================

Когда ищут, то можно просто спрятать всё что от root--chats-mark и
показать поиск, потом удалить всё до root--chats-marks и показать
снова чаты

State: Conn Ready
Search: [text to search               ]

Global
------

User1
User2
Channel1

Chats and Users
---------------
listing ...
listing ..

Messages
--------

User1 msg
User2 msg2

^^^^^Плохо

Или лучше, ввести понятие типа фильтрования и если сейчас отображены
чаты то удалять всё из root ewoc, менять его pretty-printer и добалять
другие элементы

типа
----(chats ...)----
Обычный дисплей чатов

----(global "keyword")----
)chat1      (  ;; Такие скобки если не member   <-- хуйня
)chat2      (
--------------------------------- (divider)
обычные чаты
[normal-chat1]
[narmal-chat2]
...


или:
----(messages "keyword")----
[chat1] msg1
[chat2] msg2
..
----(shared 'type (type photo))----
Thumbnail1 Thumbnail2
[Load More]  button to load more

----(calls missed)----
missed call1
missed call2

=============
 Chat buffer
=============

TODO: подумать чо как тут должно выглядить

- use lui based mode.  Лучше всё таки свой режим сделать, чтобы не
  ограничиваться и не зависить от lui, будет больше контроля хоть и
  придётся переимплементить функционал из lui

17:15W @vpupkin> message from v pupkin
17:19V @zevlg> message from me, highlighted with different background color
------------------------[text here for page cut]------------------------

- Поддержка мультилайна по Ctrl-Enter, C-j  [сделано по умолчанию]

- Вставлять разделитель даты, в случае если новое сообщение в новом
  дне, например:

    17:15W @vpupkin> message from v pupkin
    ---------------------(May 4)---------------------
    00:01W @zevlg> new message here

  см. circe-new-day-notifier.el
  см. telega-chat-insert-date-breaks

- Polls: [DONE]

    📊 Poll Title (10 votes)
    [x] NO   ############## (70% 5 votes)
    [ ] YES  #####          (20% 2 votes)

Prompts
~~~~~~~

Normal:
    __________________________
    >>> []

Edit:
    __________________________
    | Edit: message text...
    `-> []

Reply:
    __________________________
    | Reply: @vpupkin> message lala ...
    `-> []

If not a member of chat:
    __________________________
    [ JOIN ]

Formatting messages:

[AH] @user (admin)
[AL] message here long message
     continue message message              12:20w


Channel message with signature:

👁10 --Mike Hoorn
message here long message
continue message message                   12:20w

with reply markup
~~~~~~~~~~~~~~~~~

[AH] @vpupkin
[AL] | Reply: @user> msagsac
     messgasaoenth
     sntahoe ntoahssssss asonth eosn       11:18
     [ button1 ]  [ button2 ]

[AH] @vpupkin
[AL] | Forwarded From: @user
     msg msg

Prompt with chat action
~~~~~~~~~~~~~~~~~~~~~~~

(ББ) Билеты Москва
     Билеты на Усик -Гасиев                19:01
____(@zevlg is typing...)_______________________
>>> []

Идеи
~~~~

- [DONE] telega-tracking-filter взаместо telega-use-tracking -
  Оределять что добавлять в трекинг, а что нет по фильтру
  сообщения/чата.  см Фильтры для чатов

  В итоге называется `telega-use-tracking-for'

- [DONE] Если чувак прокручивал историю и в это время приходят
  сообщения, то показывать сколько сообщений в modeline.

- Если показываются сообщения, но самое последнее сообщение ещё не
  загружено, то делать input недоступным, а в footer показывать колво
  непрочитаных сообщений/меншонов, типа:

  .................(100@2).................

  [DONE] только показываем сколько не прочитано в modeline

- [TODO] Если писать в чат нельзя, то не показывать prompt
  см. https://t.me/emacs_telega/3775

- [TODO] Глобальный chat input history, и чтобы по нему можно было
  искать в любом чате

- Если играется voice/videoNote  [DONE partly, video ноты не показывает]
  _____________________________[⏸ @zevlg [stop]]__
  >>> []

- [TODO] Labeled chats.  Чату можно назначить label и он показывается
  как префикс у имени чата.  По label можно фильтровать чаты.

    [*ITV* | chat1     ]
    [*Emacs* | chat2   ]           - [DONE]

  В рутбуфере иметь возможность группировать чаты по label, как в
  gnus, например:

    **ITV**
      [chat1      ]
      [chat2      ]
    **Emacs**
      [chat1      ]
      [chat2      ]

  Иметь возможность иметь favorite chats.  favorite chats это чаты с
  label="★"

Фильтры для чатов (aka Shared media)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Аля фильтры для чатов, только для сообщений

- Показывать треды, как в https://t.me/designers/44

  MSG1
  MSG2
  _______________________________[related messages]__
  >>> []

- Shared media

  MSG1
  MSG2
  _______________________________[shared photos]__
  >>> []

- Поиск по чату

  MSG1
  MSG2
  _____________________________[search "привет"]__
  >>> []

TODO
----

* Всегда трекать файлы в msg на апдейты, чтобы например
  `telega--deleteFile' отрабатывался.  Возможно ещё потребуется это
  для трекинга заливки файла [DONE]

* Не использовать `image-size' в media подсистеме, image-size
  полностью подгружает картинку даже если она ещё не показывается.
  Это делает загрузку стикеров/анимаций очень медленной

  [DONE] Частично сделал, но иногда всё равно вызывается `image-size'

* [TODO] Когда пользователь уходит в offline (фокус переключается), то
  можно скачать что-нибудь в бэкграунде, например жирную инфу о
  installed stickersets

* [TODO] Сделать настройку, чтобы в chat input не использовались emoji
  icon, проблема если cut&paste картинку, то она схлопывается в одну

* [TODO] Весь chatbuf делать read-only и только область с chatbuf
  inputом помечать как inhibit-read-only

* [TODO] undo list сделать, чтобы только измениня в chatbuf input
  попадали в undo list

* Рядом с location картинкой рисовать +/- для зума
  .-----------------.
  |                 | zoom: 2
  |                 | [ + ]
  |                 | [ - ]
  |                 |
  `-----------------'

  [DONE]

* Рисовать аватар(ы) на карте с локацией

  [DONE] Рисуется только :sender_user_id

* [TODO] Client Side filter для сообщений с рекламой в каналах:
   - Если канал и в сообщении есть кнопка с t.me/joinchat/xxx - то
     расцениваем как рекламу и игнорим

* [TODO] Ввести custom variable - telega-media-size
  '(MIN-WIDTH  MIN-HEIGHT MAX-WIDTH  MAX-HEIGHT)

  И при показе любой картинки делать её, чтобы она была в пределах
  этих размерах, не меньше и не больше.  Если картинка не помещается
  (меньше или больше по ширине или высоте), то скейлим.  После
  применения скейлинга нужно посчитать как x-margin так и y-margin
  (задаётся как cons в :margin)

* [DONE] Перед ">>>" показывать иконку чата, чтобы меньше было
  возможности отправить сообщение "не туда".

  Одночарактерная иконка чата также может быть использована в rootbuf.

- [WON'T DO] REPL для tdlib и для tonlib, куда можно вводить (s-exp) и
  в ответ пишутся ответы.

  [НЕ НУЖНО, можно просто евалить всё в *scratch*]

* [TODO] Записи о каком-то пользователе/чате.  Иногда удобно записать,
  что какой-то пользователь чудил или наоборот мегакрут был.  Можно
  хранить эти допкомменты в :client_data.

  Пользователей с допкомментами как-то помечать в чатиках (может быть
  на аватарке какой-нибудь астерик в углу ставить или ещё как), чтобы
  видно было, что это какой-то чувак с допкомментами

* Анимированые текстовые сообщения.  Сообщение выводится постепенно
  (как будто кто-то печатает его).  Просто апдейтим контент сообщения,
  добавляя по одному символу с определённым таймаутом и получатся
  как-будто печатаем

- [TODO] Возможность добавлять сообщение в список favorite messages
  (спец-сообщение в SavedMessages).  Можно там хранить прям список ссылок вида: 

  https://t.me/voicesofstrangers/255
  https://t.me/c/1041107395/291797

  Придумать какой-нибудь вариант ссылки вообще на любое сообщение, типа
  https://t.me/msg/<chat-id>/<msg-id/1048576>

  Использовать ~X-favorites-msg-id~ опцию(~telega--setOption~), чтобы
  хранить там msg-id, в котором хранятся favorite messages

Fonts
-----

* fonts-emojione  (colored emojis, for `telega-symbol-emojify')
* fonts-noto      (quite bad)
* Symbola from https://fonts2u.com/symbola.font (for unicode emojis with good vertical spacing)
* Symbola from https://github.com/ONLYOFFICE/core-fonts/blob/master/ancient-scripts/Symbola_hint.ttf (good vertical spacing)

* http://users.teilar.gr/~g1951d/  (Symbola Author: George Dourosg 1951d@teilar.gr)

Telega prefix map
-----------------

См. https://github.com/zevlg/telega.el/issues/87

C-c C-t  -> telega

C-c t     -> PREFIX
C-c t t   -> telega
C-c t s   -> telega-saved-messages (переключается на чат Saved Messages)
C-c t f   -> telega-file-send (посылает фото если режим image-mode,
             иначе как файл)
C-c t w   -> telega-save-buffer (записыват содержимое буфера в клауд)
C-c t b   -> telega-switch-buffer
C-c t C-s -> тоже самое что и C-c t w
