Сообщество - Лига программистов

Лига программистов

2 119 постов 11 911 подписчиков

Популярные теги в сообществе:

8
Вопрос из ленты «Эксперты»

ИИ для обычного человека

Доброго дня уважаемые!
Я где то около года назад начал пользоваться Искусственным Интеллектом, начал знакомство с DeepSeek от Китайских друзей. Но по мере изучения возможностей понял, что в одном чате он не много информации может запоминать, и со временем он забывает что было в начале чата. Так же он не делал чего либо в файлах Ворд, Ексель и подобных.
Я перешел на ChatGPT, он мне так понравился, что я начал оплачивать подписку и активнее пользоваться им. Но проблема крайне медленной работы меня доконала.

Я хотел бы задать вопрос к знающим это дело, какой ИИ по функционалу такой же как ChatGPT или даже лучше, но при этом со скоростью в России более менее норм.

Я использую Андроид, Самсунг С24ФЕ, установил ГПТ как ПВА приложение (это как я понял веб версия оформленная в приложение)

Я не пользуюсь там картинками рисованием или монтажом видео или прочее. Мне он нужен для работы (работаю технологом в общественном питании), да и в жизни если мне нужно собрать данные из нужных мне источников и проанализировать, то он мне очень помогает. А файлы типа эксель и ворд очень нужны по работе.

Прошу совета, вроде как для таких запросов пост для минусов будет в комментарии.
Не плюсов ради, а помощи для )

2

Прощай, терминальный хаос: пишем свой TUI-менеджер port-forward для Kubernetes на Go

Прощай, терминальный хаос: пишем свой TUI-менеджер port-forward для Kubernetes на Go

Введение

Каждый, кто работает с Kubernetes, знает эту боль. Утро начинается с того, что нужно подключиться к базе данных в production для дебага, потом к Redis в staging для проверки кэша, затем к RabbitMQ для мониторинга очередей, и наконец к API-сервису для тестирования нового эндпоинта.

И вот уже восемь открытых терминалов, в каждом — свой kubectl port-forward. Окна перемешиваются, названия похожи, и найти нужный терминал становится квестом.

Ну да да, можно использовать Tmux, но это не сильно облегчает процесс.

С какими проблемами я столкнулся

  • Потеря контекста — когда одно из соединений падает, приходится перебирать все терминалы, чтобы найти нужный. На это уходит драгоценное время.

  • Ручная работа при смене контекста — переключил kubectl context на другой кластер, и всё нужно перенастраивать заново. Каждый раз одни и те же команды.

  • Отсутствие истории — вернулся после обеда, половина соединений отвалилась. Какие именно порты были нужны? Приходится вспоминать или искать в истории bash.

  • Сложность передачи знаний — коллега просит команду для подключения к сервису. Диктуешь по буквам namespace, имя пода, номера портов. Это неэффективно и приводит к ошибкам.

Я решил, что пора автоматизировать этот процесс и написать специализированный инструмент, исходник на GitHub PortFwd

Анализ существующих решений

Прежде чем писать своё, я изучил, что уже есть на рынке. Оказалось, что решения существуют, но каждое имеет свои плюсы и минусы.

kubectl port-forward

Встроенный инструмент, который работает надёжно и стабильно. Но у него принципиальное ограничение: один терминал — одно соединение. При работе с микросервисной архитектурой, где нужно одновременно держать открытыми 5-10 соединений, это превращается в хаос.

kubefwd

Интересный проект, который автоматически форвардит все сервисы из namespace. Звучит удобно, но есть серьёзные проблемы. Во-первых, он требует права sudo, потому что модифицирует /etc/hosts. Во-вторых, это слишком инвазивно — я хочу контролировать, какие именно сервисы форвардить, а не получать всё скопом.

Lens

Красивый графический интерфейс с множеством функций для работы с Kubernetes. Но это Electron-приложение, которое потребляет более 500 МБ оперативной памяти и 2% CPU даже в режиме простоя. Для такой простой задачи, как управление port-forward, это явный overkill. Плюс Lens — это комбайн, а мне нужен специализированный инструмент.

