Introducing the new text editor 🎉

This commit is contained in:
Ankit Mahato
2023-03-12 23:22:14 +05:30
parent 3646f294ee
commit 8f5487f646
2 changed files with 127 additions and 59 deletions

View File

@ -1,20 +1,28 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/providers/providers.dart';
import 'package:apidash/widgets/editor.dart';
import 'package:apidash/consts.dart';
class EditRequestBody extends StatefulWidget {
class EditRequestBody extends ConsumerStatefulWidget {
const EditRequestBody({super.key});
@override
State<EditRequestBody> createState() => _EditRequestBodyState();
ConsumerState<EditRequestBody> createState() => _EditRequestBodyState();
}
class _EditRequestBodyState extends State<EditRequestBody> {
class _EditRequestBodyState extends ConsumerState<EditRequestBody> {
@override
Widget build(BuildContext context) {
final activeId = ref.watch(activeIdStateProvider);
final reqestModel = ref
.read(collectionStateNotifierProvider.notifier)
.getRequestModel(activeId!);
return Container(
decoration: kTableContainerDecoration,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: kBorder12,
),
margin: kP5,
child: Column(
children: [
@ -31,8 +39,16 @@ class _EditRequestBodyState extends State<EditRequestBody> {
],
),
),
const Expanded(
child: TextFieldEditor(),
Expanded(
child: TextFieldEditor(
fieldKey: "$activeId-body",
initialValue: reqestModel.requestBody,
onChanged: (String value) {
ref
.read(collectionStateNotifierProvider.notifier)
.update(activeId, requestBody: value);
},
),
)
],
),
@ -54,13 +70,14 @@ class _DropdownButtonBodyContentTypeState
extends ConsumerState<DropdownButtonBodyContentType> {
@override
Widget build(BuildContext context) {
final surfaceColor = Theme.of(context).colorScheme.surface;
final activeId = ref.watch(activeIdStateProvider);
final collection = ref.read(collectionStateNotifierProvider);
final idIdx = collection.indexWhere((m) => m.id == activeId);
final requestBodyContentType = ref.watch(collectionStateNotifierProvider
.select((value) => value[idIdx].requestBodyContentType));
return DropdownButton<ContentType>(
focusColor: kColorGrey50,
focusColor: surfaceColor,
value: requestBodyContentType,
icon: const Icon(
Icons.unfold_more_rounded,
@ -95,55 +112,3 @@ class _DropdownButtonBodyContentTypeState
);
}
}
class TextFieldEditor extends ConsumerStatefulWidget {
const TextFieldEditor({Key? key}) : super(key: key);
@override
ConsumerState<TextFieldEditor> createState() => _TextFieldEditorState();
}
class _TextFieldEditorState extends ConsumerState<TextFieldEditor> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
final activeId = ref.watch(activeIdStateProvider);
final reqestModel = ref
.read(collectionStateNotifierProvider.notifier)
.getRequestModel(activeId!);
return TextFormField(
key: Key("$activeId-body"),
keyboardType: TextInputType.multiline,
expands: true,
maxLines: null,
textAlignVertical: TextAlignVertical.top,
initialValue: reqestModel.requestBody ?? "",
style: kCodeStyle,
onChanged: (value) {
ref
.read(collectionStateNotifierProvider.notifier)
.update(activeId, requestBody: value);
},
decoration: InputDecoration(
hintText: "Enter content (body)",
hintStyle: kCodeHintStyle,
focusedBorder: OutlineInputBorder(
borderRadius: kBorder12,
borderSide: BorderSide(
color: Theme.of(context).colorScheme.surfaceVariant,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: kBorder12,
borderSide: BorderSide(
color: Theme.of(context).colorScheme.surfaceVariant,
),
),
),
);
}
}

103
lib/widgets/editor.dart Normal file
View File

@ -0,0 +1,103 @@
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:apidash/consts.dart';
class TextFieldEditor extends StatefulWidget {
const TextFieldEditor(
{Key? key, required this.fieldKey, this.onChanged, this.initialValue})
: super(key: key);
final String fieldKey;
final Function(String)? onChanged;
final String? initialValue;
@override
State<TextFieldEditor> createState() => _TextFieldEditorState();
}
class _TextFieldEditorState extends State<TextFieldEditor> {
final TextEditingController controller = TextEditingController();
final editorFocusNode = FocusNode();
final keyboardListnerFocusNode = FocusNode();
@override
void initState() {
super.initState();
}
void insertTab() {
String sp = " ";
int offset = math.min(
controller.selection.baseOffset, controller.selection.extentOffset);
String text = controller.text.substring(0, offset) +
sp +
controller.text.substring(offset);
controller.value = TextEditingValue(
text: text,
selection: controller.selection.copyWith(
baseOffset: controller.selection.baseOffset + sp.length,
extentOffset: controller.selection.extentOffset + sp.length,
),
);
}
@override
Widget build(BuildContext context) {
if (widget.initialValue != null) {
controller.text = widget.initialValue!;
}
return RawKeyboardListener(
focusNode: keyboardListnerFocusNode,
onKey: (RawKeyEvent event) {
if (event.runtimeType == RawKeyDownEvent &&
(event.logicalKey == LogicalKeyboardKey.tab)) {
if (kIsWeb) {
FocusScope.of(context).previousFocus();
} else {
editorFocusNode.requestFocus();
}
insertTab();
}
},
child: TextFormField(
key: Key(widget.fieldKey),
controller: controller,
focusNode: editorFocusNode,
keyboardType: TextInputType.multiline,
expands: true,
maxLines: null,
style: kCodeStyle,
textAlignVertical: TextAlignVertical.top,
onChanged: widget.onChanged,
decoration: InputDecoration(
hintText: "Enter content (body)",
hintStyle: TextStyle(
color: Theme.of(context).colorScheme.outline.withOpacity(
kHintOpacity,
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.primary.withOpacity(
kHintOpacity,
),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.surfaceVariant,
),
),
),
),
);
}
@override
void dispose() {
keyboardListnerFocusNode.dispose();
editorFocusNode.dispose();
super.dispose();
}
}