Рефакторинг frontend/pweb/lib/pages/payment_methods/page.dart #169

Open
opened 2025-12-25 16:26:27 +00:00 by tech · 0 comments
Owner

1) Убрать провайдеры из build

Что сделать: вынести MultiProvider из PaymentPage.build в отдельный виджет-обёртку PaymentPageScope (или поднять выше по дереву, где роут создаётся).
Зачем: сейчас при каждом rebuild страницы пересоздаётся конфигурация провайдеров → нестабильный lifecycle, лишние перезапуски логики.

Критерий: PaymentPage становится “тонким” UI, а провайдеры создаются один раз на вход в страницу.


2) Никаких side effects в ProxyProvider.update

Что сделать: убрать flow.sync(...) из ChangeNotifierProxyProvider2.update.
Варианты без Riverpod/BLoC:

  • перенести синхронизацию в didChangeDependencies() или в отдельный метод, вызываемый из listener’а на RecipientsProvider/PaymentMethodsProvider;
  • либо сделать PaymentFlowProvider так, чтобы он принимал входы через сеттеры, а sync вызывался явным образом (не в update).

Зачем: update должен только прокидывать зависимости, иначе легко получить циклы notifyListeners() → rebuild → update → sync → notify…

Критерий: в ProxyProvider.update нет вызовов, которые меняют состояние других провайдеров (кроме “set dependencies”).


3) Вычислять availableTypes один раз и без дублирования

Что сделать:

  • вынести _availablePaymentTypes в отдельную чистую функцию/extension;
  • вычислять availableTypes один раз через context.select / Selector (получатель + готовность методов + список методов/фильтрованный список).

Зачем: сейчас маппинг считается несколько раз (и в build, и внутри update), плюс лишние перестроения.

Критерий: один источник правды для availableTypes, нет повторных вызовов в рамках одного билда.


4) Починить автоселект метода по кошельку (по событию “данные готовы”)

Что сделать: _handleWalletAutoSelection не вызывать “после кадра” вслепую.
Сделать listener, который срабатывает один раз при переходе methodsProvider.isReady == true и только если есть selectedWallet.

Минимальный вариант:

  • bool _walletApplied = false;

  • в didChangeDependencies() или через addListener на PaymentMethodsProvider:

    • если !_walletApplied && wallet != null && methodsProvider.isReady → применить и поставить _walletApplied=true.

Зачем: сейчас можно попасть в состояние “кошелёк есть, методы ещё не подгрузились” → автоселект не случится.

Критерий: автоселект срабатывает гарантированно и ровно один раз.


5) Убрать хрупкий матч по description.contains(wallet.walletUserID)

Что сделать: заменить поиск метода для кошелька на структурированное поле.
Варианты:

  • добавить поле walletUserId / walletRef в PaymentMethod.data (лучше);
  • или добавить нормализованный metadata в PaymentMethod, где будет ключ walletUserId.

Зачем: contains по строке — источник тихих багов.

Критерий: _getPaymentMethodForWallet не парсит description.


6) Разделить UI и управляющую логику внутри страницы

Что сделать: вынести обработчики в маленький класс PaymentPageActions (без смены архитектуры), который принимает нужные провайдеры и делает:

  • selectRecipient, clearRecipient, onSearchChanged, send.

Зачем: сейчас State перегружен и смешивает все обязанности.

Критерий: State хранит только контроллеры/фокус и делегирует действия.


7) Снизить количество watch и перестроений

Что сделать: заменить context.watch на context.select там, где нужны конкретные поля:

  • recipientProvider.currentObject
  • methodsProvider.isReady
  • methodsProvider.methods (или уже отфильтрованный список)
  • quotationProvider.isReady
  • flowProvider.selectedType

Зачем: меньше лишних rebuild.

Критерий: изменение не относящихся данных не перерисовывает всю страницу.


Минимальный результат

  • Провайдеры создаются один раз (не в build).
  • ProxyProvider.update не мутирует чужое состояние.
  • Автовыбор кошелька устойчивый.
  • availableTypes не пересчитывается по кругу.
  • Матч кошелька структурный, не строковый.
  • Страница легче читается и проще тестируется.