k9s

Отличный TUI для работы с Kubernetes, который я сам активно использую. Но port-forward там — не основная функция. Управлять множеством одновременных соединений неудобно, нет сохранения сессий, нет группировки.

После этого анализа я понял, что нужно писать своё решение. Лёгкое, специализированное, без Electron'а.

kftRay

Отдельно рассмотрю и сравню проект https://kftray.app/

Сравнение этих двух инструментов интересно тем, что они решают одну и ту же задачу — управление пробросом портов (port-forwarding) в Kubernetes — но делают это с совершенно разных позиций.

Характеристика kftray (Rust) portFwd (Go) Язык программирования Rust (фреймворк Tauri) Go Интерфейс Полноценный GUI (графическое окно в трее) CLI (командная строка) + кастомный UI Сложность Высокая (визуальное управление множеством конфигов) Минималистичная (быстрый запуск из терминала) Кроссплатформенность Отличная (Windows, macOS, Linux) Отличная (нативный бинарник) Целевая аудитория Те, кто хочет «настроить и забыть» через интерфейс Те, кто предпочитает терминал и скорость

Почему для такого проекта Go может быть лучше?

Несмотря на то, что kftray на Rust выглядит очень современно, использование Go для portFwd дает несколько фундаментальных преимуществ в контексте Kubernetes:

  1. Нативная экосистема Kubernetes: Весь Kubernetes (и kubectl) написан на Go. Используя Go, разработчик portFwd применяет те же самые библиотеки (client-go), которые используют создатели K8s. Это гарантирует 100% совместимость с конфигами kubeconfig, контекстами и методами аутентификации.

  2. Стабильность сетевых соединений: В Go работа с сетью и многопоточностью (Goroutines) реализована «из коробки» очень эффективно. Проброс портов — это постоянное ожидание трафика и пересылка пакетов. Горутины позволяют обрабатывать сотни таких соединений с минимальным потреблением памяти и без риска «уронить» поток.

  3. Скорость компиляции и деплоя: Если вам нужно быстро внести правку в логику проброса портов, Go скомпилирует бинарник за секунды. Rust (особенно с тяжелым Tauri/GUI) собирается значительно дольше.

  4. Размер и простота: Для системной утилиты, которая должна просто «перекидывать байты» из кластера на локальную машину, Go предлагает более простой и читаемый код. В Rust-проекте (как kftray) много времени уходит на управление памятью и согласование типов интерфейса, в то время как в Go-проекте фокус остается на сетевой логике.

Плюсы portFwd (на Go)

  • Минимализм: Идеально подходит для автоматизации и скриптов.

  • Низкий порог входа: Если вы захотите доработать инструмент под себя, разобраться в коде на Go будет в разы проще, чем в Rust-коде с GUI-обвязкой.

  • Работа с контекстами: Go-библиотеки лучше всего справляются с переключением между десятками кластеров и сложными методами SSO-логина в облака (AWS/GCP/Azure).

Плюсы kftray (на Rust)

  • Визуальный комфорт: Если у вас 20+ портов, управлять ими через иконку в трее удобнее, чем держать открытыми 5 вкладок терминала.

  • Безопасность памяти: Rust исключает целый класс ошибок сегментации, что важно для долгоживущих фоновых процессов.

Итог

Если вам нужен инструмент для ежедневной рутины с красивыми кнопками — выбирайте kftray. Если вам нужна надежная, быстрая и легкая утилита, которая работает так же, как сам Kubernetes — portFwd на Go будет более естественным и предсказуемым выбором.

Теория: как работает port-forward в Kubernetes

Прежде чем писать реализацию, важно понять, как port-forward работает под капотом. Без этого понимания легко написать код, который будет падать в неожиданных местах.

Архитектура соединения

Когда вы выполняете kubectl port-forward pod/nginx 8080:80, данные проходят через несколько компонентов (см. рис. 1). Клиент устанавливает соединение с API Server, который проксирует запрос на Kubelet ноды, где запущен под. Kubelet, в свою очередь, использует nsenter для доступа к network namespace контейнера и пересылает данные процессу внутри.

