Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: [feat] support communicable with another plugin, add custom exception, add PluggableLifeCycle abstract class #45

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void main() {
..register(ColorSucker())
..register(AlignRuler())
..register(ColorPicker())
..register(Palette())
..register(TouchIndicator())
..register(Performance())
..register(ShowCode())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class PageInfoHelper {
final packageName = parts.first.split('/').last;
final keyword = "package:$packageName/$fileForwardPart";
CodeDisplayService().getScriptIdsWithKeyword(keyword);
debugPrint(keyword);
return keyword;
}

Expand Down Expand Up @@ -80,9 +79,9 @@ class PageInfoHelper {
selection.candidates = objectList;
}

Future<String?> getCode() async {
Future<String?> getCode({String? path}) async {
CodeDisplayService codeDisplayService = CodeDisplayService();
String targetFileName = filePath!.split('/').last;
String targetFileName = (path ?? filePath!).split('/').last;
String? scriptId =
await codeDisplayService.getScriptIdWithFileName(targetFileName);
if (scriptId == null) return null;
Expand Down
77 changes: 53 additions & 24 deletions kits/flutter_ume_kit_show_code/lib/show_code/show_code.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_ume/flutter_ume.dart';
import 'package:flutter_ume_kit_show_code/flutter_ume_kit_show_code.dart';
import 'package:flutter_ume_kit_show_code/show_code/page_info_helper.dart';
import 'package:flutter_ume_kit_show_code/show_code/syntax_highlighter.dart';
import 'package:flutter_ume_kit_show_code/show_code/icon.dart' as icon;
import 'package:share/share.dart';

class ShowCode extends StatefulWidget implements Pluggable {
const ShowCode({Key? key}) : super(key: key);
class ShowCode extends StatefulWidget
implements Pluggable, Communicable, PluggableLifeCycle {
String? launchKey;

ShowCode({Key? key}) : super(key: key);

@override
ShowCodeState createState() => ShowCodeState();
Expand All @@ -28,6 +32,21 @@ class ShowCode extends StatefulWidget implements Pluggable {

@override
void onTrigger() {}

@override
void handleParams(dynamic params) {
if (params is Map && params.containsKey('launchKey')) {
launchKey = params['launchKey'];
}
}

@override
void onDeactivate() {
launchKey = null;
}

@override
void onActivate() {}
}

class ShowCodeState extends State<ShowCode> with WidgetsBindingObserver {
Expand All @@ -43,9 +62,15 @@ class ShowCodeState extends State<ShowCode> with WidgetsBindingObserver {
@override
void initState() {
pageInfoHelper = PageInfoHelper();
filePath =
pageInfoHelper.packagePathConvertFromFilePath(pageInfoHelper.filePath!);
pageInfoHelper.getCode().then((c) {
if (widget.launchKey != null) {
filePath =
pageInfoHelper.packagePathConvertFromFilePath(widget.launchKey!);
} else {
filePath = pageInfoHelper
.packagePathConvertFromFilePath(pageInfoHelper.filePath!);
}

pageInfoHelper.getCode(path: filePath).then((c) {
code = c;
setState(() {});
});
Expand Down Expand Up @@ -109,7 +134,9 @@ class ShowCodeState extends State<ShowCode> with WidgetsBindingObserver {
height: 22,
child: CircularProgressIndicator(),
),
if (showCodeList && _codeList != null && _codeList!.isNotEmpty)
if (showCodeList &&
_codeList != null &&
_codeList!.isNotEmpty)
PopupMenuButton<String>(
padding: EdgeInsets.zero,
icon: Icon(Icons.arrow_drop_down),
Expand Down Expand Up @@ -194,25 +221,27 @@ class ShowCodeState extends State<ShowCode> with WidgetsBindingObserver {

@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
floatingActionButton: FloatingActionButton(
onPressed: () => _share(),
child: Icon(Icons.share),
return MaterialApp(
home: Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
floatingActionButton: FloatingActionButton(
onPressed: () => _share(),
child: Icon(Icons.share),
),
body: Container(
color: Colors.white,
child: SafeArea(
child: Column(
children: <Widget>[
_infoView(),
Divider(),
Expanded(
flex: 1,
child: _codeView(),
)
],
))),
),
body: Container(
color: Colors.white,
child: SafeArea(
child: Column(
children: <Widget>[
_infoView(),
Divider(),
Expanded(
flex: 1,
child: _codeView(),
)
],
))),
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ColorPicker extends StatefulWidget implements PluggableWithNestedWidget {
String get name => 'ColorPicker';

@override
String get displayName => 'TouchIndicator';
String get displayName => 'ColorPicker';

@override
void onTrigger() {}
Expand Down Expand Up @@ -108,7 +108,20 @@ class _ColorPickerState extends State<ColorPicker> {
color: Colors.blue)),
])),
),
)
),
if (_color != null &&
PluggableCommunicationService()
.isAvailableKey('Palette'))
IconButton(
onPressed: () {
PluggableCommunicationService().callWithKey(
'Palette',
{'initialColor': _color ?? Colors.white});
},
icon: Image(
image: PluggableCommunicationService()
.pluginImageWithKey('Palette')!),
),
],
)),
)),
Expand Down
2 changes: 2 additions & 0 deletions kits/flutter_ume_kit_ui/lib/components/palette/icon.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const iconData =
r'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';
77 changes: 77 additions & 0 deletions kits/flutter_ume_kit_ui/lib/components/palette/palette.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'dart:convert';

import 'package:flutter_ume_kit_ui/third_party/cyclop/lib/cyclop.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ume/flutter_ume.dart';
import 'icon.dart' as icon;

class Palette extends StatefulWidget
implements Pluggable, Communicable, PluggableLifeCycle {
Palette({Key? key}) : super(key: key);

Color? initialColor;

@override
_PaletteState createState() => _PaletteState();

@override
Widget buildWidget(BuildContext? context) => this;

@override
String get name => 'Palette';

@override
String get displayName => 'Palette';

@override
void onTrigger() {}

@override
ImageProvider<Object> get iconImageProvider =>
MemoryImage(base64Decode(icon.iconData));

@override
void handleParams(dynamic params) {
if (params is Map && params.containsKey('initialColor')) {
initialColor = params['initialColor'];
}
}

@override
void onDeactivate() {
initialColor = null;
}

@override
void onActivate() {}
}

class _PaletteState extends State<Palette> {
late Color backgroundColor;

Set<Color> swatches = Colors.primaries.map((e) => Color(e.value)).toSet();

@override
void initState() {
super.initState();
if (widget.initialColor != null) {
backgroundColor = widget.initialColor!;
} else {
backgroundColor = Colors.grey.shade200;
}
}

@override
Widget build(BuildContext context) {
return Center(
child: ColorButton(
key: const Key('c1'),
color: backgroundColor,
swatches: swatches,
onColorChanged: (value) => setState(() => backgroundColor = value),
onSwatchesChanged: (newSwatches) =>
setState(() => swatches = newSwatches),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_ume/flutter_ume.dart';
import 'package:flutter_ume/core/pluggable_communication_service.dart';
import 'package:flutter_ume/service/inspector/inspector_overlay.dart';
import 'package:flutter_ume_kit_ui/components/hit_test.dart';
import 'icon.dart' as icon;

Expand Down Expand Up @@ -90,6 +93,21 @@ class _WidgetInfoInspectorState extends State<WidgetInfoInspector>
);
children.add(gesture);
children.add(InspectorOverlay(selection: selection));
if (selection.active &&
PluggableCommunicationService().isAvailableKey('ShowCode'))
children.add(Positioned(
left: _lastPointerLocation?.dx,
top: _lastPointerLocation?.dy,
child: CircleAvatar(
child: IconButton(
onPressed: () {
PluggableCommunicationService().callWithKey('ShowCode',
{'launchKey': SelectionInfo(selection).filePath!});
},
icon: Image(
color: Colors.white,
image: PluggableCommunicationService()
.pluginImageWithKey('ShowCode')!)))));
return Stack(children: children, textDirection: TextDirection.ltr);
}
}
1 change: 1 addition & 0 deletions kits/flutter_ume_kit_ui/lib/flutter_ume_kit_ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export 'package:flutter_ume_kit_ui/components/widget_info_inspector/widget_info_
export 'package:flutter_ume_kit_ui/components/widget_detail_inspector/widget_detail_inspector.dart';
export 'package:flutter_ume_kit_ui/components/color_picker/color_picker.dart';
export 'package:flutter_ume_kit_ui/components/touch_indicator/touch_indicator.dart';
export 'package:flutter_ume_kit_ui/components/palette/palette.dart';
5 changes: 5 additions & 0 deletions lib/core/pluggable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ abstract class Pluggable {
ImageProvider get iconImageProvider;
}

abstract class PluggableLifeCycle {
void onActivate();
void onDeactivate();
}

typedef StreamFilter = bool Function(dynamic);

abstract class PluggableWithStream extends Pluggable {
Expand Down
48 changes: 48 additions & 0 deletions lib/core/pluggable_communication_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
import 'package:flutter_ume/core/plugin_manager.dart';
import 'package:flutter_ume/util/exception_factory.dart';

import 'ui/global.dart';

abstract class Communicable {
void handleParams(dynamic params);
}

class PluggableCommunicationService {
static final PluggableCommunicationService _instance =
PluggableCommunicationService._internal();
factory PluggableCommunicationService() => _instance;

final _availableKeys = <String>{};
List<String> get availableKeys => _availableKeys.toList();
void registerKeys(String pluggableKey) => _availableKeys.add(pluggableKey);

PluggableCommunicationService._internal();

bool isAvailableKey(String pluggableKey) {
return PluginManager.instance.pluginsMap.containsKey(pluggableKey) &&
PluginManager.instance.pluginsMap[pluggableKey] is Communicable &&
_availableKeys.contains(pluggableKey);
}

ImageProvider? pluginImageWithKey(String pluggableKey) {
if (!isAvailableKey(pluggableKey)) return null;
return PluginManager.instance.pluginsMap[pluggableKey]!.iconImageProvider;
}

void callWithKey(String pluggableKey, dynamic params) {
if (!PluginManager.instance.pluginsMap.containsKey(pluggableKey)) {
throw ExceptionFactory.pluggableCommunicationNonexistKeyException;
}
if (!(PluginManager.instance.pluginsMap[pluggableKey] is Communicable)) {
throw ExceptionFactory.pluggableCommunicationNotCommunicableException;
}
umeEventBus.fire(PluggableChangedEvent(pluggableKey, params: params));
}
}

class PluggableChangedEvent {
String pluggableKey;
Object? params;
PluggableChangedEvent(this.pluggableKey, {this.params});
}
9 changes: 9 additions & 0 deletions lib/core/plugin_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class PluginManager {
if (plugin.name.isEmpty) {
return;
}
if (plugin is Communicable) {
PluggableCommunicationService().registerKeys(plugin.name);
}
_pluginsMap[plugin.name] = plugin;
}

Expand All @@ -37,11 +40,17 @@ class PluginManager {
}

void activatePluggable(Pluggable pluggable) {
if (pluggable is PluggableLifeCycle) {
(pluggable as PluggableLifeCycle).onActivate();
}
_activatedPluggable = pluggable;
}

void deactivatePluggable(Pluggable pluggable) {
if (_activatedPluggable?.name == pluggable.name) {
if (pluggable is PluggableLifeCycle) {
(pluggable as PluggableLifeCycle).onDeactivate();
}
_activatedPluggable = null;
}
}
Expand Down
3 changes: 3 additions & 0 deletions lib/core/ui/global.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import 'package:event_bus/event_bus.dart';
import 'package:flutter/widgets.dart';

final GlobalKey rootKey = GlobalKey();

final GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>(debugLabel: 'ume_navigator');

final EventBus umeEventBus = EventBus();
Loading