AppFiles - Mobile Development
2.17K subscribers
3.23K photos
44 videos
13 files
4.23K links
Библиотеки, обучающие статьи, курсы и видео для (мобильных) разработчиков. Если есть вопросы - пишите @lbogolubov.
Download Telegram
📺 Видео и подкасты за неделю

• (iOS En) AI-Assisted TDD in Practice (Swift + AI)
• (iOS En) Vibe Coding a macOS App in Xcode 27
• (iOS En) Apple Music Reactions Emoji Picker
• (And Ru) AI-агент Android-разработчика: как вынести его на сервер и выполнять задачи 24/7
• (And En) Beginner's Guide to Continuous Integration (CI) for Android with GitHub Actions
• (And En) Is TDD the next big thing for agentic development on Android?
• (And En) Reflection is Evil
• (Crs En) Developing Music Creation Apps for Web, Desktop and Android
• (Crs En) Advanced Kotlin Native Integration
• (Dev Ru) «Чё ты такой серьёзный?» Как юмор помогает продуктовым командам
• (Dev Ru) Анастасия Терёхина. Гадание на собеседовании: можно ли за час «технички» предсказать работу на годы вперед
• (Dev En) Redefining Machine Learning with Kotlin A Device First Approach to AI
• (Dev En) Teaching Kotlin for the AI Era: Tips, Tools, and Practical Insights
• (Mtr Ru) «Считаем то, что важно» – практический гид по метрикам в продукте

Прошлогодние видео:

• (iOS Ru) Стратегия автотестирования для iOS приложений
• (iOS Ru) 5 вопросов для iOS разработчика
• (iOS Ru) Борьба с утечками памяти: от задачи до победы
• (And Ru) Google закрывает свободу на Android
• (And Ru) 5 уроков из опыта реализации pixel-perfect тестирования дизайн-системы в Android
• (And Ru) Gradle-сборка. Измеряем самое важное
• (And Ru) Шифруем файлы в Android
• (Crs Ru) Kotlin Multiplatform в большом проекте
• (Dev Ru) Как «думают» LLM: внутренняя механика языковых моделей
• (Dev Ru) Как AI научился рассуждать — Reinforcement learning, reasoning models

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Как я написал круговой лаунчер на Jetpack Compose: тригонометрия свайпов и системные грабли

Большинство лаунчеров для Android повторяют одну и ту же концепцию сетки иконок. Чтобы открыть приложение, нужно листать бесконечные рабочие столы и тянуться пальцем до нужной иконки (а она может быть и в верхнем углу экрана, поэтому часто приходится использовать вторую руку).

Я решил сделать SwipeLauncher — открытый лаунчер с круговыми меню, где любое действие или вложенное меню открывается одним свайпом из любой точки экрана.

Статья: https://habr.com/ru/articles/1075198/
Платформа: Android

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Разработка на Авроре под Аврору: разворачиваем Coder в облаке и пишем плагин для VS Code

Среди веб-решений (GigaIDE, GitLab Web IDE и другие) мне больше всего нравится code-server (coder) — полноценная веб-версия Visual Studio Code, которая поддерживает большинство привычных плагинов. В статье я подробно расскажу, как развернуть облачную среду разработки, привязать ее к планшету и написать собственный плагин для автоматизации сборки под «Аврору ОС».

Статья: https://habr.com/ru/companies/selectel/articles/1074074/
Платформа: разработка

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
🤮1
Media is too big
VIEW IN TELEGRAM
Arkive - плагин Gradle для генерации веб-каталога экранов

Arkive превращает ваши первью Compose и XML-представлений в просматриваемый каталог экранов вашего приложения — запись производится на JVM с помощью Roborazzi (или, при желании, Paparazzi), без использования устройств или эмуляторов, без написания тестового кода.

Arkive на GitHub: https://github.com/infinum/arkive
Платформа: Android
⭐️: 17

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Lucide Swift - типобезопасные Lucide иконки с векторным рендерингом

Lucide Swift - библиотека для использования иконок Lucide с поддержкой векторной графики и типобезопасностью, нативная для SwiftUI. Более 2112 иконок (1738 обычных + 374 экспериментальных Lab), отображаемых как настоящие векторные фигуры из данных SVG-путей, без каких-либо зависимостей в рантайме.

Фичи: 