рис. 1: Архитектура port-forward в Kubernetes

Протокол SPDY

Для мультиплексирования потоков Kubernetes использует протокол SPDY — предшественник HTTP/2. Это позволяет передавать несколько потоков данных через одно TCP-соединение. Процесс установки соединения выглядит так:

  1. Клиент отправляет HTTP POST запрос на эндпоинт /api/v1/namespaces/{ns}/pods/{pod}/portforward

  2. В заголовке указывается Upgrade: SPDY/3.1, что инициирует переключение протокола

  3. API Server устанавливает SPDY-соединение и создаёт потоки для данных и ошибок

  4. Kubelet получает запрос и проксирует данные в контейнер

Критический нюанс: Service vs Pod

Это один из самых важных моментов, который я понял не сразу. Хотя Kubernetes API формально поддерживает эндпоинт /services/{service}/portforward, на практике kubectl резолвит сервис в под и подключается напрямую к поду.

Почему так? Потому что port-forward работает на уровне конкретного контейнера через Kubelet, а не через механизм балансировки kube-proxy. Это значит, что нам тоже придётся находить backing pod для сервиса и резолвить targetPort.

Архитектура приложения

После изучения теории я спроектировал архитектуру PortFwd. Приложение разделено на несколько слоёв, каждый из которых отвечает за свою область.

Слой Kubernetes (k8s/client.go)

Этот компонент инкапсулирует всю работу с Kubernetes API. Он отвечает за получение списка namespace'ов, подов и сервисов, а также за резолвинг сервисов в поды. Использует официальную библиотеку client-go.

Менеджер соединений (portforward/manager.go)

Центральный компонент, который управляет жизненным циклом всех port-forward соединений. Он создаёт SPDY-транспорт, отслеживает статус каждого соединения, обрабатывает ошибки и уведомляет UI об изменениях через callback.

Слой UI (ui/app.go, views.go, styles.go)

Терминальный интерфейс построен на фреймворке Bubble Tea с использованием библиотеки Lipgloss для стилизации. Bubble Tea реализует Elm Architecture: Model (состояние), Update (обработка событий), View (рендеринг).

Конфигурация (config/state.go)

Компонент для сохранения и восстановления сессий. При выходе из приложения текущие соединения сохраняются в YAML-файл, а при следующем запуске — восстанавливаются.

Реализация: работа с Kubernetes API

Инициализация клиента

Для работы с кластером нужно инициализировать клиент. Я использовал паттерн из официальных примеров client-go: сначала пробуем получить in-cluster конфиг (если приложение запущено внутри пода), а если не получается — читаем kubeconfig файл.

Ключевой момент — использование clientcmd.BuildConfigFromFlags, которая автоматически учитывает текущий context из kubeconfig. Это позволяет приложению работать с тем же кластером, что и kubectl.

Резолвинг Service в Pod

Когда пользователь выбирает сервис для port-forward, нам нужно найти backing pod. Алгоритм следующий:

  1. Получаем сервис — делаем GET-запрос к API для получения спецификации сервиса

  2. Резолвим targetPort — сервис может иметь port: 80, но контейнер слушает на targetPort: 8000. Нужно использовать именно targetPort

  3. Строим label selector — из поля spec.selector сервиса формируем строку для поиска подов

  4. Находим Running под — получаем список подов по selector и выбираем первый со статусом Running

Обработка Named Ports

Отдельная сложность — именованные порты. Сервис может указывать targetPort: http вместо числа. В этом случае нужно найти порт с таким именем в спецификации контейнера пода. Без этой обработки приложение будет пытаться подключиться к неправильному порту.

Это была одна из главных граблей в разработке. Я потратил несколько часов, разбираясь, почему соединение отказывает, пока не понял, что приложение стучится в порт 80, а процесс слушает на 8000.

Реализация: SPDY port-forward

Создание транспорта

