fix refresh, error

This commit is contained in:
Christien Rioux 2024-02-29 13:54:03 -05:00
parent 56d8f81cf2
commit 0cf2b947be
5 changed files with 86 additions and 62 deletions

View File

@ -26,8 +26,8 @@ class ContactInvitationDisplayDialog extends StatefulWidget {
final String message;
@override
ContactInvitationDisplayDialogState createState() =>
ContactInvitationDisplayDialogState();
State<ContactInvitationDisplayDialog> createState() =>
_ContactInvitationDisplayDialogState();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
@ -36,7 +36,7 @@ class ContactInvitationDisplayDialog extends StatefulWidget {
}
}
class ContactInvitationDisplayDialogState
class _ContactInvitationDisplayDialogState
extends State<ContactInvitationDisplayDialog> {
final focusNode = FocusNode();
final formKey = GlobalKey<FormState>();
@ -123,12 +123,8 @@ class ContactInvitationDisplayDialogState
},
).paddingAll(16),
])),
error: (e, s) {
Navigator.of(context).pop();
showErrorToast(context,
translate('send_invite_dialog.failed_to_generate'));
return const Text('');
})));
error: (e, s) =>
Text(translate('send_invite_dialog.failed_to_generate')))));
}
@override

View File

@ -212,17 +212,54 @@ class DHTShortArray {
return record!.get(subkey: recordSubkey, forceRefresh: forceRefresh);
}
Future<List<Uint8List>?> getAllItems({bool forceRefresh = false}) async {
await _refreshHead(forceRefresh: forceRefresh, onlyUpdates: true);
final out = <Uint8List>[];
for (var pos = 0; pos < _head.index.length; pos++) {
final index = _head.index[pos];
final recordNumber = index ~/ _stride;
final record = _getLinkedRecord(recordNumber);
if (record == null) {
assert(record != null, 'Record does not exist');
return null;
}
final recordSubkey = (index % _stride) + ((recordNumber == 0) ? 1 : 0);
final elem =
await record.get(subkey: recordSubkey, forceRefresh: forceRefresh);
if (elem == null) {
return null;
}
out.add(elem);
}
return out;
}
Future<T?> getItemJson<T>(T Function(dynamic) fromJson, int pos,
{bool forceRefresh = false}) =>
getItem(pos, forceRefresh: forceRefresh)
.then((out) => jsonDecodeOptBytes(fromJson, out));
Future<List<T>?> getAllItemsJson<T>(T Function(dynamic) fromJson,
{bool forceRefresh = false}) =>
getAllItems(forceRefresh: forceRefresh)
.then((out) => out?.map(fromJson).toList());
Future<T?> getItemProtobuf<T extends GeneratedMessage>(
T Function(List<int>) fromBuffer, int pos,
{bool forceRefresh = false}) =>
getItem(pos, forceRefresh: forceRefresh)
.then((out) => (out == null) ? null : fromBuffer(out));
Future<List<T>?> getAllItemsProtobuf<T extends GeneratedMessage>(
T Function(List<int>) fromBuffer,
{bool forceRefresh = false}) =>
getAllItems(forceRefresh: forceRefresh)
.then((out) => out?.map(fromBuffer).toList());
Future<bool> tryAddItem(Uint8List value) async {
await _refreshHead(onlyUpdates: true);

View File

@ -18,13 +18,13 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
required T Function(List<int> data) decodeElement,
}) : _decodeElement = decodeElement,
super(const BlocBusyState(AsyncValue.loading())) {
Future.delayed(Duration.zero, () async {
_initFuture = Future(() async {
// Open DHT record
_shortArray = await open();
_wantsCloseRecord = true;
// Make initial state update
_update();
await _refreshNoWait();
_subscription = await _shortArray.listen(_update);
});
}
@ -35,57 +35,53 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
}) : _shortArray = shortArray,
_decodeElement = decodeElement,
super(const BlocBusyState(AsyncValue.loading())) {
_initFuture = Future(() async {
// Make initial state update
_update();
Future.delayed(Duration.zero, () async {
await _refreshNoWait();
_subscription = await shortArray.listen(_update);
});
}
Future<void> refresh({bool forceRefresh = false}) async => busy((emit) async {
var out = IList<T>();
// xxx could be parallelized but we need to watch out for rate limits
for (var i = 0; i < _shortArray.length; i++) {
final cir = await _shortArray.getItem(i, forceRefresh: forceRefresh);
if (cir == null) {
throw Exception('Failed to get short array element');
Future<void> refresh({bool forceRefresh = false}) async {
await _initFuture;
await _refreshNoWait(forceRefresh: forceRefresh);
}
out = out.add(_decodeElement(cir));
}
emit(AsyncValue.data(out));
Future<void> _refreshNoWait({bool forceRefresh = false}) async =>
busy((emit) async {
await _refreshInner(emit, forceRefresh: forceRefresh);
});
Future<void> _refreshInner(void Function(AsyncValue<IList<T>>) emit,
{bool forceRefresh = false}) async {
try {
final newState =
(await _shortArray.getAllItems(forceRefresh: forceRefresh))
?.map(_decodeElement)
.toIList();
if (newState == null) {
emit(const AsyncValue.loading());
} else {
emit(AsyncValue.data(newState));
}
} on Exception catch (e) {
emit(AsyncValue.error(e));
}
}
void _update() {
// Run at most one background update process
// Because this is async, we could get an update while we're
// still processing the last one
// still processing the last one. Only called after init future has run
// so we dont have to wait for that here.
_sspUpdate.busyUpdate<T, AsyncValue<IList<T>>>(busy, (emit) async {
try {
final initialState = await _getElementsInner();
emit(AsyncValue.data(initialState));
} on Exception catch (e) {
emit(AsyncValue.error(e));
}
await _refreshInner(emit);
});
}
// Get and decode the entire short array
Future<IList<T>> _getElementsInner() async {
assert(isBusy, 'should only be called from a busy state');
var out = IList<T>();
for (var i = 0; i < _shortArray.length; i++) {
// Get the element bytes (throw if fails, array state is invalid)
final bytes = (await _shortArray.getItem(i))!;
// Decode the element
final elem = _decodeElement(bytes);
// Append to the output list
out = out.add(elem);
}
return out;
}
@override
Future<void> close() async {
await _initFuture;
await _subscription?.cancel();
_subscription = null;
if (_wantsCloseRecord) {
@ -94,10 +90,13 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
await super.close();
}
Future<R> operate<R>(Future<R> Function(DHTShortArray) closure) async =>
_operateMutex.protect(() async => closure(_shortArray));
Future<R> operate<R>(Future<R> Function(DHTShortArray) closure) async {
await _initFuture;
return _operateMutex.protect(() async => closure(_shortArray));
}
final _operateMutex = Mutex();
late final Future<void> _initFuture;
late final DHTShortArray _shortArray;
final T Function(List<int> data) _decodeElement;
StreamSubscription<void>? _subscription;

View File

@ -251,10 +251,10 @@ packages:
dependency: "direct main"
description:
name: change_case
sha256: f4e08feaa845e75e4f5ad2b0e15f24813d7ea6c27e7b78252f0c17f752cf1157
sha256: "47c48c36f95f20c6d0ba03efabceff261d05026cca322cc2c4c01c343371b5bb"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
version: "2.0.1"
characters:
dependency: transitive
description:
@ -423,14 +423,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
file_utils:
dependency: transitive
description:
name: file_utils
sha256: d1e64389a22649095c8405c9e177272caf05139255931c9ff30d53b5c9bcaa34
url: "https://pub.dev"
source: hosted
version: "1.0.1"
fixnum:
dependency: "direct main"
description:
@ -1342,10 +1334,10 @@ packages:
dependency: transitive
description:
name: system_info2
sha256: af2f948e3f31a3367a049932a8ad59faf0063ecf836a020d975b9f41566d8bc9
sha256: "65206bbef475217008b5827374767550a5420ce70a04d2d7e94d1d2253f3efc9"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
version: "4.0.0"
system_info_plus:
dependency: transitive
description:

View File

@ -20,7 +20,7 @@ dependencies:
bloc_tools:
path: packages/bloc_tools
blurry_modal_progress_hud: ^1.1.1
change_case: ^1.1.0
change_case: ^2.0.1
charcode: ^1.3.1
circular_profile_avatar: ^2.0.5
circular_reveal_animation: ^2.0.1