• Настоящий векторный рендеринг: SVG-пути преобразуются в нативные SwiftUI Shape, поэтому иконки можно масштабировать до любого размера без пикселизации.
• Типобезопасный API: 1 738+/1 792 enum-вариантов с полной поддержкой автодополнения Xcode. Проверка на этапе компиляции предотвращает ошибки вида «иконка не найдена» во время выполнения.
• Поддержка Lucide Lab: полная интеграция 374+ экспериментальных иконок из репозитория Lucide Lab.
• Ноль зависимостей: чистая реализация на Swift без внешних runtime-зависимостей — только Swift и SwiftUI.
• Нативная интеграция со SwiftUI: библиотека построена на протоколе SwiftUI Shape и поддерживает стандартные модификаторы, включая .stroke(), .fill(), .frame() и другие.
• Поддержка нескольких платформ: iOS 14+, macOS 11+, tvOS 14+, watchOS 7+, visionOS 1+.
• Настраиваемая толщина линии: толщину обводки можно задавать через параметр strokeWidth.
• Абсолютная толщина линии: absoluteStrokeWidth позволяет сохранять одинаковую толщину обводки независимо от размера иконки.
• Интеграция с Label: нативная поддержка SwiftUI Label для меню, панелей инструментов и кнопок.
• Высокая производительность: поиск иконки через enum примерно в 7 раз быстрее подходов на основе Bundle, а рендеринг через Shape — примерно в 2 раза быстрее растеризации PDF.

Lucide Swift на GitHub: https://github.com/ajaxjiang96/lucide-swift
Платформа: iOS
⭐️: 38

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Как я перестал платить за macOS-минуты: перенос iOS-сборки с GitHub Actions на Xcode Cloud, с цифрами

Есть один факт про GitHub Actions, который многие мобильные разработчики узнают только из счёта: одна минута на macOS-раннере стоит десять минут на Linux. Не в деньгах — в «бесплатных» минутах, которые входят в тарифный план. Ваш пятиминутный iOS-архив съедает из квоты столько же, сколько пятьдесят минут Linux-тестов. И пока Android-джоба тратит 6 минут квоты, её соседка по воркфлоу тратит 45.

Ниже — история одного переезда: как я вынес iOS-деплой из GitHub Actions в Xcode Cloud, что при этом сломалось (семь раз), что измерил и почему теперь iOS-релиз стоит мне ноль минут GitHub Actions и 6 минут оплачиваемого compute-времени Apple при 25 бесплатных часах в месяц.

Статья: https://habr.com/ru/articles/1076692/
Платформа: iOS

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
👏1
Рекомпозиции, которых не было

Недавно я глубоко погрузился в профилирование, пытаясь понять, почему один экран Compose в продакшене ощущался тяжелее, чем должен. То, что начиналось как обычная проверка производительности, быстро превратилось во что-то большее: Layout Inspector и Memory Profiler показывали совершенно разные картины происходящего. Вот что я обнаружил, что исправил и что хотел бы знать раньше.

Статья: https://apptractor.ru/info/articles/rekompozitsii-kotoryh-ne-bylo.html
Платформа: Android

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Compose Recomposition Highlighter - тепловая карта рекомпозиций

Compose Recomposition Highlighter — это инструмент для разработчиков, не создающий дополнительной нагрузки на систему и позволяющий разработчикам и QA-инженерам визуально выявлять избыточные рекомпозиции, нестабильные параметры и бесконечные циклы рендеринга непосредственно на физических устройствах в виде тепловых карт, без привязки к Layout Inspector в Android Studio.

Compose Recomposition Highlighter на GitHub: https://github.com/zakayothuku/compose-recomposition-highlighter
Платформа: Android
⭐️: 15

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Нативная разработка снова стала будущим мобильных приложений в Shopify

Мы не держимся за решение только потому, что когда-то оно было успешным. Когда меняется одна из ключевых предпосылок, мы готовы вернуться назад и спросить себя, остаётся ли это решение правильным. LLM изменили одну из основных предпосылок, лежавших в основе нашего решения 2020 года, поэтому мы заново оценили наш мобильный стек, начиная с фундаментальных принципов.

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

Статья: https://apptractor.ru/info/articles/nativnaya-razrabotka-snova-stala-buduschim-mobilnyh-prilozheniy-v-shopify.html
Платформа: кроссплатформа

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2😁2
Norch - скрипт, который прячет чёлку MacBook

Репозиторий нашего читателя:
Я долгое время пользовался бесплатным приложением TopNotch, которое прячет чёлку на MacBook. После обновления на macOS 27 оно перестало работать. Автор обещал исправление, но через пару недель, а ждать не хотелось. Поэтому я вместе с Claude написал простой бесплатный скрипт на Swift, который делает то же самое.

