import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../web/application/mall_web_host_controller.dart'; import 'mall_tab_config.dart'; enum MallEntryOpenResult { opened, unavailable, failed, alreadyOpening } class MallEntryController { MallEntryController(this._ref); final Ref _ref; bool _opening = false; Future open( BuildContext context, { MallTabConfig? initialConfig, }) async { if (_opening) return MallEntryOpenResult.alreadyOpening; _opening = true; try { var config = initialConfig; if (config?.isVisible != true) { config = await _ref.read(mallTabConfigProvider.notifier).ensureLoaded(); } if (config?.isVisible != true || !context.mounted) { return MallEntryOpenResult.unavailable; } final clickId = await _ref .read(mallTabConfigProvider.notifier) .recordClick(); if (clickId == null || !context.mounted) { return MallEntryOpenResult.unavailable; } _ref .read(mallClickAttributionProvider.notifier) .state = MallClickAttribution( adId: config!.adId, trackingId: config.trackingId, clickId: clickId, ); final uri = config.attributedUri( clickId: clickId, isDark: Theme.of(context).brightness == Brightness.dark, ); if (uri == null) return MallEntryOpenResult.unavailable; // The bottom mall entry is always resident. Server open-mode metadata is // still retained for attribution, while explicit links inside H5 decide // their own external handoff through the WebView navigation policy. MallWebHostController.instance.open(uri); return MallEntryOpenResult.opened; } catch (_) { return MallEntryOpenResult.failed; } finally { _opening = false; } } } final mallEntryControllerProvider = Provider((ref) => MallEntryController(ref));