mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-24 02:47:49 +08:00
1747766f73
Signed-off-by: fufesou <shuanglongchen@yeah.net>
320 lines
7.6 KiB
Dart
320 lines
7.6 KiB
Dart
// The plugin manager is a singleton class that manages the plugins.
|
|
// 1. It merge metadata and the desc of plugins.
|
|
|
|
import 'dart:convert';
|
|
import 'dart:collection';
|
|
import 'package:flutter/material.dart';
|
|
|
|
const String kValueTrue = '1';
|
|
const String kValueFalse = '0';
|
|
|
|
class ConfigItem {
|
|
String key;
|
|
String description;
|
|
String defaultValue;
|
|
|
|
ConfigItem(this.key, this.defaultValue, this.description);
|
|
ConfigItem.fromJson(Map<String, dynamic> json)
|
|
: key = json['key'] ?? '',
|
|
description = json['description'] ?? '',
|
|
defaultValue = json['default'] ?? '';
|
|
|
|
static String get trueValue => kValueTrue;
|
|
static String get falseValue => kValueFalse;
|
|
static bool isTrue(String value) => value == kValueTrue;
|
|
static bool isFalse(String value) => value == kValueFalse;
|
|
}
|
|
|
|
class UiType {
|
|
String key;
|
|
String text;
|
|
String tooltip;
|
|
String action;
|
|
|
|
UiType(this.key, this.text, this.tooltip, this.action);
|
|
|
|
UiType.fromJson(Map<String, dynamic> json)
|
|
: key = json['key'] ?? '',
|
|
text = json['text'] ?? '',
|
|
tooltip = json['tooltip'] ?? '',
|
|
action = json['action'] ?? '';
|
|
|
|
static UiType? create(Map<String, dynamic> json) {
|
|
if (json['t'] == 'Button') {
|
|
return UiButton.fromJson(json['c']);
|
|
} else if (json['t'] == 'Checkbox') {
|
|
return UiCheckbox.fromJson(json['c']);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
class UiButton extends UiType {
|
|
String icon;
|
|
|
|
UiButton(
|
|
{required String key,
|
|
required String text,
|
|
required this.icon,
|
|
required String tooltip,
|
|
required String action})
|
|
: super(key, text, tooltip, action);
|
|
|
|
UiButton.fromJson(Map<String, dynamic> json)
|
|
: icon = json['icon'] ?? '',
|
|
super.fromJson(json);
|
|
}
|
|
|
|
class UiCheckbox extends UiType {
|
|
UiCheckbox(
|
|
{required String key,
|
|
required String text,
|
|
required String tooltip,
|
|
required String action})
|
|
: super(key, text, tooltip, action);
|
|
|
|
UiCheckbox.fromJson(Map<String, dynamic> json) : super.fromJson(json);
|
|
}
|
|
|
|
class Location {
|
|
// location key:
|
|
// host|main|settings|plugin
|
|
// client|remote|toolbar|display
|
|
HashMap<String, UiType> ui;
|
|
|
|
Location(this.ui);
|
|
Location.fromJson(Map<String, dynamic> json) : ui = HashMap() {
|
|
(json['ui'] as Map<String, dynamic>).forEach((key, value) {
|
|
var ui = UiType.create(value);
|
|
if (ui != null) {
|
|
this.ui[ui.key] = ui;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
class PublishInfo {
|
|
PublishInfo({
|
|
required this.lastReleased,
|
|
required this.published,
|
|
});
|
|
|
|
final DateTime lastReleased;
|
|
final DateTime published;
|
|
}
|
|
|
|
class Meta {
|
|
Meta({
|
|
required this.id,
|
|
required this.name,
|
|
required this.version,
|
|
required this.description,
|
|
required this.author,
|
|
required this.home,
|
|
required this.license,
|
|
required this.publishInfo,
|
|
required this.source,
|
|
});
|
|
|
|
final String id;
|
|
final String name;
|
|
final String version;
|
|
final String description;
|
|
final String author;
|
|
final String home;
|
|
final String license;
|
|
final PublishInfo publishInfo;
|
|
final String source;
|
|
}
|
|
|
|
class SourceInfo {
|
|
String name; // 1. RustDesk github 2. Local
|
|
String url;
|
|
String description;
|
|
|
|
SourceInfo({
|
|
required this.name,
|
|
required this.url,
|
|
required this.description,
|
|
});
|
|
}
|
|
|
|
class PluginInfo with ChangeNotifier {
|
|
SourceInfo sourceInfo;
|
|
Meta meta;
|
|
String installedVersion; // It is empty if not installed.
|
|
String failedMsg;
|
|
String invalidReason; // It is empty if valid.
|
|
|
|
PluginInfo({
|
|
required this.sourceInfo,
|
|
required this.meta,
|
|
required this.installedVersion,
|
|
required this.invalidReason,
|
|
this.failedMsg = '',
|
|
});
|
|
|
|
bool get installed => installedVersion.isNotEmpty;
|
|
bool get needUpdate => installed && installedVersion != meta.version;
|
|
|
|
void setInstall(String msg) {
|
|
if (msg == "finished") {
|
|
msg = '';
|
|
}
|
|
failedMsg = msg;
|
|
if (msg.isEmpty) {
|
|
installedVersion = meta.version;
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
void setUninstall(String msg) {
|
|
failedMsg = msg;
|
|
if (msg.isEmpty) {
|
|
installedVersion = '';
|
|
}
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
class PluginManager with ChangeNotifier {
|
|
String failedReason = ''; // The reason of failed to load plugins.
|
|
final List<PluginInfo> _plugins = [];
|
|
|
|
PluginManager._();
|
|
static final PluginManager _instance = PluginManager._();
|
|
static PluginManager get instance => _instance;
|
|
|
|
List<PluginInfo> get plugins => _plugins;
|
|
|
|
PluginInfo? getPlugin(String id) {
|
|
for (var p in _plugins) {
|
|
if (p.meta.id == id) {
|
|
return p;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
void handleEvent(Map<String, dynamic> evt) {
|
|
if (evt['plugin_list'] != null) {
|
|
_handlePluginList(evt['plugin_list']);
|
|
} else if (evt['plugin_install'] != null && evt['id'] != null) {
|
|
_handlePluginInstall(evt['id'], evt['plugin_install']);
|
|
} else if (evt['plugin_uninstall'] != null && evt['id'] != null) {
|
|
_handlePluginUninstall(evt['id'], evt['plugin_uninstall']);
|
|
} else {
|
|
debugPrint('Failed to handle manager event: $evt');
|
|
}
|
|
}
|
|
|
|
void _sortPlugins() {
|
|
plugins.sort((a, b) {
|
|
if (a.installed) {
|
|
return -1;
|
|
} else if (b.installed) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
void _handlePluginList(String pluginList) {
|
|
_plugins.clear();
|
|
try {
|
|
for (var p in json.decode(pluginList) as List<dynamic>) {
|
|
final plugin = _getPluginFromEvent(p);
|
|
if (plugin == null) {
|
|
continue;
|
|
}
|
|
_plugins.add(plugin);
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Failed to decode $e, plugin list \'$pluginList\'');
|
|
}
|
|
_sortPlugins();
|
|
notifyListeners();
|
|
}
|
|
|
|
void _handlePluginInstall(String id, String msg) {
|
|
debugPrint('Plugin \'$id\' install msg $msg');
|
|
for (var i = 0; i < _plugins.length; i++) {
|
|
if (_plugins[i].meta.id == id) {
|
|
_plugins[i].setInstall(msg);
|
|
_sortPlugins();
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void _handlePluginUninstall(String id, String msg) {
|
|
debugPrint('Plugin \'$id\' uninstall msg $msg');
|
|
for (var i = 0; i < _plugins.length; i++) {
|
|
if (_plugins[i].meta.id == id) {
|
|
_plugins[i].setUninstall(msg);
|
|
_sortPlugins();
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
PluginInfo? _getPluginFromEvent(Map<String, dynamic> evt) {
|
|
final s = evt['source'];
|
|
assert(s != null, 'Source is null');
|
|
if (s == null) {
|
|
return null;
|
|
}
|
|
final source = SourceInfo(
|
|
name: s['name'],
|
|
url: s['url'] ?? '',
|
|
description: s['description'] ?? '',
|
|
);
|
|
|
|
final m = evt['meta'];
|
|
assert(m != null, 'Meta is null');
|
|
if (m == null) {
|
|
return null;
|
|
}
|
|
|
|
late DateTime lastReleased;
|
|
late DateTime published;
|
|
try {
|
|
lastReleased = DateTime.parse(
|
|
m['publish_info']?['last_released'] ?? '1970-01-01T00+00:00');
|
|
} catch (e) {
|
|
lastReleased = DateTime.utc(1970);
|
|
}
|
|
try {
|
|
published = DateTime.parse(
|
|
m['publish_info']?['published'] ?? '1970-01-01T00+00:00');
|
|
} catch (e) {
|
|
published = DateTime.utc(1970);
|
|
}
|
|
|
|
final meta = Meta(
|
|
id: m['id'],
|
|
name: m['name'],
|
|
version: m['version'],
|
|
description: m['description'] ?? '',
|
|
author: m['author'],
|
|
home: m['home'] ?? '',
|
|
license: m['license'] ?? '',
|
|
source: m['source'] ?? '',
|
|
publishInfo:
|
|
PublishInfo(lastReleased: lastReleased, published: published),
|
|
);
|
|
return PluginInfo(
|
|
sourceInfo: source,
|
|
meta: meta,
|
|
installedVersion: evt['installed_version'],
|
|
invalidReason: evt['invalid_reason'] ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
PluginManager get pluginManager => PluginManager.instance;
|