Работает так: даёшь ему картинку для обоев, а он добавляет сверху чёрную полосу под строкой меню и скругляет углы. Так решаются сразу две проблемы: чёлку не видно, и обои не выглядывают из-за углов окон, развёрнутых на весь экран. Размеры и радиус скругления скрипт берёт из системы, настраивать ничего не нужно, и в фоне ничего не висит.

Norch на GitHub: https://github.com/mezhevikin/norch
Платформа: iOS
⭐️: 4

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3👎1
Appstore PPP Prices - цены встроенных покупок по покупательной способности

Appstore PPP Prices — бесплатная утилита с открытым исходным кодом, которая приносит PPP-цены (паритет покупательной способности, ППС) в App Store. Она массово обновляет цены встроенных покупок и подписок сразу в 175+ странах: берёт коэффициенты из ВВП на душу населения, при желании подстраивает их через GPT под тип вашего приложения и записывает цены напрямую через App Store Connect API. Одна команда вместо вечера кликов по территориям.

Фичи: 

• Лёгкая установка — одна строка на macOS, Windows или Linux. Свой Python не нужен.
• Дружелюбно для ИИ-агентов — Claude Code, Codex или Cursor поставят, настроят и запустят всё за вас.
• Безопасно по умолчанию — --dry-run печатает все 174 цены до того, как применится хоть одна.
• Ключ API не покидает вашу машину — ни аккаунта, ни загрузки, ни посредника.
• 175+ территорий одной командой — и встроенные покупки, и подписки.
• Реальные ценовые точки Apple — каждая цена в местной валюте и принимается App Store Connect.
• Бесплатно и с открытым кодом (MIT) — подписка на утилиту для подписок не нужна.

Appstore PPP Prices на GitHub: https://github.com/duceum/appstore-ppp-pricing-agent-skill
Платформа: iOS
⭐️: 46

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Учим Siri говорить о вашем любимом приложении: пример Walk Mate

В посте на прошлой неделе я рассказал, как Walk Mate начал передавать избранные маршруты в Spotlight. Добавляете маршрут в избранное и задаёте ему название. Ищете в Spotlight, нажимаете — маршрут открывается на карте. Для этого использовались App Intents без особых изысков: IndexedEntity для избранного маршрута, OpenIntent для его загрузки и небольшой маршрутизатор, чтобы нажатие в Spotlight попадало в тот же редьюсер, что и нажатие внутри приложения. Фраз для Siri тогда ещё не было.

Spotlight уже знает, что прогулка существует. Теперь Siri в iOS 27 должна уметь говорить о ней.

В прошлый раз Spotlight мог находить избранный маршрут. Теперь я делаю так, чтобы Siri могла говорить о нём, передавать его в Карты и открывать голосом.

Статья: https://apptractor.ru/info/articles/uchim-siri-govorit-o-vashem-lyubimom-prilozhenii-primer-walk-mate.html
Платформа: iOS

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
AVD-SLIM - оптимизатор оперативной памяти и процессора для эмулятора Android

AVD-SLIM — это легковесная CLI-утилита, не имеющая внешних зависимостей, она снижает потребление оперативной памяти хост-системы виртуальным устройством Android (AVD) с ~8 ГБ до ~1,5 ГБ и практически сводит к нулю нагрузку на процессор в режиме простоя на системах с Apple Silicon и Linux.

При разработке Android-приложений на macOS или Linux разработчики нередко замечают, что процесс qemu-system-aarch64 потребляет от 5 до 8+ ГБ оперативной памяти в Activity Monitor.

Почему эмулятор потребляет 8 ГБ?

• Ловушка Lavapipe: Android Studio часто по умолчанию использует hw.gpu.mode = auto, из-за чего происходит откат на программную растеризацию Mesa на CPU (lavapipe). В результате около 4 ГБ буферов программного рендеринга выделяются непосредственно в оперативной памяти хоста поверх памяти гостевой ОС.
• Образы с размером страницы 16 КБ: на современных ARM64-образах (google_apis_ps16k) QEMU жёстко задаёт минимальный объём памяти (minRam = 4096MB), молча игнорируя более низкие настройки ОЗУ.
• Лишние системные службы Android: более 35 необязательных фоновых процессов — Google Assistant, System Intelligence, Maps, Photos, YouTube, телеметрия и другие — будят ядра CPU и засоряют память.
• Устаревшие снимки состояния: Android Studio повторно загружает закэшированные снимки (hardware-qemu.ini), в которых сохраняются тяжёлые состояния на 4 ГБ даже после перезапуска.

Решение

Так же как simslim отключает лишнюю активность iOS Simulator через launchctl, avdslim, AVD-SLIM:

