]> git.proxmox.com Git - flutter/pve_flutter_frontend.git/commitdiff
rework guest id selector
authorTim Marx <t.marx@proxmox.com>
Fri, 6 Dec 2019 16:52:20 +0000 (17:52 +0100)
committerTim Marx <t.marx@proxmox.com>
Fri, 6 Dec 2019 17:12:43 +0000 (18:12 +0100)
Signed-off-by: Tim Marx <t.marx@proxmox.com>
lib/bloc/pve_guest_id_selector_bloc.dart
lib/events/pve_guest_id_selector_events.dart [deleted file]
lib/states/pve_guest_id_selector_states.dart [deleted file]
lib/widgets/pve_guest_id_selector_widget.dart

index d2a57838f4d621c5cf7eebc72168d12082b9804b..f4cbe84e0bf7d351c7be527cfd638fcc08a7fe7f 100644 (file)
@@ -1,63 +1,61 @@
 import 'dart:async';
 import 'dart:convert';
+import 'package:flutter/material.dart';
+import 'package:pve_flutter_frontend/bloc/proxmox_base_bloc.dart';
+import 'package:pve_flutter_frontend/states/proxmox_form_field_state.dart';
 
 import 'package:meta/meta.dart';
-import 'package:pve_flutter_frontend/events/pve_guest_id_selector_events.dart';
-import 'package:pve_flutter_frontend/states/pve_guest_id_selector_states.dart';
 import 'package:rxdart/rxdart.dart';
 import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart'
     as proxclient;
 
