MEOWLS — мобильное приложение для iOS, которое предлагает пользователям удобную платформу покупки товаров для домашних животных. Приложение имеет два режима: Store для клиентов и POS для сотрудников.
- Основные возможности
- Технологии и инструменты
- Структура проекта
- Внешний вид приложения
- Развертывание и запуск
- Тестирование
- Поддержка и вклад
- Помощь
- Благодарность
- Лицензия
- Главная страница: Экран с автоматическими и обычными слайдерами баннеров, статическими баннерами, текущими акциями, скидками, подборками товаров;
- Поиск: Возможность поиска интересующего товара или категории;
- Избранное: Любимые товары, отмеченные сердечком не потеряются. Поддержка сохранения избранных товаров и для неавторизованного пользователя, с последующей синхронизацией (merge) с уже избранными товарами после авторизации;
- Авторизация: Экран входа, чтобы ничего не потерять. Возможность просмотреть пользовательское соглашение и политику конфиденциальности;
- Регистрация: Если еще нет аккаунта, его легко создать; После регистрации выполняется автоматический вход в аккаунт;
- При авторизации или регистрации выполняется синхронизация корзины, избранного, если там есть товары;
- Каталог: Просмотр товаров по выбранным категориям или сразу всех;
- Листинг товаров: Возможность посмотреть товары, добавить в корзину/избранное, не открывая товар, применить желаемые фильтры и сортировку или открыть выбранный товар;
- Карточка товара: Детально изучите выбранный товар, посмотрите нужную информацию, изображения;
- Корзина: Добавляйте товары для того, чтобы их не потерять и купить по выгодной цене;
- Оформление заказа/Чекаут: Заполните необходимую информацию об адресе доставки, времени получении, получателе и способе оплаты;
- Заказы: Ваши предыдущие заказы;
- Профиль пользователя: Возможность перейти в нужные разделы приложения, просмотреть/изменить личную информацию, открыть совершенные заказы, контактную информацию, выйти из аккаунта или его удалить;
- Swift: Язык проекта;
- Архитектура: MVVM+State Machine+Router (UIKit), MVVM+Observation+Router (SwiftUI+Combine);
- Паттерны: Фабрика, Билдер, Синглтон, Стратегия+Команда;
- SOLID, DRY, KISS, YAGNI: Разработка придерживающаяся этих принципов;
- UI: UIKit, SwiftUI. Верстка кодом. Кастомные переиспользуемые компоненты;
- Изображения: Kingfisher + кеширование;
- Сеть: Alamofire, кастомные обертки APIWrapper, APIService. Работа с сервером посредством REST-API, кодирование/декодирование данных. Пагинация запросов (кастомный Paginator);
- Многопоточность и асинхронность: GCD, async/await, Task;
- Dependency Injection: Factory + вся инъекция через протоколы;
- Хранение данных: Обертки над Keychain, UserDefaults;
- Безопасность: Часть запросов покрываются токеном со сроком действия, поддержка обновления токена или предложения повторной авторизации.
- Fastlane: Автоматизация процессов сборки, тестирования и эмулирование развертывания. При МР в develop или main запускает сборку проекта, тесты для двух таргетов для получения возможности влить изменения;
- GitHub Actions + self-hosted runner;
- XcodeGen: Автоматизация и предотвращение проблем, связанных с ручной правкой .xcodeproj. Сборка проекта на раннере;
- SwiftGen: Генерация кода для изображений, цветов;
- Поддержка нескольких языков: Локализация строк для русского и английского языков;
Ошибки и аналитика: Firebase
👀 РАСКРЫТЬ СТРУКТУРУ
.
├── MEOWLS
│ ├── Store # Специфичные таргету покупателя исходные коды
│ │ ├── Common # Общие файлы для всего таргета
│ │ │ ├── Extensions # Расширения
│ │ │ ├── Files # Файлы, например json, картинка ресурсов и �т.д.
│ │ │ └── Resources # Картинки, цвета
│ │ │ ├── Assets.xcassets
│ │ │ ├── Colors.xcassets
│ │ │ ├── Generated # Сгенерированный SwiftGen ресурсы
│ │ │ ├── Info.plist
│ │ │ ├── Storyboards # Только LaunchScreen используется в проекте как сториборд
│ │ │ └── Strings # Локализация строк
│ │ ├── Components # Кастомные UI компоненты
│ │ │ └── SwiftUI. # для SwftUI
│ │ │ └── Controls
│ │ ├── Modules # Модули(экраны) покупателя
│ │ │ ├── App # AppDelegate, SceneDelegate
│ │ │ ├── Favorites # Экран избранного. Каждый модуль внутри разбит на одинаковую структуру:
│ │ │ │ ├── ApiService # Сетевой слой модуля, взаимодействующий с глобальными APIService или APIWrapper.
│ │ │ │ │ ├── FavoritesApiService.swift # Реализация
│ │ │ │ │ └── FavoritesApiServiceProtocol.swift # и обязательный протокол
│ │ │ │ ├── Builder # Сборщик модуля (протокол и регистрация в DI внутри)
│ │ │ │ │ └── FavoritesBuilder.swift
│ │ │ │ ├── Helper # Различные хелперы и сервисы только для данного модуля
│ │ │ │ │ └── FavoritesCellFactory.swift # Фабрика создания моделей для таблицы(List)
│ │ │ │ ├── Model # Модель модуля
│ │ │ │ │ └── FavoritesModel.swift
│ │ │ │ ├── Router # Роутер модуля, наследует CommonRouter. Может проксировать запросы роутинга в глобальный Router
│ │ │ │ │ ├── FavoritesRouter.swift # Релизация, наследующая CommonRouter
│ │ │ │ │ └── FavoritesRouterProtocol.swift # и обязательный протокол, наследующий CommonRouterProtocol
│ │ │ │ ├── View # Содержит View или ViewController. Может содержать компоненты/ячейки для этого модуля
│ │ │ │ │ └── FavoritesView.swift
│ │ │ │ └── ViewModel # Бизнес логика модуля. Может содержать дочерние вью модели
│ │ │ │ ├── FavoritesViewModel.swift # Реализация
│ │ │ │ └── FavoritesViewModelProtocol.swift # и обязательный протокол наследующий ObservableObject
│ │ │ ├── Intro
│ │ │ ├── ProfileData # Пример структуры папок модуля с дочерней вью моделью
│ │ │ │ ├── ApiService
│ │ │ │ ├── Builder
│ │ │ │ ├── Helper
│ │ │ │ ├── Model
│ │ │ │ ├── Router
│ │ │ │ ├── View
│ │ │ │ └── ViewModel
│ │ │ │ └── ChildViewModel
│ │ │ └── Root # Рутовый таб контроллер для приложения покупателя
│ │ │ └── RootTabController.swift
│ │ ├── Services # Специфичные для таргета сервисы
│ │ └── Tests # Тесты(API, Unit, UI) для приложения покупателя
│ ├── Kit # Общие для всех таргетов исходные коды
│ │ ├── API # Модели ответов и запросов
│ │ │ └── Model
│ │ │ ├── Address
│ │ │ │ ├── Address.swift
│ │ │ │ ├── City.swift
│ │ │ │ └── Location.swift
│ │ │ ├── Cart
│ │ │ ├── Category
│ │ │ ├── Coordinatable.swift
│ │ │ ├── Dummy
│ │ │ ├── Error
│ │ │ ├── Favorites
│ │ │ ├── Image
│ │ │ ├── MainBanner
│ │ │ ├── Network # API path для обращения к серверу, дженерик модели ответов сервера
│ │ │ │ ├── APIResourcePath.swift
│ │ │ │ ├── APIResourceServer.swift
│ │ │ │ ├── APIResourceService.swift
│ │ │ │ └── APIResponse.swift
│ │ │ ├── Pagination # Пагинация
│ │ │ ├── Product
│ │ │ ├── Redirect
│ │ │ ├── Sale
│ │ │ ├── Search
│ │ │ ├── Suggestions
│ │ │ └── User
│ │ ├── Common
│ │ │ ├── Extensions
│ │ │ ├── Files
│ │ │ └── Resources
│ │ ├── Components
│ │ │ ├── Alert # Кастомный алерт
│ │ │ ├── DesignSystem # Дизайн система, кастомные компоненты для всего приложения
│ │ │ │ ├── SwiftUI
│ │ │ │ │ ├── Controls
│ │ │ │ │ │ ├── ButtonStyles
│ │ │ │ │ │ └── Loader
│ │ │ │ │ ├── DomainHostingController.swift
│ │ │ │ │ ├── Extensions
│ │ │ │ │ ├── Message
│ │ │ │ │ ├── TextFields
│ │ │ │ │ └── Web
│ │ │ │ └── UIKit
│ │ │ │ ├── Buttons
│ │ │ │ ├── Cells
│ │ │ │ │ ├── DomainBoldWithButtonCollectionHeader
│ │ │ │ │ ├── DomainHeaderWithButtonTableCell
│ │ │ │ │ └── ProductCell
│ │ │ │ ├── Controls
│ │ │ │ │ └── DomainImageSlider
│ │ │ │ ├── View
│ │ │ │ │ └── Message
│ │ │ │ └── Web
│ │ │ ├── Navigation
│ │ │ ├── Nibless
│ │ │ └── Utilities
│ │ ├── Modules
│ │ │ ├── Authorization
│ │ │ ├── AutoCompleteField
│ │ │ ├── Catalogue
│ │ │ │ └── CatalogueListing
│ │ │ ├── Intro
│ │ │ ├── MainFlow
│ │ │ ├── Region
│ │ │ └── Search
│ │ ├── Services
│ │ │ ├── DataSource
│ │ │ ├── FavoritesService
│ │ │ ├── Keychain
│ │ │ ├── LocationManager
│ │ │ ├── Logging.swift
│ │ │ ├── Network
│ │ │ │ ├── APIErrorLocalizer.swift
│ │ │ │ ├── APIService.swift
│ │ │ │ ├── APIServiceProtocol.swift
│ │ │ │ └── APIWrapper
│ │ │ │ ├── APIWrapper.swift
│ │ │ │ └── APIWrapperProtocol.swift
│ │ │ ├── RegionService
│ │ │ │ └── RegionAgent
│ │ │ ├── Router
│ │ │ │ ├── CommonRouter.swift
│ │ │ │ └── CommonRouterProtocol.swift
│ │ │ ├── SettingsService
│ │ │ │ ├── SettingsKey.swift
│ │ │ │ ├── SettingsService.swift
│ │ │ │ └── SettingsServiceProtocol.swift
│ │ │ ├── UniversalPaginator
│ │ │ │ ├── Paginator.swift
│ │ │ │ └── PaginatorProtocol.swift
│ │ │ ├── User
│ │ │ │ ├── Customer
│ │ │ │ ├── Employee
│ │ │ │ └── User.swift
│ │ │ ├── Validation
│ │ │ │ └── Validator.swift
│ │ │ └── WebView
│ │ │ └── WebKitCacheCleaner.swift
│ │ └── Tests
│ ├── POS
│ │ ├── Common
│ │ ├── Components
│ │ ├── Modules
│ │ ├── Services
│ │ └── Tests
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Pods
│ │ ├── Alamofire
│ │ ├── Factory
│ │ ├── Kingfisher
│ │ ├── PhoneNumberKit
│ │ └── SnapKit
│ ├── Tests
│ │ ├── APITests
│ │ │ ├── POS
│ │ │ └── Store
│ │ ├── UITests
│ │ │ ├── POS
│ │ │ └── Store
│ │ └── UnitTests
│ │ ├── POS
│ │ └── Store
│ ├── build
│ │ └── XCBuildData
│ ├── Fastlane
│ │ ├── Fastfile
│ │ ├── README.md
│ │ ├── report.xml
│ │ └── test_output
│ │ ├── api_tests_pos
│ │ ├── ui_tests_pos
│ │ └── unit_tests_pos
│ ├── project.yml
│ ├── swiftgen.yml
│ ├── MEOWLS.xcodeproj
│ └── MEOWLS.xcworkspace
├── Automation
│ ├── Scripts
│ │ └── setup
│ └── Swiftgen
│ ├── ColorAssets.stencil
│ ├── ImageAssets.stencil
│ ├── KitColorAssets.stencil
│ └── KitImageAssets.stencil
├── Brewfile
├── Brewfile.lock.json
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
└── XcodeTemplate
Только Store приложение
ОБЗОР ПРИЛОЖЕНИЯ
Открыть в высоком разрешении
fullMEOWLSAppRecord.mov
1. Установка Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
ИЛИ
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Important
Для продолжения убедитесь, что у вас установлен Homebrew.
2. Установка brew пакетов из Brewfile:
Important
Для продолжения убедитесь, перейдите в папку с проектом, содержащую папки Automation
, MEOWLS
и т.д.
brew bundle && \
export PATH="/opt/homebrew/opt/ruby/bin:$PATH"
3. Установка Bundler:
gem install bundler --user-install
ИЛИ если есть проблемы
sudo gem install bundler
4. Установка гемов из Gemfile:
bundle install
5. Сборка проекта скриптом setup:
Important
Для продолжения убедитесь, перейдите в папку со скриптом ./Automation/Scripts и запустите скрипт из командной строки:
Поддерживаются команды для скрипта: «open» для открытия проекта после сборки и «clear» для очистки существующих проектных файлов перед сборкой (например, ./setup clear open
).
Скрипт запустит xcodegen
для сборки проекта, swiftgen
для генерации ресурсов и pod install --repo-update
для установки под зависимостей проекта.
./setup
Important
В данный момент реализовано только приложение для покупателя [ТАРГЕТ Store Debug/Release], для просмотра MVP проекта выбирайте его. Можно зарегистрироваться под любым номером телефона без подтверждения.
- Выберите таргет Store Debug/Release;
- Необходимо собрать проект для тестирования: Product -> Build For -> Testing (⇧+⌘+U);
- Далее нужно выбрать тестовый план: Pdouct -> Test Plan -> APITest(по умолчанию)/UITest/UnitTest;
- Запуск тестов: Product -> Test (⌘+U).
- Откройте терминал и перейдите в корень проекта - папка, содержащая
Stote
,Kit
иPOS
; - Запустите сборку/тесты командами, указанными в файле
Fastlane/README.md
, например:
fastlane ios debug_build_store && \
fastlane ios ui_tests_store
Я рад любым предложениям по улучшению проекта. Для этого создайте форк репозитория и отправьте Pull Request.
Если нужно связаться со мной или получить помощь по проекту, пишите на почту и в телеграм.
Все иконки в приложении взяты с сайта https://www.svgrepo.com/.
Vectors and icons by SVG Repo.
Для получения информации со своего сервера используется API https://api.meowls.artemayer.ru.
Статика, пользовательское соглашение, политика конфиденциальности, правила возврата, условия доставки и контакты доступны по адресу https://static.artemayer.ru/.
Проект лицензирован под GPL-3.0 License. Подробности смотрите в файле LICENSE.