fl-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 المهني
Behavioral guidelines for Flutter base tasks: clarify ambiguity, keep changes simple and surgical, and define verifiable success criteria before coding.
Scaffolds a new feature module under apps/main/lib/presentation/modules using the bundled module generator
Reviews UI-layer changes — screens, blocs, widgets, routes — against the template's StateBase + CoreBlocBase + fl_theme conventions
Awareness index of every reusable widget in fl_ui, fl_theme, fl_media, and core's common_widget — name, one-line purpose, when to reach for it instead of writing a new one
Builds the data layer with Freezed DTOs, Retrofit clients, the storage-seam local data manager, and repositories wired through injectable
Teaches and applies Flutter/Dart dependency injection with Injectable + GetIt, grounded in this repo's Clean Architecture and code generation conventions. Use when changing DI wiring, adding BLoCs/use cases/repositories/modules, using @Named/@preResolve/@factoryParam/env registrations, reviewing DI best practices, or setting up DI tests.
| name | fl-extension-action |
| description | Extracts screen handlers and bloc listeners into a part-of "*.action.dart" extension file |
| license | MIT |
| 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/generated/app_localizations.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;
late AppLocalizations trans;
@override
Widget build(BuildContext context) {
_themeData = context.theme;
trans = translate(context);
return BlocListener<FeatureBloc, FeatureState>(
listener: _blocListener,
child: ScreenForm(
title: trans.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.