build method
Build the internal widget.
The context used during the build is passed as is.
It also inherits WidgetRef for updating the state in ref and is passed FormRef containing information for the form.
内部のウィジェットをビルドします。
ビルド中に使用されるcontextがそのまま渡されます。
また、refに状態を更新するためのWidgetRefを継承し、フォーム用の情報が含まれたFormRefが渡されます。
Implementation
@override
Widget build(BuildContext context, FormRef ref) {
// Describes the process of loading
// and defining variables required for the page.
//
// You can use [ref.isAdding] or [ref.isEditing] to determine if the form is currently adding new data or editing data.
//
// If editing is in progress, it is possible to get the ID of the item being edited with [ref.editId].
final adapter = MasamuneModuleSimpleblogMasamuneAdapter.primary;
final note = ref.select(
onAdd: () => null,
onEdit: (editId) => NoteModel.document(editId).watch(ref)..load(),
);
final user = UserModel.document(adapter.auth.userId).watch(ref)..load();
final controller = NoteModel.form(
note?.value ?? const NoteModel(title: "", text: ""),
).watch(ref);
// Describes the structure of the page.
return UniversalScaffold(
appBar: UniversalAppBar(
leadingWhenDisabledPop: BackButton(
onPressed: () {
adapter.page.index().push(adapter.router);
},
),
title: Text(ref.isAdding
? ml().$(ml().add).of.$(
adapter.option.articleLabel?.value.value(ml.locale) ??
ml().article)
: ml().$(ml().edit).of.$(note?.value?.title)),
actions: [
if (ref.isEditing)
IconButton(
onPressed: () async {
Modal.confirm(
context,
submitText: ml().yes,
cancelText: ml().no,
title: ml().confirmation,
text: ml()
.youWillDelete
.$(adapter.option.articleLabel?.value.value(ml.locale) ??
ml().article)
.onceDeletedItCannotBeUndone,
onSubmit: () async {
try {
await note?.delete().showIndicator(context);
adapter.router.pop();
adapter.router.pop();
} catch (e) {
Modal.alert(
context,
submitText: ml().close,
title: ml().error,
text: ml().$(ml().delete).haveFailed,
);
}
},
);
},
icon: const Icon(Icons.delete),
),
IconButton(
onPressed: () async {
if (!controller.validateAndSave()) {
return;
}
try {
final doc =
note ?? NoteModel.collection().read(adapter.ref).create();
await doc
.save(
ref.isAdding
? controller.value.copyWith(
user: user,
)
: controller.value,
)
.showIndicator(context);
// 追加時のみ送信
if (ref.isAdding) {}
adapter.router.pop();
} catch (e) {
Modal.alert(
context,
submitText: ml().close,
title: ml().error,
text: ml().$(ml().save).haveFailed,
);
}
},
icon: const Icon(Icons.save),
),
],
),
body: SafeArea(
child: UniversalContainer(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
FormLabel(ml().title),
FormTextField(
form: controller,
initialValue: controller.value.title,
onSaved: (value) {
return controller.value.copyWith(title: value);
},
),
FormLabel(ml().dateTime),
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 2,
child: FormDateTimeField(
form: controller,
initialValue: controller.value.time.value,
onSaved: (value) {
return controller.value.copyWith(
time: ModelTimestamp(value),
);
},
),
),
Expanded(
flex: 1,
child: FormEnumDropdownField(
picker: FormEnumDropdownFieldPicker(
values: PublishEnum.values,
labelBuilder: (value) => value?.label ?? "",
),
form: controller,
initialValue: PublishEnum.values
.firstWhereOrNull((e) => e.name == publish) ??
controller.value.publish,
onSaved: (value) =>
controller.value.copyWith(publish: value),
),
),
],
),
FormLabel(ml().content),
Expanded(
child: FormTextField(
form: controller,
minLength: 10,
expands: true,
keyboardType: TextInputType.multiline,
style:
const FormStyle(textAlignVertical: TextAlignVertical.top),
initialValue: controller.value.text,
onSaved: (value) {
return controller.value.copyWith(text: value);
},
),
),
],
),
),
),
bottomNavigationBar: SafeArea(
top: false,
child: UniversalPadding(
padding: 0.p,
child: FormMultiMedia(
form: controller,
initialValue: controller.value.images.mapAndRemoveEmpty(
(e) => e.toFormMediaValue(),
),
builder: (context, value) {
return AspectRatio(
aspectRatio: 1,
child: Image(
image: Asset.image(value.uri.toString()),
fit: BoxFit.cover,
),
);
},
onTap: (ref) async {
final uri = await adapter.option.onPickerSelected?.call();
if (uri == null) {
return;
}
ref.update(uri, FormMediaType.image);
},
onSaved: (value) => controller.value.copyWith(
images: value.mapAndRemoveEmpty((e) => e.toModelImageUri()),
),
),
),
),
);
}