Для установки port-forward соединения используется несколько компонентов из client-go:

  • spdy.RoundTripperFor — создаёт HTTP transport с поддержкой SPDY upgrade

  • spdy.NewDialer — создаёт dialer, который умеет устанавливать SPDY-соединения

  • portforward.NewOnAddresses — собственно создаёт port-forwarder

Важный момент: я использую NewOnAddresses с параметром []string{"127.0.0.1"}, а не стандартный New. Это заставляет слушать только на IPv4. По умолчанию forwarder слушает и на IPv4, и на IPv6, что на некоторых системах (особенно macOS) вызывает проблемы с dual-stack.

Управление жизненным циклом

Каждое соединение имеет несколько каналов для управления:

  • stopChan — сигнал остановки, закрытие этого канала прерывает ForwardPorts

  • readyChan — сигнал готовности, сообщает что туннель установлен

  • context с cancelFunc — для graceful shutdown

При запуске соединения мы ждём либо сигнала готовности (соединение установлено), либо ошибки, либо таймаута (30 секунд). После установки соединения переходим в режим ожидания завершения.

Реализация: TUI на Bubble Tea

Почему Bubble Tea?

Bubble Tea от Charm — это фреймворк для построения терминальных интерфейсов на Go, вдохновлённый Elm Architecture. Он предоставляет чистую модель программирования:

  • Model — иммутабельное состояние приложения (текущий view, список соединений, выбранный элемент)

  • Update — чистая функция, которая принимает сообщение и возвращает новое состояние

  • View — чистая функция, которая рендерит состояние в строку для терминала

Этот подход делает код предсказуемым и легко тестируемым. Состояние всегда консистентно, потому что изменяется только через Update.

Стилизация с Lipgloss

Для визуального оформления я использую Lipgloss — библиотеку для стилизации терминального вывода. Она позволяет задавать цвета, отступы, границы, выравнивание — всё, что нужно для красивого интерфейса.

Я выбрал цветовую схему в стиле киберпанка: неоновый зелёный для активных соединений, красный для ошибок, жёлтый для предупреждений. Это делает статусы соединений мгновенно различимыми.

Связь UI и Manager

Менеджер соединений работает асинхронно — соединения устанавливаются и падают в фоне. Чтобы UI узнавал об изменениях, я использую callback-паттерн. При инициализации UI устанавливает callback в менеджере, и при любом изменении состояния соединения менеджер вызывает этот callback, который отправляет сообщение в Bubble Tea.

Реализация: сохранение состояния

Зачем это нужно

Одна из главных фич PortFwd — сохранение сессий между запусками. Вы настроили 5 port-forward соединений, закрыли приложение, а при следующем запуске — все соединения автоматически восстанавливаются.

Формат хранения

Состояние сохраняется в YAML-файл по пути ~/.config/portfwd/state.yaml. Для каждого соединения сохраняются: namespace, тип ресурса (pod или service), имя ресурса, локальный и удалённый порты, и флаг wasActive — было ли соединение активно при сохранении.

Флаг wasActive важен: если пользователь вручную остановил соединение перед выходом, при следующем запуске оно должно остаться остановленным, а не переподключаться автоматически.

Логика восстановления

При запуске приложение читает файл состояния и для каждого сохранённого соединения проверяет:

  1. Если wasActive: false — добавляем как остановленное, не подключаемся

  2. Если wasActive: true — проверяем доступность ресурса (существует ли под/сервис)

  3. Если ресурс доступен — автоматически переподключаемся

  4. Если ресурс недоступен — добавляем как остановленное с ошибкой

Грабли, на которые я наступил

Эта секция — самая ценная часть статьи. Здесь собраны реальные проблемы, на которые я потратил часы отладки.

Проблема 1: Зависание при выходе

Симптом: после нажатия q приложение не завершается, висит бесконечно.

Причина: callback onChange вызывает program.Send() в Bubble Tea. После вызова tea.Quit программа закрывает канал сообщений, и Send() блокируется навечно, ожидая возможности отправить сообщение.

