Browse Source

neon: check app compatibility in appsbloc

pull/395/head
Nikolas Rimikis 1 year ago
parent
commit
eaf9347df1
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 4
      packages/neon/neon/lib/l10n/en.arb
  2. 4
      packages/neon/neon/lib/l10n/localizations.dart
  3. 4
      packages/neon/neon/lib/l10n/localizations_en.dart
  4. 49
      packages/neon/neon/lib/src/blocs/apps.dart
  5. 55
      packages/neon/neon/lib/src/pages/home.dart
  6. 11
      packages/neon/neon/lib/src/utils/result.dart

4
packages/neon/neon/lib/l10n/en.arb

@ -36,10 +36,10 @@
} }
}, },
"errorUnableToOpenFile": "Unable to open the file", "errorUnableToOpenFile": "Unable to open the file",
"errorUnsupportedVersion": "Sorry, this Nextcloud {name} version is not supported.", "errorUnsupportedVersion": "Sorry, the version of the following apps on your Nextcloud instance are not supported. \n {unsupported} \n Please contact your administrator to resolve the issues.",
"@errorUnsupportedVersion" : { "@errorUnsupportedVersion" : {
"placeholders": { "placeholders": {
"name": { "unsupported": {
"type": "String" "type": "String"
} }
} }

4
packages/neon/neon/lib/l10n/localizations.dart

@ -194,8 +194,8 @@ abstract class AppLocalizations {
/// No description provided for @errorUnsupportedVersion. /// No description provided for @errorUnsupportedVersion.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Sorry, this Nextcloud {name} version is not supported.'** /// **'Sorry, the version of the following apps on your Nextcloud instance are not supported. \n {unsupported} \n Please contact your administrator to resolve the issues.'**
String errorUnsupportedVersion(String name); String errorUnsupportedVersion(String unsupported);
/// No description provided for @errorEmptyField. /// No description provided for @errorEmptyField.
/// ///

4
packages/neon/neon/lib/l10n/localizations_en.dart

@ -79,8 +79,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get errorUnableToOpenFile => 'Unable to open the file'; String get errorUnableToOpenFile => 'Unable to open the file';
@override @override
String errorUnsupportedVersion(String name) { String errorUnsupportedVersion(String unsupported) {
return 'Sorry, this Nextcloud $name version is not supported.'; return 'Sorry, the version of the following apps on your Nextcloud instance are not supported. \n $unsupported \n Please contact your administrator to resolve the issues.';
} }
@override @override

49
packages/neon/neon/lib/src/blocs/apps.dart

@ -16,6 +16,8 @@ abstract class AppsBlocStates {
BehaviorSubject<String?> get activeAppID; BehaviorSubject<String?> get activeAppID;
BehaviorSubject get openNotifications; BehaviorSubject get openNotifications;
BehaviorSubject<Iterable<(String, Object?)>?> get appVersions;
} }
class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates { class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates {
@ -50,6 +52,8 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates
} }
}), }),
); );
unawaited(_checkCompatibility());
} }
}); });
@ -59,11 +63,52 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates
(final data) => data.capabilities.notifications != null ? _findAppImplementation('notifications') : null, (final data) => data.capabilities.notifications != null ? _findAppImplementation('notifications') : null,
), ),
); );
unawaited(_checkCompatibility());
}); });
unawaited(refresh()); unawaited(refresh());
} }
Future<void> _checkCompatibility() async {
final apps = appImplementations.valueOrNull;
final capabilities = _capabilitiesBloc.capabilities.valueOrNull;
// ignore cached data
if (capabilities == null || apps == null || !capabilities.hasUncachedData || !apps.hasUncachedData) {
return;
}
final appIds = {
'core',
...apps.requireData.map((final a) => a.id),
};
final notSupported = <(String, Object?)>[];
for (final id in appIds) {
try {
final (supported, minVersion) = switch (id) {
'core' => await _account.client.core.isSupported(capabilities.requireData),
'news' => await _account.client.news.isSupported(),
'notes' => await _account.client.notes.isSupported(capabilities.requireData),
_ => (true, null),
};
if (!supported) {
notSupported.add((id, minVersion));
}
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
}
}
if (notSupported.isNotEmpty) {
appVersions.add(notSupported);
}
}
T? _findAppImplementation<T extends AppImplementation>(final String id) { T? _findAppImplementation<T extends AppImplementation>(final String id) {
final matches = _filteredAppImplementations([id]); final matches = _filteredAppImplementations([id]);
if (matches.isNotEmpty) { if (matches.isNotEmpty) {
@ -89,6 +134,7 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates
unawaited(notificationsAppImplementation.close()); unawaited(notificationsAppImplementation.close());
unawaited(activeAppID.close()); unawaited(activeAppID.close());
unawaited(openNotifications.close()); unawaited(openNotifications.close());
unawaited(appVersions.close());
for (final app in _allAppImplementations) { for (final app in _allAppImplementations) {
for (final bloc in app.blocs.values) { for (final bloc in app.blocs.values) {
@ -114,6 +160,9 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates
@override @override
BehaviorSubject openNotifications = BehaviorSubject(); BehaviorSubject openNotifications = BehaviorSubject();
@override
BehaviorSubject<List<(String, Object?)>?> appVersions = BehaviorSubject();
@override @override
Future refresh() async { Future refresh() async {
await _requestManager.wrapNextcloud<List<NextcloudApp>, NextcloudCoreNavigationApps>( await _requestManager.wrapNextcloud<List<NextcloudApp>, NextcloudCoreNavigationApps>(

55
packages/neon/neon/lib/src/pages/home.dart

@ -42,45 +42,26 @@ class _HomePageState extends State<HomePage> {
} }
}); });
_capabilitiesBloc.capabilities.listen((final result) async { _appsBloc.appVersions.listen((final values) {
if (result.data != null) { if (values == null || !mounted) {
// ignore cached version and prevent duplicate dialogs return;
if (result.isCached) { }
return;
final l10n = AppLocalizations.of(context);
final buffer = StringBuffer()..writeln();
for (final error in values) {
final (appId, minVersion) = error;
final appName = l10n.appImplementationName(appId);
if (appName.isNotEmpty && minVersion != null) {
buffer.writeln('- $appName $minVersion');
} }
_appsBloc.appImplementations.listen((final appsResult) async {
// ignore cached version and prevent duplicate dialogs
if (appsResult.data == null || appsResult.isCached) {
return;
}
for (final id in [
'core',
...appsResult.data!.map((final a) => a.id),
]) {
try {
final (supported, _) = switch (id) {
'core' => await _account.client.core.isSupported(result.data),
'news' => await _account.client.news.isSupported(),
'notes' => await _account.client.notes.isSupported(result.data),
_ => (true, null),
};
if (supported || !mounted) {
return;
}
var name = AppLocalizations.of(context).appImplementationName(id);
if (name == '') {
name = id;
}
await _showProblem(
AppLocalizations.of(context).errorUnsupportedVersion(name),
);
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
}
}
});
} }
final message = l10n.errorUnsupportedVersion(buffer.toString());
unawaited(_showProblem(message));
}); });
GlobalPopups().register(context); GlobalPopups().register(context);

11
packages/neon/neon/lib/src/utils/result.dart

@ -51,6 +51,17 @@ class Result<T> {
bool get hasError => error != null; bool get hasError => error != null;
bool get hasData => data != null;
bool get hasUncachedData => hasData && !isCached;
T get requireData {
if (hasData) {
return data!;
}
throw StateError('Result has no data');
}
@override @override
bool operator ==(final Object other) => bool operator ==(final Object other) =>
other is Result && other.isLoading == isLoading && other.data == data && other.error == error; other is Result && other.isLoading == isLoading && other.data == data && other.error == error;

Loading…
Cancel
Save