-class PveGuestIdSelectorBloc {
+class PveGuestIdSelectorBloc
+    extends ProxmoxBaseBloc<PveGuestIdSelectorEvent, GuestIdSelectorState> {
   final proxclient.Client apiClient;
-  final PublishSubject<PveGuestIdSelectorEvent> _eventSubject =
-      PublishSubject<PveGuestIdSelectorEvent>();
-  BehaviorSubject<PveGuestIdSelectorState> _stateSubject;
 
-  StreamSink<PveGuestIdSelectorEvent> get events => _eventSubject.sink;
-  Stream<PveGuestIdSelectorState> get state => _stateSubject.stream;
+  @override
+  GuestIdSelectorState get initialState => GuestIdSelectorState();
 
-  PveGuestIdSelectorBloc({@required this.apiClient}) {
-    _stateSubject = BehaviorSubject<PveGuestIdSelectorState>();
-    _eventSubject
-        .debounceTime(Duration(milliseconds: 250))
-        .switchMap((event) => _eventToState(event))
-        .forEach((PveGuestIdSelectorState state) {
-      _stateSubject.add(state);
-    });
+  PveGuestIdSelectorBloc({@required this.apiClient});
+
+  @override
+  Stream<GuestIdSelectorState> eventPipe(
+    PublishSubject<PveGuestIdSelectorEvent> events,
+    Stream<GuestIdSelectorState> pipeInto(PveGuestIdSelectorEvent event),
+  ) {
+    return events.debounceTime(Duration(milliseconds: 150)).switchMap(pipeInto);
   }
 
-  Stream<PveGuestIdSelectorState> _eventToState(
+  @override
+  Stream<GuestIdSelectorState> processEvents(
       PveGuestIdSelectorEvent event) async* {
-    print(event);
-
-    if (event is LoadNextFreeId) {
-      final id = await getNextFreeID();
-      yield PveGuestIdSelectorState(id: id);
+    if (event is PrefetchId) {
+      try {
+        final id = await getNextFreeID();
+        yield GuestIdSelectorState(value: id);
+      } on proxclient.ProxmoxApiException catch (e) {
+        yield GuestIdSelectorState(value: null, errorText: "Could not load ID");
+      }
     }
-
-    if (event is ValidateInput) {
+    if (event is OnChanged) {
       if (event.id == "") {
-        yield PveGuestIdSelectorState(id: event.id, error: "Input required");
+        yield GuestIdSelectorState(
+            value: event.id, errorText: "Input required");
         return;
       }
 
       try {
         final id = await getNextFreeID(id: event.id);
-        yield PveGuestIdSelectorState(id: id);
+        yield GuestIdSelectorState(value: id);
       } on proxclient.ProxmoxApiException catch (e) {
         if (e.details != null && e.details['vmid'] != null) {
-          yield PveGuestIdSelectorState(id: event.id, error: e.details['vmid']);
+          yield GuestIdSelectorState(
+              value: event.id, errorText: e.details['vmid']);
         }
       }
     }
   }
 
-  void dispose() {
-    _eventSubject.close();
-    _stateSubject.close();
-  }
-
   Future<String> getNextFreeID({String id}) async {
     var url = Uri.parse(
         proxclient.getPlatformAwareOrigin() + '/api2/json/cluster/nextid');
@@ -72,3 +70,18 @@ class PveGuestIdSelectorBloc {
     return jsonBody['data'];
   }
 }
+
+abstract class PveGuestIdSelectorEvent {}
+
+class PrefetchId extends PveGuestIdSelectorEvent {}
+
+class OnChanged extends PveGuestIdSelectorEvent {
+  final String id;
+
+  OnChanged(this.id);
+}
+
+class GuestIdSelectorState extends PveFormFieldState<String> {
+  GuestIdSelectorState({String value, String errorText})
+      : super(value: value, errorText: errorText);
+}
diff --git a/lib/events/pve_guest_id_selector_events.dart b/lib/events/pve_guest_id_selector_events.dart
deleted file mode 100644 (file)
index ed01551..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-abstract class PveGuestIdSelectorEvent {}
-
-class LoadNextFreeId extends PveGuestIdSelectorEvent {}
-
-class ValidateInput extends PveGuestIdSelectorEvent {
-  final String id;
-
-  ValidateInput(this.id);
-}
\ No newline at end of file
diff --git a/lib/states/pve_guest_id_selector_states.dart b/lib/states/pve_guest_id_selector_states.dart
deleted file mode 100644 (file)
index 634c6bc..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-class PveGuestIdSelectorState {
-  final String id;
-  final String error;
-
-  PveGuestIdSelectorState({this.id, this.error});
-}
index 88bcd4c80071053b8c151785efec65122c728c2e..4d54390611e3be073500a658d325d218bc046c4b 100644 (file)
@@ -2,33 +2,42 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:provider/provider.dart';
 import 'package:pve_flutter_frontend/bloc/pve_guest_id_selector_bloc.dart';
-import 'package:pve_flutter_frontend/events/pve_guest_id_selector_events.dart';
-import 'package:pve_flutter_frontend/states/pve_guest_id_selector_states.dart';
+import 'package:pve_flutter_frontend/states/proxmox_form_field_state.dart';
 
 class PveGuestIdSelector extends StatelessWidget {
+  final String labelText;
+
+  PveGuestIdSelector(
+      {Key key,
+      this.labelText,})
+      : super(key: key);
+
   @override
   Widget build(BuildContext context) {
     final _pveGuestIdSelectorBloc =
         Provider.of<PveGuestIdSelectorBloc>(context);
-
-    return StreamBuilder<PveGuestIdSelectorState>(
+    return StreamBuilder<PveFormFieldState>(
         stream: _pveGuestIdSelectorBloc.state,
+        initialData: _pveGuestIdSelectorBloc.state.value,
         builder: (context, snapshot) {
-          print("build");
-          if (snapshot.hasData) {
-            final state = snapshot.data;
-            return TextFormField(
-              decoration:
-                  InputDecoration(labelText: 'VM ID', errorText: state.error),
-              initialValue: state.id,
-              keyboardType: TextInputType.number,
-              inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
-              onChanged: (text) {
-                _pveGuestIdSelectorBloc.events.add(ValidateInput(text));
-              },
-            );
-          }
-          return Container();
+          final state = snapshot.data;
+
+          return TextFormField(
+            // make sure a new internal state is created if the
+            // first build has no data
+            key: state.value != null ? null : ValueKey(1),
+            decoration: InputDecoration(labelText: labelText, helperText: ' '),
+            initialValue: state?.value,
+            keyboardType: TextInputType.number,
+            inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
+            autovalidate: true,
+            onChanged: (text) {
+              _pveGuestIdSelectorBloc.events.add(OnChanged(text));
+            },
+            validator: (_) {
+              return state?.errorText;
+            },
+          );
         });
   }
 }