Решение: отключать callback до остановки соединений. Сначала делаем m.onChange = nil, потом останавливаем соединения. Тогда при изменении состояния соединения callback не вызывается и deadlock не возникает.

Проблема 2: connection refused при подключении к сервису

Симптом: при port-forward к сервису получаем ошибку connection refused внутри контейнера.

Причина: я использовал port сервиса (например, 80) вместо targetPort (например, 8000). Приложение в контейнере слушало на 8000, а мы стучались в 80.

Решение: полный резолвинг targetPort, включая обработку named ports. Нужно всегда использовать targetPort, а не port сервиса.

Проблема 3: panic при повторном закрытии канала

Симптом: panic: close of closed channel при быстром двойном нажатии на «Stop».

Причина: канал stopChan закрывается дважды. В Go закрытие уже закрытого канала вызывает panic.

Решение: использовать sync.Once для защиты операции закрытия. Once гарантирует, что функция выполнится только один раз, даже при конкурентных вызовах.

Проблема 4: IPv6 connection refused

Симптом: на некоторых системах получаем ошибку IPv6 dial tcp6 [::1]:80: connection refused.

Причина: по умолчанию port-forwarder слушает и на IPv4, и на IPv6. На системах с определёнными сетевыми настройками это вызывает проблемы.

Решение: явно указывать только IPv4 через NewOnAddresses с параметром []string{"127.0.0.1"}.

Проблема 5: соединения не восстанавливаются при рестарте

Симптом: при запуске приложения список соединений пустой, хотя файл состояния существует.

Причина: я вызывал saveSessionState() после StopAll(). К моменту сохранения все соединения уже были удалены из менеджера.

Решение: изменить порядок: сначала сохраняем состояние (когда соединения ещё существуют), потом останавливаем их.

Альтернативы, от которых я отказался

WebSocket вместо SPDY: Kubernetes поддерживает оба протокола, но client-go имеет готовую и протестированную реализацию именно для SPDY. Писать свой WebSocket-клиент — лишняя работа без явных преимуществ.

Прямое подключение к Kubelet: Теоретически можно обойти API Server. Но это требует отдельной аутентификации, обхода сетевых ограничений и не даёт никаких преимуществ для нашей задачи.

Тестирование и результаты

Производительность

Я измерил потребление ресурсов PortFwd в сравнении с альтернативами при 5 активных соединениях в режиме простоя:

  • PortFwd: ~30 МБ RAM, ~0.1% CPU

  • Lens: ~500 МБ RAM, ~2% CPU

  • 5 отдельных kubectl: ~100 МБ RAM, ~0.5% CPU

PortFwd потребляет в 15 раз меньше памяти, чем Lens, и запускается мгновенно (менее 100 мс против ~5 секунд у Lens).

Функциональность

  • ✅ Единое окно для всех соединений

  • ✅ Интерактивный выбор: namespace → тип ресурса → pod/service → порты

  • ✅ Автоматический резолвинг targetPort для сервисов

  • ✅ Сохранение и восстановление сессий между запусками

  • ✅ Отдельные логи для каждого соединения

  • ✅ Graceful shutdown без zombie-процессов

  • ✅ Справка по горячим клавишам

Горячие клавиши

  • ↑/↓ или j/k — навигация по списку

  • n — создать новое соединение

  • d — отключить выбранное соединение

  • D — отключить все соединения

  • r — переподключить выбранное

  • l — показать логи соединения

  • x — удалить остановленное соединение

  • ? — показать справку

  • q — выход

Заключение

Что получилось

Я создал специализированный инструмент, который решает конкретную проблему — управление множеством port-forward соединений в Kubernetes. PortFwd легковесный, быстрый и делает одну вещь хорошо.

Что можно улучшить

  • Профили — сохранение наборов соединений для разных окружений (dev, staging, prod) с быстрым переключением

  • Multi-cluster — работа с несколькими кластерами одновременно в одном окне

  • Auto-reconnect — автоматическое переподключение при потере связи без участия пользователя

  • Import — импорт соединений из kubectl команд или YAML-манифестов