• Передаёт QEMU параметр -lowram: снимает внутренний нижний предел в 4 ГБ и запускает ядро Android в режиме малого объёма памяти (hw.ramSize = 1024M или 1536M).
• Принудительно включает аппаратное ускорение GPU на разных платформах: использует -gpu host, чтобы рендеринг выполнялся нативно через драйверы графики хоста, полностью обходя программные растеризаторы на CPU.
• Отключает более 24 лишних фоновых служб: выключает необязательные сервисы Google через pm disable-user --user 0.
• Убирает задержки анимаций: устанавливает масштаб анимации окон, переходов и аниматоров в 0x.
• Снижает фоновую активность: ограничивает background_process_limit = 4, сохраняя работу OAuth и биометрии, а также отключает автосинхронизацию.
• Очищает кэши: сбрасывает страничные кэши Linux и выполняет уплотнение памяти.
qemu-system-aarch64  ██████████████████████████  8,518 MB
qemu-system-aarch64 █████ 1,560 MB

Reclaimed: ~6.0 GB host RAM (82% reduction)


AVD-SLIM на GitHub: https://github.com/kdbhalala/avdslim
Платформа: Android
⭐️: 31

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Как разрабатывать фронтенд без готового бэкенда: инструменты перехвата трафика, мокирования и принцип их работы

Зимой 2026 мы получили задачу: новый финансовый инструмент, дедлайн через три месяца, готовность бэкенда — через полтора. Команда начала работу на моках и успела. В статье я расскажу, какие инструменты перехвата и мокирования трафика помогли нам выпустить фичу в срок без готового бэкенда, как настроить их за один вечер и почему понимание принципов работы TLS и MITM-атаки экономит часы отладки.

Статья: https://habr.com/ru/companies/tbank/articles/1082854/
Платформа: разработка

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Я создал Android-приложение на Swift: главное о новом SDK в Swift 6.3

Около 10 лет я пишу на Swift исключительно для закрытой экосистемы Apple. Поэтому, когда я прочитал, что в Swift 6.3 наконец появился официальный SDK для Android… я буквально рассмеялся. А потом всё-таки решил нормально попробовать его за выходные.

Кратко: нет, я не запустил SwiftUI-приложение на своём Pixel. Зато получил кое-что намного интереснее — и гораздо более применимое к моей реальной работе.

Статья: https://apptractor.ru/info/articles/ya-sozdal-android-prilozhenie-na-swift-glavnoe-o-novom-sdk-v-swift-6-3.html
Платформа: кроссплатформа

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Storeshots-MCP - генератор скриншотов для App Store и Google Play

Создание скриншотов для магазина приложений — это, по сути, две разные задачи, скрывающиеся под одной вывеской. Первая — творческая (что именно показать, какой экран лучше всего «продает» конкретную функцию, как сформулировать текст на многих языках), а вторая — техническая (оформление рамок, типографика, точные размеры в пикселях, отсутствие альфа-канала). При использовании обычных дизайн-инструментов обе части работы приходится выполнять вручную, тогда как специализированные SaaS-сервисы делают техническую составляющую доступной только по платной подписке.

Storeshots-MCP превращает необработанные скриншоты приложения в готовые визуальные материалы для страниц в магазинах приложений: добавляет рамки устройств, заголовки с акцентом на преимущества и брендированные фоны, а также обеспечивает точное соответствие размерам, требуемым в App Store и Google Play. Инструмент работает как MCP-сервер, поэтому используемый вами ИИ-агент пишет и переводит тексты, а storeshots генерирует итоговые изображения. Никаких графических редакторов, подписок или API-ключей.

Storeshots-MCP на GitHub: https://github.com/mtbun/storeshots-mcp
Платформа: разработка
⭐️: 20

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
📺 Видео и подкасты за неделю