### 1) Убрать провайдеры из `build` **Что сделать:** вынести `MultiProvider` из `PaymentPage.build` в отдельный виджет-обёртку `PaymentPageScope` (или поднять выше по дереву, где роут создаётся). **Зачем:** сейчас при каждом rebuild страницы пересоздаётся конфигурация провайдеров → нестабильный lifecycle, лишние перезапуски логики. **Критерий:** `PaymentPage` становится “тонким” UI, а провайдеры создаются один раз на вход в страницу. --- ### 2) Никаких side effects в `ProxyProvider.update` **Что сделать:** убрать `flow.sync(...)` из `ChangeNotifierProxyProvider2.update`. Варианты без Riverpod/BLoC: * перенести синхронизацию в `didChangeDependencies()` или в отдельный метод, вызываемый из listener’а на `RecipientsProvider/PaymentMethodsProvider`; * либо сделать `PaymentFlowProvider` так, чтобы он принимал входы через сеттеры, а `sync` вызывался явным образом (не в update). **Зачем:** `update` должен только прокидывать зависимости, иначе легко получить циклы `notifyListeners()` → rebuild → update → sync → notify… **Критерий:** в `ProxyProvider.update` нет вызовов, которые меняют состояние других провайдеров (кроме “set dependencies”). --- ### 3) Вычислять `availableTypes` один раз и без дублирования **Что сделать:** * вынести `_availablePaymentTypes` в отдельную чистую функцию/extension; * вычислять `availableTypes` один раз через `context.select` / `Selector` (получатель + готовность методов + список методов/фильтрованный список). **Зачем:** сейчас маппинг считается несколько раз (и в build, и внутри update), плюс лишние перестроения. **Критерий:** один источник правды для `availableTypes`, нет повторных вызовов в рамках одного билда. --- ### 4) Починить автоселект метода по кошельку (по событию “данные готовы”) **Что сделать:** `_handleWalletAutoSelection` не вызывать “после кадра” вслепую. Сделать listener, который срабатывает один раз при переходе `methodsProvider.isReady == true` и только если есть `selectedWallet`. Минимальный вариант: * `bool _walletApplied = false;` * в `didChangeDependencies()` или через `addListener` на `PaymentMethodsProvider`: * если `!_walletApplied && wallet != null && methodsProvider.isReady` → применить и поставить `_walletApplied=true`. **Зачем:** сейчас можно попасть в состояние “кошелёк есть, методы ещё не подгрузились” → автоселект не случится. **Критерий:** автоселект срабатывает гарантированно и ровно один раз. --- ### 5) Убрать хрупкий матч по `description.contains(wallet.walletUserID)` **Что сделать:** заменить поиск метода для кошелька на структурированное поле. Варианты: * добавить поле `walletUserId` / `walletRef` в `PaymentMethod.data` (лучше); * или добавить нормализованный `metadata` в `PaymentMethod`, где будет ключ `walletUserId`. **Зачем:** `contains` по строке — источник тихих багов. **Критерий:** `_getPaymentMethodForWallet` не парсит `description`. --- ### 6) Разделить UI и управляющую логику внутри страницы **Что сделать:** вынести обработчики в маленький класс `PaymentPageActions` (без смены архитектуры), который принимает нужные провайдеры и делает: * `selectRecipient`, `clearRecipient`, `onSearchChanged`, `send`. **Зачем:** сейчас `State` перегружен и смешивает все обязанности. **Критерий:** `State` хранит только контроллеры/фокус и делегирует действия. --- ### 7) Снизить количество `watch` и перестроений **Что сделать:** заменить `context.watch` на `context.select` там, где нужны конкретные поля: * `recipientProvider.currentObject` * `methodsProvider.isReady` * `methodsProvider.methods` (или уже отфильтрованный список) * `quotationProvider.isReady` * `flowProvider.selectedType` **Зачем:** меньше лишних rebuild. **Критерий:** изменение не относящихся данных не перерисовывает всю страницу. --- ## Минимальный результат * Провайдеры создаются один раз (не в build). * `ProxyProvider.update` не мутирует чужое состояние. * Автовыбор кошелька устойчивый. * `availableTypes` не пересчитывается по кругу. * Матч кошелька структурный, не строковый. * Страница легче читается и проще тестируется.
tech added the frontend label 2025-12-25 16:26:27 +00:00
protuberanets was assigned by tech 2025-12-25 16:26:28 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tech/sendico#169