Уроки, которые я извлёк

  1. Читай исходники kubectl — это лучшая документация по работе с Kubernetes API. Официальная документация не покрывает многие нюансы.

  2. Тестируй на разных системах — dual-stack IPv4/IPv6 ведёт себя по-разному на Linux и macOS. То, что работает у тебя, может сломаться у пользователя.

  3. sync.Once — твой друг — каналы в Go закрываются только один раз, и это легко забыть при конкурентном доступе.

  4. Порядок операций критичен — особенно при graceful shutdown. Сначала сохраняй состояние, потом останавливай процессы.

Полезные ссылки


Буду рад звёздам на GitHub, issue с багами и pull request'ам с улучшениями. Спасибо за внимание!

Показать полностью
11
Вопрос из ленты «Эксперты»

Разработчики приложений для Android, подскажите

Собственно нужная подсказка, или пинок в нужном направлении. Уверен, что здесь есть знающие люди.

И так, задача. У меня давно появилась потребность в одном приложении на телефон. Назовем его "калькулятор". Для работы. Часто бывает, что клиенты обращаются с запросом стоимости изделий именно в тот момент когда я нахожусь далеко от компа. На стационарном компе, в мастерской, у меня есть просто экселевский файл с исходными данными и формулами для расчета, в котором я считаю стоимость изделий. На телефоне с этим сложнее, существенно. Я конечно так же скопировал на него этот самый файл, но эксель на телефоне это то еще извращение. В общем крайне неудобно.