• (iOS En) iPhone Duo Group Lab + iPhone Duo Group Lab
• (iOS En) Meet new APIs for iPhone Duo
• (iOS En) Chat Bubble TextField Transition Using SwiftUI
• (iOS En) AsyncImage Caching in iOS 27: Everything You Need to Know
• (iOS En) Apple Music Player Bottom Bar Transition
• (iOS En) iOS 27 Launch Screens Done Right: Simple to Fully Custom
• (iOS En) Apple Bed Time Circular Slider Using SwiftUI
• (And Ru) Когда Shared Transition — это требование дизайнеров: необычные кейсы на Compose
• (And Ru) Как поменялась Android-разработка с приходом AI
• (And Ru) Спрятаться у всех на виду: как современные вирусы под Android избегают декомпиляции, анализа и изучения кода
• (And Ru) Своя Android-ферма без фермы: автоматизация реальных устройств в CI/CD
• (And En) My Full App Development Tech Stack In 2026
• (And En) Certificate Pinning - The MOST Important Security Measure for Network Traffic In Your App
• (And En) What's New in Kotlin 2.4.20
• (And En) Powering Up Your Assertions
• (Dev Ru) Автоматическое code review на базе OpenCode: LLM-агент в CI/CD
• (Dev Ru) AI как экзокостюм разработчика
• (Dev Ru) Путь к Chaos As A Service: как (и зачем) мы построили платформу для Chaos Engineering
• (Dev Ru) Как попасть в IT в 2027 году. Что учить для начала карьеры.

Прошлогодние видео:

• (iOS Ru) Пишем видеоплеер под iOS с нуля
• (And Ru) Разбор кода: пиксельная погода на Kotlin
• (And Ru) Бессмертное приложение
• (And Ru) Укрощаем UDF state-based архитектуры. Реальные кейсы в больших приложениях

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Переносим дизайн-систему в код: риски, решения, лучшие практики

В этой статье я расскажу, как нам удалось возродить проект дизайн‑системы из мертвых и успешно внедрить её в наше приложение. Поделюсь опытом создания дизайн‑системы на Jetpack Compose для Android‑проекта. При этом большинство подходов применимы и на других платформах, а также помогают лучше понять общие принципы разработки подобных решений. Материал будет полезен как тем, кто только планирует внедрять дизайн-систему в свой продукт, так и тем, кто уже находится в процессе.

Статья: https://habr.com/ru/companies/domclick/articles/993686/
Платформа: Android

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
LiquidGlass for Android - жидкое стекло для View

Высокопроизводительный компонент в стиле Liquid Glass / «глассморфизма» для системы Android View, поддерживающий размытие фона в реальном времени, преломление на основе SDF, хроматическую дисперсию и интерактивные эффекты, напоминающие поведение жидкости.

Просто добавьте его в существующую иерархию View. Миграция на Compose не требуется. Работает с API 24+. 

LiquidGlass for Android на GitHub: https://github.com/QWEA0/Liquid-Glass-Android
Платформа: Android
⭐️: 148

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
👏3
Нативные OTA-обновления в Android: что можно исправить без выпуска нового APK

Практическое руководство по архитектуре обновлений в Android: Play In-App Updates, Remote Config, server-driven UI, ограничения на динамический код и причины, по которым механизм Code Push во Flutter не имеет прямого аналога в нативной разработке на Kotlin.

Статья: https://apptractor.ru/info/articles/nativnye-ota-obnovleniya-v-android-chto-mozhno-ispravit-bez-vypuska-novogo-apk.html
Платформа: Android

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
Giga Pisar - русская диктовка для macOS на GigaAM

Giga Pisar - диктовка голосом для macOS на модели GigaAM v3 от Сбера, открытой SOTA-модели распознавания русской речи. Точнее Whisper на русском, сама расставляет пунктуацию и заглавные, работает полностью локально — звук не покидает компьютер.

Распознавание работает внутри самого приложения. Ни питона, ни ffmpeg, ни Homebrew, ни какого-либо сервера рядом.

• main.swift — приложение в строке меню: перехват клавиши-рации, запись с микрофона, вставка текста
• swift/ — ядро распознавания на Swift: Features.swift (звук → признаки), Ort.swift (запуск модели), Recognizer.swift (декодирование RNN-T), Tokenizer.swift (сборка текста), Audio.swift (чтение wav, нарезка по паузам)
• swift/Brain.swift — мозг по желанию: локальная нейронка (вложенный llama.cpp) причёсывает надиктованное по командам вроде «Писарь, исправь»
• swift/Chips.swift — менюшка у курсора: собрать мысль / сократить / перевести, подмена текста на месте и «вернуть как было»
• vendor/ — onnxruntime и движок llama.cpp, качаются сборкой сами (в репозиторий не входят)
• install.sh — кладёт файлы модели в ~/.giga/model

Ядро — перенос на Swift питоновского giga_core.py из Гига Писаря для Linux. Оба гоняются на одних записях скриптом scripts/сверка-swift.py и должны выдавать один и тот же текст.

Giga Pisar на GitHub: https://github.com/moznoazachem/giga-pisar
Платформа: macOS
⭐️: 47

👨‍🦯‍➡️ AppFiles: код, инструменты, практики, производительность
Please open Telegram to view this post
VIEW IN TELEGRAM