mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: make theme uploads more tolerant (#5617)
This commit is contained in:
parent
6b1e7b6ac8
commit
271b250eac
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flowy_infra/plugins/bloc/dynamic_plugin_bloc.dart';
|
||||
import 'package:flowy_infra/plugins/bloc/dynamic_plugin_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'theme_upload_decoration.dart';
|
||||
@ -57,8 +58,9 @@ class _ThemeUploadWidgetState extends State<ThemeUploadWidget> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget child =
|
||||
const UploadNewThemeWidget(key: Key('upload_new_theme_widget'));
|
||||
Widget child = const UploadNewThemeWidget(
|
||||
key: Key('upload_new_theme_widget'),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -149,4 +149,39 @@ class FlowyColorScheme {
|
||||
_$FlowyColorSchemeFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$FlowyColorSchemeToJson(this);
|
||||
|
||||
/// Merges the given [json] with the default color scheme
|
||||
/// based on the given [brightness].
|
||||
///
|
||||
factory FlowyColorScheme.fromJsonSoft(
|
||||
Map<String, dynamic> json, [
|
||||
Brightness brightness = Brightness.light,
|
||||
]) {
|
||||
final colorScheme = brightness == Brightness.light
|
||||
? const DefaultColorScheme.light()
|
||||
: const DefaultColorScheme.dark();
|
||||
final defaultMap = colorScheme.toJson();
|
||||
final mergedMap = Map<String, dynamic>.from(defaultMap)..addAll(json);
|
||||
|
||||
return FlowyColorScheme.fromJson(mergedMap);
|
||||
}
|
||||
|
||||
/// Useful in validating that a teheme adheres to the default color scheme.
|
||||
/// Returns the keys that are missing from the [json].
|
||||
///
|
||||
/// We use this for testing and debugging, and we might make it possible for users to
|
||||
/// check their themes for missing keys in the future.
|
||||
///
|
||||
/// Sample usage:
|
||||
/// ```dart
|
||||
/// final lightJson = await jsonDecode(await light.readAsString());
|
||||
/// final lightMissingKeys = FlowyColorScheme.getMissingKeys(lightJson);
|
||||
/// ```
|
||||
///
|
||||
static List<String> getMissingKeys(Map<String, dynamic> json) {
|
||||
final defaultKeys = const DefaultColorScheme.light().toJson().keys;
|
||||
final jsonKeys = json.keys;
|
||||
|
||||
return defaultKeys.where((key) => !jsonKeys.contains(key)).toList();
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,11 @@ class DynamicPluginBloc extends Bloc<DynamicPluginEvent, DynamicPluginState> {
|
||||
}
|
||||
|
||||
Future<void> onLoadRequested(Emitter<DynamicPluginState> emit) async {
|
||||
emit(DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins));
|
||||
emit(
|
||||
DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addPlugin(Emitter<DynamicPluginState> emit) async {
|
||||
@ -33,31 +36,41 @@ class DynamicPluginBloc extends Bloc<DynamicPluginEvent, DynamicPluginState> {
|
||||
try {
|
||||
final plugin = await FlowyPluginService.pick();
|
||||
if (plugin == null) {
|
||||
emit(DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins));
|
||||
return;
|
||||
return emit(
|
||||
DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins,
|
||||
),
|
||||
);
|
||||
}
|
||||
await FlowyPluginService.instance.addPlugin(plugin);
|
||||
} on PluginCompilationException catch (exception) {
|
||||
return emit(DynamicPluginState.compilationFailure(
|
||||
errorMessage: exception.message));
|
||||
return emit(
|
||||
DynamicPluginState.compilationFailure(errorMessage: exception.message),
|
||||
);
|
||||
}
|
||||
|
||||
emit(const DynamicPluginState.compilationSuccess());
|
||||
emit(DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins));
|
||||
emit(
|
||||
DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removePlugin(
|
||||
Emitter<DynamicPluginState> emit, String name) async {
|
||||
Emitter<DynamicPluginState> emit,
|
||||
String name,
|
||||
) async {
|
||||
emit(const DynamicPluginState.processing());
|
||||
|
||||
final plugin = await FlowyPluginService.instance.lookup(name: name);
|
||||
|
||||
if (plugin == null) {
|
||||
emit(DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins));
|
||||
return;
|
||||
return emit(
|
||||
DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await FlowyPluginService.removePlugin(plugin);
|
||||
@ -65,7 +78,8 @@ class DynamicPluginBloc extends Bloc<DynamicPluginEvent, DynamicPluginState> {
|
||||
emit(const DynamicPluginState.deletionSuccess());
|
||||
emit(
|
||||
DynamicPluginState.ready(
|
||||
plugins: await FlowyPluginService.instance.plugins),
|
||||
plugins: await FlowyPluginService.instance.plugins,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flowy_infra/colorscheme/colorscheme.dart';
|
||||
import 'package:flowy_infra/plugins/service/models/exceptions.dart';
|
||||
@ -123,8 +125,9 @@ class FlowyDynamicPlugin {
|
||||
late final FlowyColorScheme darkTheme;
|
||||
|
||||
try {
|
||||
lightTheme = FlowyColorScheme.fromJson(
|
||||
await jsonDecode(await light.readAsString()));
|
||||
lightTheme = FlowyColorScheme.fromJsonSoft(
|
||||
await jsonDecode(await light.readAsString()),
|
||||
);
|
||||
} catch (e) {
|
||||
throw PluginCompilationException(
|
||||
'The light theme json file is not valid.',
|
||||
@ -132,8 +135,10 @@ class FlowyDynamicPlugin {
|
||||
}
|
||||
|
||||
try {
|
||||
darkTheme = FlowyColorScheme.fromJson(
|
||||
await jsonDecode(await dark.readAsString()));
|
||||
darkTheme = FlowyColorScheme.fromJsonSoft(
|
||||
await jsonDecode(await dark.readAsString()),
|
||||
Brightness.dark,
|
||||
);
|
||||
} catch (e) {
|
||||
throw PluginCompilationException(
|
||||
'The dark theme json file is not valid.',
|
||||
|
@ -0,0 +1,32 @@
|
||||
import 'package:flowy_infra/colorscheme/colorscheme.dart';
|
||||
import 'package:flowy_infra/colorscheme/default_colorscheme.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('Theme missing keys', () {
|
||||
test('no missing keys', () {
|
||||
const colorScheme = DefaultColorScheme.light();
|
||||
final toJson = colorScheme.toJson();
|
||||
|
||||
expect(toJson.containsKey('surface'), true);
|
||||
|
||||
final missingKeys = FlowyColorScheme.getMissingKeys(toJson);
|
||||
expect(missingKeys.isEmpty, true);
|
||||
});
|
||||
|
||||
test('missing surface and bg2', () {
|
||||
const colorScheme = DefaultColorScheme.light();
|
||||
final toJson = colorScheme.toJson()
|
||||
..remove('surface')
|
||||
..remove('bg2');
|
||||
|
||||
expect(toJson.containsKey('surface'), false);
|
||||
expect(toJson.containsKey('bg2'), false);
|
||||
|
||||
final missingKeys = FlowyColorScheme.getMissingKeys(toJson);
|
||||
expect(missingKeys.length, 2);
|
||||
expect(missingKeys.contains('surface'), true);
|
||||
expect(missingKeys.contains('bg2'), true);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user