Решение этой задачи. Задумался я над созданием решения данной проблемы. Первый вариант, который я видел, это создать страничку в интернете (написать на РНР код этого "калькулятора") и разместить ее на хосте, где у меня сайт расположен. Вроде бы просто, но в дороге часто не везде есть инет, поэтому решение так себе. Второй вариант - написать приложение на телефон. Ну что, сказано - сделано. Вернее решено сделать. Два дня я грыз теорию. Накачал кучу приложений, фреймворков и прочего. Всё установлено, вроде бы даже настроено по инструкции.
Что попробовал: Cordova. По инструкциям - всё просто и легко. На деле нихрена не работает от слова "совсем". Expo. Почти аналогично. Почти работает, но без особого результата. React Native. Создал приложение. Тестируется, работает локально на компе. Прям всё что надо! И КАК надо. Дальше надо его на телефон скомпилировать и установить. А тут все пути сходятся к Android Studio (AS). И вот там-то самая беда. После трех дней сражений с компом, я наконец-то победил этот AS. Даже виртуальное устройство запускается, правда на холодный запуск только срабатывает. Пытаюсь скомпилировать и запустить эмулятор, AS зависает в бесконечной попытке запустить AVD. В общем результата нет. Само приложение для телефона в формате APK создать не могу (((
Перечитал кучу форумов, инструкций, просмотрел кучу видеороликов (и не только русских). Везде все просто, но на деле НЕ РАБОТАЕТ!

Приложение не публичное, исключительно ДЛЯ СЕБЯ. Публиковать его на всяких там Плеях не собираюсь ни разу.
Заказывать разработку данного приложения на стороне - маразм. Ибо потребность несоизмерима со стоимостью.
Код созданного приложения рабочий (локально всё работает). В коде, пусть и не на профессиональном уровне, но разбираюсь (JS, CSS, HTML - этого достаточно для данной задачи). Да и само приложение до безобразия простое. Там кода-то строк 200 не больше. Код не оптимизирован, для лучшего понимания.

Знающие люди, кто имеет реальный опыт разработки приложений для Android, подскажите в какую сторону копать? Какие программы (и т.п.) используете? Ну или краткое описание сборок "тут создаем, тут тестируем, тут компилируем, тут собираем и загружаем". Дальше думаю разберусь. Благодарен за любую помощь (подсказку, ссылку, направление, наставление).

PS: скачал и установил последние версии node 25.2.1, Git 2.52.0, JDK 8u231, Android Studio 2025.2.3.9 (SDK и AVD стоит), для написания кода использую Visual Studio Code.

Показать полностью
7

Написал умный подборщик подарков на Python, потому что сам не умею их выбирать

Привет! Я учусь в 9 классе, и выбор подарков для меня это всегда головная боль. Гугл выдает старые подборки, а маркетплейсы просто суют рандомные товары.
Решил автоматизировать этот процесс, чтобы система сама думала за меня.

За пару выходных собрал пет-проект NeuroGifter.

Стек:
Выбрал классику для веба на Python:

  • Бэкенд: Flask.

  • База данных: SQLite.

  • AI: API текстовой нейросети (LLM).

Архитектура (Как это работает):
Я не хотел, чтобы пользователь каждый раз ждал 15 секунд ответа от нейросети. Поэтому реализовал гибридную схему:

  1. Кэширование: Скрипт сначала проверяет локальную базу. Если кто-то уже искал подарок по таким параметрам (например, "для геймера, 15 лет"), сайт мгновенно выдает сохраненные варианты.

  2. Генерация: Если в базе пусто, запрос летит к LLM. Она придумывает идеи, и они тут же сохраняются в базу для будущих пользователей.

  3. JSON-структура: Самым сложным было заставить нейронку выдавать данные в чистом JSON без лишнего текста, чтобы Python мог их распарсить и подставить цены.

Фича «На весь мир»:
Решил добавить поддержку двух языков. Сайт определяет регион (или переключается кнопкой):

  • RU: Ищет товары и формирует ссылки на Яндекс.Маркет.

  • EN: Меняет промпты на английские и ведет поиск на Amazon.

Фронтенд:
Верстка на Tailwind. Дизайн минималистичный, главное было сделать адаптив под мобильные устройства и приятные анимации загрузки.

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

Кому интересно потестить, как нейронка справляется с запросами, или попробовать положить мой сервер нагрузкой вот ссылка на живое демо:
NeuroGifter | AI Gift Finder

Буду рад конструктивной критике архитектуры и логики работы!

Показать полностью 1
0

Андроид разработчики, нужна помощь

Серия Пилю приложуху по уходу за котами и цветами.

Пилю по тихой пет проект (первый в жизни) на Котлин.

И хотя в разработке, мягко говоря, не новичок (бекенд чуть более 20 лет опыта), андроид ставит в тупик местами. Но все понемногу разбираю.

Но...

Добавил смену языков.

Стринги (те что делают лицо андроида зеленым) наделал для каждой локали.

Вроде все как надо.

Нормально переключилось на сяоми, 13.

Нормально переключилось на сяоми, 13.

Но переключение интерфейса - не всегда удачное .

Тестирую на эмуляторе, на своих устройствах - переключается. Пользователи пробуют - и с некоторой долей вероятности интерес не переключается.

Точно фиксируется проблема на сяоми 14т, и редми 10с. Может и на других, но с этими пользователями есть связь, могу пробовать с ними.

Уже пару вариантов с попробовал - принудительное обновление активити - та же история.

Куда копать? Уже всю голову сломал. Дипсики и прочие гпт дают варианты, но суть сводят что надо принудительно обновлять активити. А это я во втором релизе сделал. Делу не помогло, зато добавило баг

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

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

Что ещё можно , попробовать? Куда копать?

Проблема - сяоми, судя по всему не только у меня. Притом у меня стоит календарик - на каденалрике меняется корректно все. А вот в интерфейсе - Бяда Бяда.

Помогите пожалуйста, что ещё можно попробовать для корректной смены языка интерфейса. Ссылка на приложуху в коммент добавлю ну и в профиле у меня есть.

Показать полностью 2

Всем добра)

Наверное, я ожидала ответов в стиле "я работаю с VR, все предложения жду на почту". Но ожидания столкнулись с реальностью))

Спасибо и за критику и за адекватность)

Будьте добрее и не спешите с обвинениями, не убедившись в них)

Всё ещё верю что есть программисты деловые, а не вот это вот всё. Удачи!

Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества