Сегодня в ветку experimental были залиты изменения, отвечающие за новый механизм движения по истории посещаемых записей в программе накопления информации MyTetra. В предыдущем релизе MyTetra уже были реализованы кнопки движения по истории и начальный механизм отслеживания перемещения пользователя. Однако старый механизм сбивался, когда пользователь в момент нахождения в "середине" истории переключался на совершенно другую запись не находящуюся в исторической последовательности.
Новый механизм движения по истории, который будет включен в новый релиз MyTetra, полностью переделан, и теперь правильно реагирует на последовательность перемещения пользоватля.
Казалось бы, ну что такого сложного в том, чтобы реализовать историю и перемещение по ней? А сложность в том, что пользователь далжен иметь возможность двигаться как назад, так и вперед по истории. Если бы пользователю была дана возможность двигаться только назад, то сложности никакой нет - знай уничтожай идентификаторы последней посещенной записи, да переключайся на предыдущую посещенную. Но когда нужно двигаться вперед по истории, то все становится гораздо интереснее.
Допустим, пользователь посетил записи с идентификаторами:
a, b, c, d, e
Затем он стал нажимать кнопку "назад по истории". Так как при движении назад удалять историю нельзя (потому что мы должны иметь возможность двигаться вперед), можно ввести понятие "Указатель в истории". При обычной работе он всегда указывает на самую актуальную (последнюю) ячейку в истории. А при движении по истории "Назад", смещается назад. Таким образом, перед началом движения по истории имеем:
a, b, c, d, e
^
А после того, как пользователь отъехал на 4 шага назад имеем:
a, b, c, d, e
^
Тут возникает вопрос. А надо ли при движении назад записывать посещаемые при движении назад записи в конец истории? Правильный ответ - надо (в старой версии MyTetra ответа на этот вопрос я не знал). Потому что если не записывать записи при движении по истории, то произойдет следующее. Предположим, что врнувшись к записи a, пользователь самостоятельно нажмет на запись h. А куда надо записать информацию о посещении h? Самое естественное - в конец истории. А так как пользователь начал "писать свою историю", то и указатель в истории надо переместить на новую запись. И тогда получим следующее:
a, b, c, d, e, h
^
А теперь попробуем снова нажать кнопку движения назад. Куда мы попадем? На запись e. А были то мы до этого на записи a. Хорошо, а если поступить по-другому, и поместить запись h после записи a? В середину истории запись h не засунешь, потому что получится черти что. Единственная возможность - это удалить все записи в истории справа от a, и добавить на их место h:
a, h
^
Но тогда теряется практически вся истори! Вот поэтому и надо записывать в историю все посещаемые записи, даже при движении по истории. Если мы записываем все движение назад, от e до a, то к моменту достижения записи a получим:
a, b, c, d, e, d, c, b, a
^
И если в этот момент пользователь самостоятельно кликнет на запись h, то история станет выглядеть так:
a, b, c, d, e, d, c, b, a, h
^
И если пользователь пожелает снова нажать кнопку "Назад", то он попадет на запись a, где он и был до этого. И так далее для других записей в глубину истории, причем последовательность именно та, в которой он видел записи. Для перехода с записи h на запись a история станет выглядеть так:
a, b, c, d, e, d, c, b, a, h, a
^
Здесь так же учитывается, что запись a еще и добавится как самая актуальная запись в истории.
Казалось бы, проблема решена? Нет! Что, если пользователь отъедет назад по истории, и начнет двигаться вперед? Из-за того, что посещенные записи добавляются даже, если происходит движение по истории, то история дополняется новыми записями с той же скоростью, что и движение указателя истории вперед. То есть, указатель никогда не достигнет самой актуальной записи:
a, b, c, d, e, d, c, b, a, h, a, h
^
a, b, c, d, e, d, c, b, a, h, a, h, a
^
Я долго думал, как же решить эту проблему. Пытался сделать маркеры на посещенных записях, для которых было движение назад по истории, чтобы при движении вперед "проскальзывать" эти записи. Но это не помогло - вновь появляющиеся в истории записи не маркировалсь (и непонятно, нужно ли их маркировать), в результате чего снова получалась путанница.
Решение было найдено в еще одном указателе, который активируется при начале движения назад по истории. Очевидно, что необходимо отслеживать момент, когда началось движение назад, чтобы при движении вперед, при достижении данного маркера перепрыгнуть к самой актуальной записи. Ну а если пользователь снова захочет проехать назад, он будет двигаться по "копиям" идентификаторов записей, которые появились в истории, когда он первый раз путешествовал назад-вперед. Причем последовательность этих "копий" правильная.
Именно такой механизм сейчас и реализован в MyTetra, и, если он покажет свою состоятельность, он будет в релизе.
Следите за новостями.