Files
jinzhi/lib/features/mall/application/mall_entry_controller.dart
T
2026-09-08 14:27:32 +08:00

63 lines
2.0 KiB
Dart

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<MallEntryOpenResult> open(
BuildContext context, {
MallEntryRequest request = MallEntryRequest.home,
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,
entry: request,
);
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));