mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-02-03 11:50:01 -05:00
fix refresh, error
This commit is contained in:
parent
56d8f81cf2
commit
0cf2b947be
@ -26,8 +26,8 @@ class ContactInvitationDisplayDialog extends StatefulWidget {
|
|||||||
final String message;
|
final String message;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ContactInvitationDisplayDialogState createState() =>
|
State<ContactInvitationDisplayDialog> createState() =>
|
||||||
ContactInvitationDisplayDialogState();
|
_ContactInvitationDisplayDialogState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
@ -36,7 +36,7 @@ class ContactInvitationDisplayDialog extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ContactInvitationDisplayDialogState
|
class _ContactInvitationDisplayDialogState
|
||||||
extends State<ContactInvitationDisplayDialog> {
|
extends State<ContactInvitationDisplayDialog> {
|
||||||
final focusNode = FocusNode();
|
final focusNode = FocusNode();
|
||||||
final formKey = GlobalKey<FormState>();
|
final formKey = GlobalKey<FormState>();
|
||||||
@ -123,12 +123,8 @@ class ContactInvitationDisplayDialogState
|
|||||||
},
|
},
|
||||||
).paddingAll(16),
|
).paddingAll(16),
|
||||||
])),
|
])),
|
||||||
error: (e, s) {
|
error: (e, s) =>
|
||||||
Navigator.of(context).pop();
|
Text(translate('send_invite_dialog.failed_to_generate')))));
|
||||||
showErrorToast(context,
|
|
||||||
translate('send_invite_dialog.failed_to_generate'));
|
|
||||||
return const Text('');
|
|
||||||
})));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -212,17 +212,54 @@ class DHTShortArray {
|
|||||||
return record!.get(subkey: recordSubkey, forceRefresh: forceRefresh);
|
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,
|
Future<T?> getItemJson<T>(T Function(dynamic) fromJson, int pos,
|
||||||
{bool forceRefresh = false}) =>
|
{bool forceRefresh = false}) =>
|
||||||
getItem(pos, forceRefresh: forceRefresh)
|
getItem(pos, forceRefresh: forceRefresh)
|
||||||
.then((out) => jsonDecodeOptBytes(fromJson, out));
|
.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>(
|
Future<T?> getItemProtobuf<T extends GeneratedMessage>(
|
||||||
T Function(List<int>) fromBuffer, int pos,
|
T Function(List<int>) fromBuffer, int pos,
|
||||||
{bool forceRefresh = false}) =>
|
{bool forceRefresh = false}) =>
|
||||||
getItem(pos, forceRefresh: forceRefresh)
|
getItem(pos, forceRefresh: forceRefresh)
|
||||||
.then((out) => (out == null) ? null : fromBuffer(out));
|
.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 {
|
Future<bool> tryAddItem(Uint8List value) async {
|
||||||
await _refreshHead(onlyUpdates: true);
|
await _refreshHead(onlyUpdates: true);
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
|
|||||||
required T Function(List<int> data) decodeElement,
|
required T Function(List<int> data) decodeElement,
|
||||||
}) : _decodeElement = decodeElement,
|
}) : _decodeElement = decodeElement,
|
||||||
super(const BlocBusyState(AsyncValue.loading())) {
|
super(const BlocBusyState(AsyncValue.loading())) {
|
||||||
Future.delayed(Duration.zero, () async {
|
_initFuture = Future(() async {
|
||||||
// Open DHT record
|
// Open DHT record
|
||||||
_shortArray = await open();
|
_shortArray = await open();
|
||||||
_wantsCloseRecord = true;
|
_wantsCloseRecord = true;
|
||||||
|
|
||||||
// Make initial state update
|
// Make initial state update
|
||||||
_update();
|
await _refreshNoWait();
|
||||||
_subscription = await _shortArray.listen(_update);
|
_subscription = await _shortArray.listen(_update);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -35,57 +35,53 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
|
|||||||
}) : _shortArray = shortArray,
|
}) : _shortArray = shortArray,
|
||||||
_decodeElement = decodeElement,
|
_decodeElement = decodeElement,
|
||||||
super(const BlocBusyState(AsyncValue.loading())) {
|
super(const BlocBusyState(AsyncValue.loading())) {
|
||||||
// Make initial state update
|
_initFuture = Future(() async {
|
||||||
_update();
|
// Make initial state update
|
||||||
Future.delayed(Duration.zero, () async {
|
await _refreshNoWait();
|
||||||
_subscription = await shortArray.listen(_update);
|
_subscription = await shortArray.listen(_update);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refresh({bool forceRefresh = false}) async => busy((emit) async {
|
Future<void> refresh({bool forceRefresh = false}) async {
|
||||||
var out = IList<T>();
|
await _initFuture;
|
||||||
// xxx could be parallelized but we need to watch out for rate limits
|
await _refreshNoWait(forceRefresh: forceRefresh);
|
||||||
for (var i = 0; i < _shortArray.length; i++) {
|
}
|
||||||
final cir = await _shortArray.getItem(i, forceRefresh: forceRefresh);
|
|
||||||
if (cir == null) {
|
Future<void> _refreshNoWait({bool forceRefresh = false}) async =>
|
||||||
throw Exception('Failed to get short array element');
|
busy((emit) async {
|
||||||
}
|
await _refreshInner(emit, forceRefresh: forceRefresh);
|
||||||
out = out.add(_decodeElement(cir));
|
|
||||||
}
|
|
||||||
emit(AsyncValue.data(out));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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() {
|
void _update() {
|
||||||
// Run at most one background update process
|
// Run at most one background update process
|
||||||
// Because this is async, we could get an update while we're
|
// 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 {
|
_sspUpdate.busyUpdate<T, AsyncValue<IList<T>>>(busy, (emit) async {
|
||||||
try {
|
await _refreshInner(emit);
|
||||||
final initialState = await _getElementsInner();
|
|
||||||
emit(AsyncValue.data(initialState));
|
|
||||||
} on Exception catch (e) {
|
|
||||||
emit(AsyncValue.error(e));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
|
await _initFuture;
|
||||||
await _subscription?.cancel();
|
await _subscription?.cancel();
|
||||||
_subscription = null;
|
_subscription = null;
|
||||||
if (_wantsCloseRecord) {
|
if (_wantsCloseRecord) {
|
||||||
@ -94,10 +90,13 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
|
|||||||
await super.close();
|
await super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<R> operate<R>(Future<R> Function(DHTShortArray) closure) async =>
|
Future<R> operate<R>(Future<R> Function(DHTShortArray) closure) async {
|
||||||
_operateMutex.protect(() async => closure(_shortArray));
|
await _initFuture;
|
||||||
|
return _operateMutex.protect(() async => closure(_shortArray));
|
||||||
|
}
|
||||||
|
|
||||||
final _operateMutex = Mutex();
|
final _operateMutex = Mutex();
|
||||||
|
late final Future<void> _initFuture;
|
||||||
late final DHTShortArray _shortArray;
|
late final DHTShortArray _shortArray;
|
||||||
final T Function(List<int> data) _decodeElement;
|
final T Function(List<int> data) _decodeElement;
|
||||||
StreamSubscription<void>? _subscription;
|
StreamSubscription<void>? _subscription;
|
||||||
|
16
pubspec.lock
16
pubspec.lock
@ -251,10 +251,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: change_case
|
name: change_case
|
||||||
sha256: f4e08feaa845e75e4f5ad2b0e15f24813d7ea6c27e7b78252f0c17f752cf1157
|
sha256: "47c48c36f95f20c6d0ba03efabceff261d05026cca322cc2c4c01c343371b5bb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "2.0.1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -423,14 +423,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.0"
|
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:
|
fixnum:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1342,10 +1334,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: system_info2
|
name: system_info2
|
||||||
sha256: af2f948e3f31a3367a049932a8ad59faf0063ecf836a020d975b9f41566d8bc9
|
sha256: "65206bbef475217008b5827374767550a5420ce70a04d2d7e94d1d2253f3efc9"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "4.0.0"
|
||||||
system_info_plus:
|
system_info_plus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -20,7 +20,7 @@ dependencies:
|
|||||||
bloc_tools:
|
bloc_tools:
|
||||||
path: packages/bloc_tools
|
path: packages/bloc_tools
|
||||||
blurry_modal_progress_hud: ^1.1.1
|
blurry_modal_progress_hud: ^1.1.1
|
||||||
change_case: ^1.1.0
|
change_case: ^2.0.1
|
||||||
charcode: ^1.3.1
|
charcode: ^1.3.1
|
||||||
circular_profile_avatar: ^2.0.5
|
circular_profile_avatar: ^2.0.5
|
||||||
circular_reveal_animation: ^2.0.1
|
circular_reveal_animation: ^2.0.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user