extension-action
Extracts screen handlers and bloc listeners into a part-of "*.action.dart" extension file
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Extracts screen handlers and bloc listeners into a part-of "*.action.dart" extension file
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Handles cross-feature BusEvent communication with EventBusManager in the Flutter base template
Implements BLoC state management using AppBlocBase, an abstract State hierarchy, and a freezed _StateData
Builds the data layer with Freezed DTOs, Retrofit clients, hive_ce local stores, and repositories wired through injectable
Reviews UI-layer changes — screens, blocs, widgets, routes — against the template's StateBase + AppBlocBase + fl_theme conventions
Adds and updates app strings through the CSV → ARB → generated localizations workflow
Scaffolds a new feature module under apps/main/lib/presentation/modules using the bundled module generator
| name | extension-action |
| description | Extracts screen handlers and bloc listeners into a part-of "*.action.dart" extension file |
| license | MIT |
| compatibility | all |
| metadata | {"audience":"flutter-developers","framework":"flutter","pattern":"extension-action"} |
_blocListener, onRefresh, navigation handlers, or form callbacks to an existing screen.<feature>_screen.dart // UI + state controllers + part 'feature.action.dart';
<feature>.action.dart // part of '<feature>_screen.dart';
// extension on _<Feature>ScreenState { ... }
feature.action.dart (note: dot, not underscore — matches generator output) is one library with the screen, so it can call private members of _<Feature>ScreenState.
<feature>_screen.dart:
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import '../../../../l10n/localization_ext.dart';
import '../../../base/base.dart';
import '../bloc/<feature>_bloc.dart';
part '<feature>.action.dart';
class FeatureScreen extends StatefulWidget {
static String routeName = '/feature';
const FeatureScreen({super.key, this.args});
final FeatureArgs? args;
@override
State<FeatureScreen> createState() => _FeatureScreenState();
}
class _FeatureScreenState extends StateBase<FeatureScreen> {
final _refreshController = RefreshController(initialRefresh: true);
@override
FeatureBloc get bloc => BlocProvider.of(context);
late ThemeData _themeData;
TextTheme get textTheme => _themeData.textTheme;
@override
Widget build(BuildContext context) {
_themeData = context.theme;
return BlocListener<FeatureBloc, FeatureState>(
listener: _blocListener,
child: ScreenForm(
title: l10n.featureTitle,
child: SmartRefresher(
controller: _refreshController,
onRefresh: onRefresh,
child: const FeatureBody(),
),
),
);
}
}
<feature>.action.dart:
part of '<feature>_screen.dart';
extension on _FeatureScreenState {
void _blocListener(BuildContext context, FeatureState state) {
hideLoading();
_refreshController.refreshCompleted();
}
void onRefresh() {
final id = widget.args?.id ?? widget.args?.initial?.id;
if (id != null) {
bloc.add(GetFeatureEvent(id));
}
}
}
Action file (extension):
_blocListener(BuildContext, State) — side effects from state changes (hide loading, complete refresh, show dialog/snackbar, navigate).onRefresh, onLoadMore, onSubmit — handlers passed to widgets.context.goToX(...)).Screen file:
build, sub-Widget _buildX() helpers.initState / dispose.TextEditingController, GlobalKey, RefreshController declarations.bloc getter override.extension on _FeatureScreenState) in generated code; if you prefer a name, use <Feature>Action for greppability.onRefresh) when the screen passes them as callbacks, or private (_handleX) when only used inside the action file.part of line MUST be the first non-comment line of the action file.part 'feature.action.dart'; (note: dot) directive in <feature>_screen.dart.part of '<feature>_screen.dart'; is the first line of the action file._blocListener calls hideLoading() early so the screen-level loading delegate is unstuck on every state change.build logic in the action file.context.goToX calls inside build — keep them in the action file.