Я продолжаю свое путешествие в мир Open Source Software, и я хотел бы поделиться своим недавним опытом исправления ошибки в большом iOS-приложении. Это приложение Firefox Focus для iOS.

Этот вклад примечателен для меня, потому что это был мой первый вклад, в котором я исправил настоящую ошибку в таком большом проекте. Мои предыдущие вклады в основном были сосредоточены на улучшениях кода/проекта.

Если вы не читали мой рассказ о моем участии в Hacktoberfest 2018, то можете найти его здесь:



Теперь позвольте мне рассказать вам о проекте и исправлении ошибок.

Фаерфокс Фокус 🔥🦊

Firefox Focus для устройств iOS — это браузер для обеспечения конфиденциальности с защитой от отслеживания и блокировкой контента. (Получено с сайта Мозилла)

Вы можете скачать Firefox Focus в App Store.

Кроме того, если вы занимаетесь разработкой для iOS или занимаетесь разработкой с открытым исходным кодом, вы можете внести свой вклад в этот проект на GitHub.

Просматривайте, как будто никто не смотрит. Новый Firefox Focus автоматически блокирует широкий спектр онлайн-трекеров — с момента запуска до момента выхода из него. Легко стирайте свою историю, пароли и файлы cookie, чтобы вас не преследовали такие вещи, как нежелательная реклама. (Взято из описания приложения в App Store)

Вот несколько скриншотов этого приложения:

Частный просмотр в большинстве браузеров не является исчерпывающим или простым в использовании. Focus — это конфиденциальность следующего уровня, которая бесплатна, всегда доступна и всегда на вашей стороне, потому что ее поддерживает Mozilla, некоммерческая организация, которая борется за ваши права в Интернете. (Взято из описания приложения в App Store)

Одной из его особенностей является то, что если вы не хотите переключаться с Safari, вы все равно можете использовать функциональность Firefox Focus в Safari (для этого выполните следующие шаги).

Ошибка ❌

Проблема заключалась в том, что текст поиска в строке URL не соответствовал фактическому поиску после использования навигации вперед и назад. Давайте рассмотрим пример:

  1. Поиск «хранитель»
  2. Поиск «мозилла»
  3. Нажмите назад
  4. Найдите «файрфокс»
  5. Нажмите назад
  6. Страница поиска показывает результаты по запросу «защитник», но Панель URL содержит « mozilla» вместо «хранитель».

Исправить 🔧

Автор проблемы оставил там пометку, что проблема может быть в SearchHistoryUtils стеке. Это помогло мне начать исследование проблемы.

Я нашел класс SearchHistoryUtils, который содержит два логических свойства.

  1. isFromURLBar
  2. isNavigating

и четыре функции:

  1. pushSearchToStack(with searchedText: String) — когда пользователь делает новый поисковый запрос, эта функция помещает этот поиск в стек.
  2. pullSearchFromStack() -> String? — эта функция не выталкивает поиск из стека, а возвращает значение текущего искомого текста, если он есть.
  3. goForward() — обновляет значение isCurrentSearch для объектов стека.
  4. goBack() — то же, что и №3

Когда я анализировал код, я исключил функции pullSearchFromStack, goForward и goBack, потому что они на самом деле не имели дело с изменениями стека. Поэтому я начал отлаживать функцию pushSearchToStack. Я отладил несколько тестовых случаев, и давайте посмотрим на мои выводы.

Итак, я в значительной степени воспроизвел ошибку, описанную в проблеме, и нашел проблему:

Когда последний поиск не является текущим поиском (например, в стеке после первого действия пользователя «Вернуться») и пользователь выполняет новый поиск, последний поиск не заменяется новым (см. красную строку в таблице выше). ).

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

Давайте взглянем на фрагмент псевдокода функции pushSearchToStack:

Разберем приведенный выше код:

  1. Он объявляет пустой стек currentStack.
  2. Он устанавливает значение currentStack в значение глобального состояния searchedHistory value.
  3. Затем он просматривает каждый поиск в стеке и устанавливает значение свойства isCurrentSearch равным false.
  4. Он добавляет новый поиск в стек и устанавливает для свойства isCurrentSearch значение true.

Поэтому я немного поиграл с кодом и добавил проверку, является ли последний поиск текущим поиском:

Если последний поиск не является текущим поиском, это означает, что пользователь нажал кнопку «назад», и currentStack удалит свой последний элемент.

Я попытался смоделировать тестовый пример, описанный выше, и он работал так, как должен был работать! Текст поиска в строке URL соответствует странице поиска.

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

Несмотря на то, что это было неправильно, это дало мне понять, что я на правильном пути.

Итак, я развил свой код:

Теперь он проверяет, является ли последний поиск текущим поиском. Если это не текущий поиск, он ищет текущий поиск в стеке и удаляет все последующие поиски из стека.

Затем он добавляет новый поиск со значением свойства isCurrentSearch в true в стек.

Весь вклад вы можете найти в моем Pull Request.

Наконец, давайте взглянем на исправленную версию браузера.

Как видите, текст в строке URL совпадает со страницей поиска, даже если вы вернетесь назад и вперед столько раз, сколько захотите.

Вывод

Мой запрос на включение был успешно объединен ✅

В целом, мне понравился опыт участия в этом проекте, и я, вероятно, буду работать над другими вопросами там снова 👨🏻‍💻🔜🔥🦊