Add explicit types and improve type safety across codebase
This commit adds explicit type annotations to variables, function parameters, and return types throughout the codebase, particularly in widget trees, Bloc logic, and repository implementations. The changes improve code readability, maintainability, and type safety, and align with Dart best practices. No business logic was changed.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
||||
import 'package:firebase_data_connect/src/core/ref.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
import 'package:krow_domain/krow_domain.dart' as domain;
|
||||
import '../../domain/repositories/hub_repository_interface.dart';
|
||||
@@ -16,8 +17,8 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
|
||||
@override
|
||||
Future<List<domain.Hub>> getHubs() async {
|
||||
final business = await _getBusinessForCurrentUser();
|
||||
final teamId = await _getOrCreateTeamId(business);
|
||||
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
|
||||
final String teamId = await _getOrCreateTeamId(business);
|
||||
return _fetchHubsForTeam(teamId: teamId, businessId: business.id);
|
||||
}
|
||||
|
||||
@@ -26,11 +27,11 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
required String name,
|
||||
required String address,
|
||||
}) async {
|
||||
final business = await _getBusinessForCurrentUser();
|
||||
final teamId = await _getOrCreateTeamId(business);
|
||||
final city = business.city;
|
||||
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
|
||||
final String teamId = await _getOrCreateTeamId(business);
|
||||
final String? city = business.city;
|
||||
|
||||
final result = await _dataConnect
|
||||
final OperationResult<dc.CreateTeamHubData, dc.CreateTeamHubVariables> result = await _dataConnect
|
||||
.createTeamHub(
|
||||
teamId: teamId,
|
||||
hubName: name,
|
||||
@@ -38,17 +39,17 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
)
|
||||
.city(city?.isNotEmpty == true ? city : '')
|
||||
.execute();
|
||||
final createdId = result.data?.teamHub_insert.id;
|
||||
final String? createdId = result.data?.teamHub_insert.id;
|
||||
if (createdId == null) {
|
||||
throw Exception('Hub creation failed.');
|
||||
}
|
||||
|
||||
final hubs = await _fetchHubsForTeam(
|
||||
final List<domain.Hub> hubs = await _fetchHubsForTeam(
|
||||
teamId: teamId,
|
||||
businessId: business.id,
|
||||
);
|
||||
domain.Hub? createdHub;
|
||||
for (final hub in hubs) {
|
||||
for (final domain.Hub hub in hubs) {
|
||||
if (hub.id == createdId) {
|
||||
createdHub = hub;
|
||||
break;
|
||||
@@ -79,8 +80,8 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
}
|
||||
|
||||
Future<dc.GetBusinessesByUserIdBusinesses> _getBusinessForCurrentUser() async {
|
||||
final session = dc.ClientSessionStore.instance.session;
|
||||
final cachedBusiness = session?.business;
|
||||
final dc.ClientSession? session = dc.ClientSessionStore.instance.session;
|
||||
final dc.ClientBusinessSession? cachedBusiness = session?.business;
|
||||
if (cachedBusiness != null) {
|
||||
return dc.GetBusinessesByUserIdBusinesses(
|
||||
id: cachedBusiness.id,
|
||||
@@ -103,12 +104,12 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
);
|
||||
}
|
||||
|
||||
final user = _firebaseAuth.currentUser;
|
||||
final firebase.User? user = _firebaseAuth.currentUser;
|
||||
if (user == null) {
|
||||
throw Exception('User is not authenticated.');
|
||||
}
|
||||
|
||||
final result = await _dataConnect.getBusinessesByUserId(
|
||||
final QueryResult<dc.GetBusinessesByUserIdData, dc.GetBusinessesByUserIdVariables> result = await _dataConnect.getBusinessesByUserId(
|
||||
userId: user.uid,
|
||||
).execute();
|
||||
if (result.data.businesses.isEmpty) {
|
||||
@@ -116,7 +117,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
throw Exception('No business found for this user. Please sign in again.');
|
||||
}
|
||||
|
||||
final business = result.data.businesses.first;
|
||||
final dc.GetBusinessesByUserIdBusinesses business = result.data.businesses.first;
|
||||
if (session != null) {
|
||||
dc.ClientSessionStore.instance.setSession(
|
||||
dc.ClientSession(
|
||||
@@ -140,14 +141,14 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
Future<String> _getOrCreateTeamId(
|
||||
dc.GetBusinessesByUserIdBusinesses business,
|
||||
) async {
|
||||
final teamsResult = await _dataConnect.getTeamsByOwnerId(
|
||||
final QueryResult<dc.GetTeamsByOwnerIdData, dc.GetTeamsByOwnerIdVariables> teamsResult = await _dataConnect.getTeamsByOwnerId(
|
||||
ownerId: business.id,
|
||||
).execute();
|
||||
if (teamsResult.data.teams.isNotEmpty) {
|
||||
return teamsResult.data.teams.first.id;
|
||||
}
|
||||
|
||||
final createTeamBuilder = _dataConnect.createTeam(
|
||||
final dc.CreateTeamVariablesBuilder createTeamBuilder = _dataConnect.createTeam(
|
||||
teamName: '${business.businessName} Team',
|
||||
ownerId: business.id,
|
||||
ownerName: business.contactName ?? '',
|
||||
@@ -157,8 +158,8 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
createTeamBuilder.email(business.email);
|
||||
}
|
||||
|
||||
final createTeamResult = await createTeamBuilder.execute();
|
||||
final teamId = createTeamResult.data?.team_insert.id;
|
||||
final OperationResult<dc.CreateTeamData, dc.CreateTeamVariables> createTeamResult = await createTeamBuilder.execute();
|
||||
final String? teamId = createTeamResult.data?.team_insert.id;
|
||||
if (teamId == null) {
|
||||
throw Exception('Team creation failed.');
|
||||
}
|
||||
@@ -170,13 +171,13 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
required String teamId,
|
||||
required String businessId,
|
||||
}) async {
|
||||
final hubsResult = await _dataConnect.getTeamHubsByTeamId(
|
||||
final QueryResult<dc.GetTeamHubsByTeamIdData, dc.GetTeamHubsByTeamIdVariables> hubsResult = await _dataConnect.getTeamHubsByTeamId(
|
||||
teamId: teamId,
|
||||
).execute();
|
||||
|
||||
return hubsResult.data.teamHubs
|
||||
.map(
|
||||
(hub) => domain.Hub(
|
||||
(dc.GetTeamHubsByTeamIdTeamHubs hub) => domain.Hub(
|
||||
id: hub.id,
|
||||
businessId: businessId,
|
||||
name: hub.hubName,
|
||||
|
||||
@@ -16,5 +16,5 @@ class AssignNfcTagArguments extends UseCaseArgument {
|
||||
const AssignNfcTagArguments({required this.hubId, required this.nfcTagId});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [hubId, nfcTagId];
|
||||
List<Object?> get props => <Object?>[hubId, nfcTagId];
|
||||
}
|
||||
|
||||
@@ -16,5 +16,5 @@ class CreateHubArguments extends UseCaseArgument {
|
||||
const CreateHubArguments({required this.name, required this.address});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [name, address];
|
||||
List<Object?> get props => <Object?>[name, address];
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ class DeleteHubArguments extends UseCaseArgument {
|
||||
const DeleteHubArguments({required this.hubId});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [hubId];
|
||||
List<Object?> get props => <Object?>[hubId];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_domain/src/entities/business/hub.dart';
|
||||
import '../../domain/arguments/assign_nfc_tag_arguments.dart';
|
||||
import '../../domain/arguments/create_hub_arguments.dart';
|
||||
import '../../domain/arguments/delete_hub_arguments.dart';
|
||||
@@ -64,7 +65,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
|
||||
) async {
|
||||
emit(state.copyWith(status: ClientHubsStatus.loading));
|
||||
try {
|
||||
final hubs = await _getHubsUseCase();
|
||||
final List<Hub> hubs = await _getHubsUseCase();
|
||||
emit(state.copyWith(status: ClientHubsStatus.success, hubs: hubs));
|
||||
} catch (e) {
|
||||
emit(
|
||||
@@ -85,7 +86,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
|
||||
await _createHubUseCase(
|
||||
CreateHubArguments(name: event.name, address: event.address),
|
||||
);
|
||||
final hubs = await _getHubsUseCase();
|
||||
final List<Hub> hubs = await _getHubsUseCase();
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: ClientHubsStatus.actionSuccess,
|
||||
@@ -111,7 +112,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
|
||||
emit(state.copyWith(status: ClientHubsStatus.actionInProgress));
|
||||
try {
|
||||
await _deleteHubUseCase(DeleteHubArguments(hubId: event.hubId));
|
||||
final hubs = await _getHubsUseCase();
|
||||
final List<Hub> hubs = await _getHubsUseCase();
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: ClientHubsStatus.actionSuccess,
|
||||
@@ -138,7 +139,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
|
||||
await _assignNfcTagUseCase(
|
||||
AssignNfcTagArguments(hubId: event.hubId, nfcTagId: event.nfcTagId),
|
||||
);
|
||||
final hubs = await _getHubsUseCase();
|
||||
final List<Hub> hubs = await _getHubsUseCase();
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: ClientHubsStatus.actionSuccess,
|
||||
|
||||
@@ -6,7 +6,7 @@ abstract class ClientHubsEvent extends Equatable {
|
||||
const ClientHubsEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
List<Object?> get props => <Object?>[];
|
||||
}
|
||||
|
||||
/// Event triggered to fetch the list of hubs.
|
||||
@@ -22,7 +22,7 @@ class ClientHubsAddRequested extends ClientHubsEvent {
|
||||
const ClientHubsAddRequested({required this.name, required this.address});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [name, address];
|
||||
List<Object?> get props => <Object?>[name, address];
|
||||
}
|
||||
|
||||
/// Event triggered to delete a hub.
|
||||
@@ -32,7 +32,7 @@ class ClientHubsDeleteRequested extends ClientHubsEvent {
|
||||
const ClientHubsDeleteRequested(this.hubId);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [hubId];
|
||||
List<Object?> get props => <Object?>[hubId];
|
||||
}
|
||||
|
||||
/// Event triggered to assign an NFC tag to a hub.
|
||||
@@ -46,7 +46,7 @@ class ClientHubsNfcTagAssignRequested extends ClientHubsEvent {
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [hubId, nfcTagId];
|
||||
List<Object?> get props => <Object?>[hubId, nfcTagId];
|
||||
}
|
||||
|
||||
/// Event triggered to clear any error or success messages.
|
||||
@@ -61,7 +61,7 @@ class ClientHubsAddDialogToggled extends ClientHubsEvent {
|
||||
const ClientHubsAddDialogToggled({required this.visible});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [visible];
|
||||
List<Object?> get props => <Object?>[visible];
|
||||
}
|
||||
|
||||
/// Event triggered to toggle the visibility of the "Identify NFC" dialog.
|
||||
@@ -71,5 +71,5 @@ class ClientHubsIdentifyDialogToggled extends ClientHubsEvent {
|
||||
const ClientHubsIdentifyDialogToggled({this.hub});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [hub];
|
||||
List<Object?> get props => <Object?>[hub];
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class ClientHubsState extends Equatable {
|
||||
|
||||
const ClientHubsState({
|
||||
this.status = ClientHubsStatus.initial,
|
||||
this.hubs = const [],
|
||||
this.hubs = const <Hub>[],
|
||||
this.errorMessage,
|
||||
this.successMessage,
|
||||
this.showAddHubDialog = false,
|
||||
@@ -57,7 +57,7 @@ class ClientHubsState extends Equatable {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
List<Object?> get props => <Object?>[
|
||||
status,
|
||||
hubs,
|
||||
errorMessage,
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:krow_domain/src/entities/business/hub.dart';
|
||||
import '../blocs/client_hubs_bloc.dart';
|
||||
import '../blocs/client_hubs_event.dart';
|
||||
import '../blocs/client_hubs_state.dart';
|
||||
@@ -23,10 +24,10 @@ class ClientHubsPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<ClientHubsBloc>(
|
||||
create: (context) =>
|
||||
create: (BuildContext context) =>
|
||||
Modular.get<ClientHubsBloc>()..add(const ClientHubsFetched()),
|
||||
child: BlocConsumer<ClientHubsBloc, ClientHubsState>(
|
||||
listener: (context, state) {
|
||||
listener: (BuildContext context, ClientHubsState state) {
|
||||
if (state.errorMessage != null) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
@@ -44,7 +45,7 @@ class ClientHubsPage extends StatelessWidget {
|
||||
).add(const ClientHubsMessageCleared());
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
builder: (BuildContext context, ClientHubsState state) {
|
||||
return Scaffold(
|
||||
backgroundColor: UiColors.bgMenu,
|
||||
floatingActionButton: FloatingActionButton(
|
||||
@@ -67,7 +68,7 @@ class ClientHubsPage extends StatelessWidget {
|
||||
vertical: UiConstants.space5,
|
||||
).copyWith(bottom: 100),
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
delegate: SliverChildListDelegate(<Widget>[
|
||||
if (state.status == ClientHubsStatus.loading)
|
||||
const Center(child: CircularProgressIndicator())
|
||||
else if (state.hubs.isEmpty)
|
||||
@@ -79,9 +80,9 @@ class ClientHubsPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
else ...<Widget>[
|
||||
...state.hubs.map(
|
||||
(hub) => HubCard(
|
||||
(Hub hub) => HubCard(
|
||||
hub: hub,
|
||||
onNfcPressed: () =>
|
||||
BlocProvider.of<ClientHubsBloc>(
|
||||
@@ -105,7 +106,7 @@ class ClientHubsPage extends StatelessWidget {
|
||||
),
|
||||
if (state.showAddHubDialog)
|
||||
AddHubDialog(
|
||||
onCreate: (name, address) {
|
||||
onCreate: (String name, String address) {
|
||||
BlocProvider.of<ClientHubsBloc>(context).add(
|
||||
ClientHubsAddRequested(name: name, address: address),
|
||||
);
|
||||
@@ -117,7 +118,7 @@ class ClientHubsPage extends StatelessWidget {
|
||||
if (state.hubToIdentify != null)
|
||||
IdentifyNfcDialog(
|
||||
hub: state.hubToIdentify!,
|
||||
onAssign: (tagId) {
|
||||
onAssign: (String tagId) {
|
||||
BlocProvider.of<ClientHubsBloc>(context).add(
|
||||
ClientHubsNfcTagAssignRequested(
|
||||
hubId: state.hubToIdentify!.id,
|
||||
@@ -159,7 +160,7 @@ class ClientHubsPage extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
GestureDetector(
|
||||
onTap: () => Modular.to.pop(),
|
||||
child: Container(
|
||||
|
||||
@@ -51,14 +51,14 @@ class _AddHubDialogState extends State<AddHubDialog> {
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
boxShadow: const [
|
||||
boxShadow: const <BoxShadow>[
|
||||
BoxShadow(color: UiColors.popupShadow, blurRadius: 20),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.client_hubs.add_hub_dialog.title,
|
||||
style: UiTypography.headline3m.textPrimary,
|
||||
@@ -83,7 +83,7 @@ class _AddHubDialogState extends State<AddHubDialog> {
|
||||
),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: UiButton.secondary(
|
||||
onPressed: widget.onCancel,
|
||||
|
||||
@@ -31,7 +31,7 @@ class HubCard extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
boxShadow: const [
|
||||
boxShadow: const <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: UiColors.popupShadow,
|
||||
blurRadius: 10,
|
||||
@@ -42,7 +42,7 @@ class HubCard extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
child: Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 52,
|
||||
height: 52,
|
||||
@@ -60,13 +60,13 @@ class HubCard extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(hub.name, style: UiTypography.body1b.textPrimary),
|
||||
if (hub.address.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: UiConstants.space1),
|
||||
child: Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
UiIcons.mapPin,
|
||||
size: 12,
|
||||
@@ -99,7 +99,7 @@ class HubCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
onPressed: onDeletePressed,
|
||||
icon: const Icon(
|
||||
|
||||
@@ -17,7 +17,7 @@ class HubEmptyState extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgBanner,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
boxShadow: const [
|
||||
boxShadow: const <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: UiColors.popupShadow,
|
||||
blurRadius: 10,
|
||||
@@ -26,7 +26,7 @@ class HubEmptyState extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 64,
|
||||
height: 64,
|
||||
|
||||
@@ -17,13 +17,13 @@ class HubInfoCard extends StatelessWidget {
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.nfc, size: 20, color: UiColors.primary),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.client_hubs.about_hubs.title,
|
||||
style: UiTypography.body2b.textPrimary,
|
||||
|
||||
@@ -48,13 +48,13 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
boxShadow: const [
|
||||
boxShadow: const <BoxShadow>[
|
||||
BoxShadow(color: UiColors.popupShadow, blurRadius: 20),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.client_hubs.nfc_dialog.title,
|
||||
style: UiTypography.headline3m.textPrimary,
|
||||
@@ -87,7 +87,7 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
|
||||
text: t.client_hubs.nfc_dialog.scan_button,
|
||||
leadingIcon: UiIcons.nfc,
|
||||
),
|
||||
if (_nfcTagId != null) ...[
|
||||
if (_nfcTagId != null) ...<Widget>[
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
@@ -98,10 +98,10 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
UiIcons.success,
|
||||
size: 20,
|
||||
@@ -141,7 +141,7 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
|
||||
],
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: UiButton.secondary(
|
||||
onPressed: widget.onCancel,
|
||||
|
||||
Reference in New Issue
Block a user