mirror of https://github.com/Wox-launcher/Wox
Add tail component to query result
This commit is contained in:
parent
b10322f1d7
commit
213671919a
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@wox-launcher/wox-plugin",
|
||||
"version": "0.0.71",
|
||||
"version": "0.0.72",
|
||||
"description": "All nodejs plugin for Wox should use types in this package",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -85,6 +85,7 @@ export interface Result {
|
|||
Score?: number
|
||||
Group?: string
|
||||
GroupScore?: number
|
||||
Tails?: ResultTail[]
|
||||
ContextData?: string
|
||||
Actions?: ResultAction[]
|
||||
// refresh result after specified interval, in milliseconds. If this value is 0, Wox will not refresh this result
|
||||
|
@ -95,6 +96,12 @@ export interface Result {
|
|||
OnRefresh?: (current: RefreshableResult) => Promise<RefreshableResult>
|
||||
}
|
||||
|
||||
export interface ResultTail {
|
||||
Type: "text" | "image"
|
||||
Text: string
|
||||
Image: WoxImage
|
||||
}
|
||||
|
||||
export interface RefreshableResult {
|
||||
Title: string
|
||||
SubTitle: string
|
||||
|
|
|
@ -30,7 +30,7 @@ class WoxImageView extends StatelessWidget {
|
|||
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_SVG.code) {
|
||||
return SvgPicture.string(woxImage.imageData, width: width, height: height);
|
||||
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_EMOJI.code) {
|
||||
return Text(woxImage.imageData, style: const TextStyle(fontSize: 30));
|
||||
return Text(woxImage.imageData, style: TextStyle(fontSize: width));
|
||||
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_BASE64.code) {
|
||||
if (!woxImage.imageData.contains(";base64,")) {
|
||||
return Text("Invalid image data: ${woxImage.imageData}", style: const TextStyle(color: Colors.red));
|
||||
|
|
|
@ -4,15 +4,19 @@ import 'package:get/get.dart';
|
|||
import 'package:uuid/v4.dart';
|
||||
import 'package:wox/components/wox_image_view.dart';
|
||||
import 'package:wox/entity/wox_image.dart';
|
||||
import 'package:wox/entity/wox_query.dart';
|
||||
import 'package:wox/entity/wox_theme.dart';
|
||||
import 'package:wox/enums/wox_list_view_type_enum.dart';
|
||||
import 'package:wox/enums/wox_result_tail_type_enum.dart';
|
||||
import 'package:wox/utils/log.dart';
|
||||
import 'package:wox/utils/wox_setting_util.dart';
|
||||
|
||||
class WoxListItemView extends StatelessWidget {
|
||||
final bool isActive;
|
||||
final Rx<WoxImage> icon;
|
||||
final Rx<String> title;
|
||||
final Rx<String> subTitle;
|
||||
final RxList<WoxQueryResultTail> tails;
|
||||
final WoxTheme woxTheme;
|
||||
final WoxListViewType listViewType;
|
||||
final bool isGroup;
|
||||
|
@ -23,6 +27,7 @@ class WoxListItemView extends StatelessWidget {
|
|||
required this.icon,
|
||||
required this.title,
|
||||
required this.subTitle,
|
||||
required this.tails,
|
||||
required this.isActive,
|
||||
required this.listViewType,
|
||||
required this.isGroup,
|
||||
|
@ -114,6 +119,51 @@ class WoxListItemView extends StatelessWidget {
|
|||
}),
|
||||
]),
|
||||
),
|
||||
// Tails
|
||||
if (tails.isNotEmpty)
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: WoxSettingUtil.instance.currentSetting.appWidth / 2),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0, right: 5.0),
|
||||
child: Obx(() {
|
||||
if (LoggerSwitch.enablePaintLog) Logger.instance.info(const UuidV4().generate(), "repaint: list item view $key - tails");
|
||||
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
for (final tail in tails)
|
||||
if (tail.type == WoxQueryResultTailTypeEnum.WOX_QUERY_RESULT_TAIL_TYPE_TEXT.code && tail.text.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: Text(
|
||||
tail.text,
|
||||
style: TextStyle(
|
||||
color: fromCssColor(isActive ? woxTheme.resultItemActiveTailTextColor : woxTheme.resultItemTailTextColor),
|
||||
fontSize: 13,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
strutStyle: const StrutStyle(
|
||||
forceStrutHeight: true,
|
||||
),
|
||||
),
|
||||
)
|
||||
else if (tail.type == WoxQueryResultTailTypeEnum.WOX_QUERY_RESULT_TAIL_TYPE_IMAGE.code && tail.image.imageData.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: WoxImageView(
|
||||
woxImage: tail.image,
|
||||
width: 14,
|
||||
height: 14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -91,7 +91,9 @@ class WoxQueryResult {
|
|||
late int score;
|
||||
late String group;
|
||||
late int groupScore;
|
||||
late RxList<WoxQueryResultTail> tails;
|
||||
late String contextData;
|
||||
|
||||
late List<WoxResultAction> actions;
|
||||
late int refreshInterval;
|
||||
|
||||
|
@ -108,6 +110,7 @@ class WoxQueryResult {
|
|||
required this.score,
|
||||
required this.group,
|
||||
required this.groupScore,
|
||||
required this.tails,
|
||||
required this.contextData,
|
||||
required this.actions,
|
||||
required this.refreshInterval,
|
||||
|
@ -123,6 +126,7 @@ class WoxQueryResult {
|
|||
score = 0;
|
||||
group = "";
|
||||
groupScore = 0;
|
||||
tails = RxList<WoxQueryResultTail>();
|
||||
contextData = "";
|
||||
actions = <WoxResultAction>[];
|
||||
refreshInterval = 0;
|
||||
|
@ -140,12 +144,25 @@ class WoxQueryResult {
|
|||
group = json['Group'];
|
||||
groupScore = json['GroupScore'];
|
||||
contextData = json['ContextData'];
|
||||
|
||||
if (json['Tails'] != null) {
|
||||
tails = RxList();
|
||||
json['Tails'].forEach((v) {
|
||||
tails.add(WoxQueryResultTail.fromJson(v));
|
||||
});
|
||||
} else {
|
||||
tails = RxList();
|
||||
}
|
||||
|
||||
if (json['Actions'] != null) {
|
||||
actions = <WoxResultAction>[];
|
||||
json['Actions'].forEach((v) {
|
||||
actions.add(WoxResultAction.fromJson(v));
|
||||
});
|
||||
} else {
|
||||
actions = <WoxResultAction>[];
|
||||
}
|
||||
|
||||
refreshInterval = json['RefreshInterval'];
|
||||
isGroup = false;
|
||||
}
|
||||
|
@ -168,6 +185,28 @@ class WoxQueryResult {
|
|||
}
|
||||
}
|
||||
|
||||
class WoxQueryResultTail {
|
||||
late String type;
|
||||
late String text;
|
||||
late WoxImage image;
|
||||
|
||||
WoxQueryResultTail({required this.type, required this.text, required this.image});
|
||||
|
||||
WoxQueryResultTail.fromJson(Map<String, dynamic> json) {
|
||||
type = json['Type'];
|
||||
text = json['Text'];
|
||||
image = WoxImage.fromJson(json['Image']);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['Type'] = type;
|
||||
data['Text'] = text;
|
||||
data['Image'] = image.toJson();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class WoxResultAction {
|
||||
late String id;
|
||||
late Rx<String> name;
|
||||
|
@ -257,11 +296,20 @@ class WoxRefreshableResult {
|
|||
late String subTitle;
|
||||
late WoxImage icon;
|
||||
late WoxPreview preview;
|
||||
late List<WoxQueryResultTail> tails;
|
||||
late String contextData;
|
||||
late int refreshInterval;
|
||||
|
||||
WoxRefreshableResult(
|
||||
{required this.resultId, required this.title, required this.subTitle, required this.icon, required this.preview, required this.contextData, required this.refreshInterval});
|
||||
WoxRefreshableResult({
|
||||
required this.resultId,
|
||||
required this.title,
|
||||
required this.subTitle,
|
||||
required this.icon,
|
||||
required this.preview,
|
||||
required this.tails,
|
||||
required this.contextData,
|
||||
required this.refreshInterval,
|
||||
});
|
||||
|
||||
WoxRefreshableResult.fromJson(Map<String, dynamic> json) {
|
||||
resultId = json['ResultId'];
|
||||
|
@ -269,6 +317,12 @@ class WoxRefreshableResult {
|
|||
subTitle = json['SubTitle'] ?? "";
|
||||
icon = WoxImage.fromJson(json['Icon']);
|
||||
preview = WoxPreview.fromJson(json['Preview']);
|
||||
tails = <WoxQueryResultTail>[];
|
||||
if (json['Tails'] != null) {
|
||||
json['Tails'].forEach((v) {
|
||||
tails.add(WoxQueryResultTail.fromJson(v));
|
||||
});
|
||||
}
|
||||
contextData = json['ContextData'];
|
||||
refreshInterval = json['RefreshInterval'];
|
||||
}
|
||||
|
@ -280,6 +334,7 @@ class WoxRefreshableResult {
|
|||
data['SubTitle'] = subTitle;
|
||||
data['Icon'] = icon.toJson();
|
||||
data['Preview'] = preview.toJson();
|
||||
data['Tails'] = tails.map((v) => v.toJson()).toList();
|
||||
data['ContextData'] = contextData;
|
||||
data['RefreshInterval'] = refreshInterval;
|
||||
return data;
|
||||
|
|
|
@ -22,11 +22,13 @@ class WoxTheme {
|
|||
late int resultItemPaddingBottom;
|
||||
late String resultItemTitleColor;
|
||||
late String resultItemSubTitleColor;
|
||||
late String resultItemTailTextColor;
|
||||
late String resultItemBorderLeft;
|
||||
late String resultItemActiveBackgroundColor;
|
||||
late String resultItemActiveTitleColor;
|
||||
late String resultItemActiveSubTitleColor;
|
||||
late String resultItemActiveBorderLeft;
|
||||
late String resultItemActiveTailTextColor;
|
||||
late String queryBoxFontColor;
|
||||
late String queryBoxBackgroundColor;
|
||||
late int queryBoxBorderRadius;
|
||||
|
@ -122,11 +124,13 @@ class WoxTheme {
|
|||
resultItemPaddingBottom = json['ResultItemPaddingBottom'];
|
||||
resultItemTitleColor = json['ResultItemTitleColor'];
|
||||
resultItemSubTitleColor = json['ResultItemSubTitleColor'];
|
||||
resultItemTailTextColor = json['ResultItemTailTextColor'];
|
||||
resultItemBorderLeft = json['ResultItemBorderLeft'];
|
||||
resultItemActiveBackgroundColor = json['ResultItemActiveBackgroundColor'];
|
||||
resultItemActiveTitleColor = json['ResultItemActiveTitleColor'];
|
||||
resultItemActiveSubTitleColor = json['ResultItemActiveSubTitleColor'];
|
||||
resultItemActiveBorderLeft = json['ResultItemActiveBorderLeft'];
|
||||
resultItemActiveTailTextColor = json['ResultItemActiveTailTextColor'];
|
||||
queryBoxFontColor = json['QueryBoxFontColor'];
|
||||
queryBoxBackgroundColor = json['QueryBoxBackgroundColor'];
|
||||
queryBoxBorderRadius = json['QueryBoxBorderRadius'];
|
||||
|
@ -174,11 +178,13 @@ class WoxTheme {
|
|||
data['ResultItemPaddingBottom'] = resultItemPaddingBottom;
|
||||
data['ResultItemTitleColor'] = resultItemTitleColor;
|
||||
data['ResultItemSubTitleColor'] = resultItemSubTitleColor;
|
||||
data['ResultItemTailTextColor'] = resultItemTailTextColor;
|
||||
data['ResultItemBorderLeft'] = resultItemBorderLeft;
|
||||
data['ResultItemActiveBackgroundColor'] = resultItemActiveBackgroundColor;
|
||||
data['ResultItemActiveTitleColor'] = resultItemActiveTitleColor;
|
||||
data['ResultItemActiveSubTitleColor'] = resultItemActiveSubTitleColor;
|
||||
data['ResultItemActiveBorderLeft'] = resultItemActiveBorderLeft;
|
||||
data['ResultItemActiveTailTextColor'] = resultItemActiveTailTextColor;
|
||||
data['QueryBoxFontColor'] = queryBoxFontColor;
|
||||
data['QueryBoxBackgroundColor'] = queryBoxBackgroundColor;
|
||||
data['QueryBoxBorderRadius'] = queryBoxBorderRadius;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
typedef WoxQueryResultTailType = String;
|
||||
|
||||
enum WoxQueryResultTailTypeEnum {
|
||||
WOX_QUERY_RESULT_TAIL_TYPE_TEXT("text", "text"),
|
||||
WOX_QUERY_RESULT_TAIL_TYPE_IMAGE("image", "image");
|
||||
|
||||
final String code;
|
||||
final String value;
|
||||
|
||||
const WoxQueryResultTailTypeEnum(this.code, this.value);
|
||||
|
||||
static String getValue(String code) => WoxQueryResultTailTypeEnum.values.firstWhere((activity) => activity.code == code).value;
|
||||
}
|
|
@ -38,6 +38,7 @@ class WoxQueryResultView extends GetView<WoxLauncherController> {
|
|||
woxTheme: controller.woxTheme.value,
|
||||
icon: woxResultAction.icon,
|
||||
title: woxResultAction.name,
|
||||
tails: RxList<WoxQueryResultTail>(),
|
||||
subTitle: "".obs,
|
||||
isActive: controller.isResultActionActiveByIndex(index),
|
||||
listViewType: WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_ACTION.code,
|
||||
|
@ -123,6 +124,7 @@ class WoxQueryResultView extends GetView<WoxLauncherController> {
|
|||
woxTheme: controller.woxTheme.value,
|
||||
icon: woxQueryResult.icon,
|
||||
title: woxQueryResult.title,
|
||||
tails: woxQueryResult.tails,
|
||||
subTitle: woxQueryResult.subTitle,
|
||||
isActive: controller.isQueryResultActiveByIndex(index),
|
||||
listViewType: WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_RESULT.code,
|
||||
|
|
|
@ -645,6 +645,7 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa
|
|||
subTitle: result.subTitle.value,
|
||||
icon: result.icon.value,
|
||||
preview: result.preview,
|
||||
tails: result.tails,
|
||||
contextData: result.contextData,
|
||||
refreshInterval: result.refreshInterval,
|
||||
).toJson(),
|
||||
|
@ -669,6 +670,7 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa
|
|||
result.subTitle.value = refreshResult.subTitle;
|
||||
result.icon.value = refreshResult.icon;
|
||||
result.preview = refreshResult.preview;
|
||||
result.tails.assignAll(refreshResult.tails);
|
||||
|
||||
// only update preview data when current result is active
|
||||
final resultIndex = queryResults.indexWhere((element) => element.id == result.id);
|
||||
|
|
|
@ -38,10 +38,10 @@ require (
|
|||
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
|
||||
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/struCoder/pidusage v0.2.1
|
||||
github.com/tidwall/gjson v1.17.1
|
||||
github.com/tidwall/pretty v1.2.1
|
||||
github.com/tmc/langchaingo v0.1.8
|
||||
github.com/webview/webview_go v0.0.0-20240220051247-56f456ca3a43
|
||||
github.com/wissance/stringFormatter v1.2.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.design/x/hotkey v0.4.1
|
||||
|
|
|
@ -173,6 +173,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
|||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/struCoder/pidusage v0.2.1 h1:dFiEgUDkubeIj0XA1NpQ6+8LQmKrLi7NiIQl86E6BoY=
|
||||
github.com/struCoder/pidusage v0.2.1/go.mod h1:bewtP2KUA1TBUyza5+/PCpSQ6sc/H6jJbIKAzqW86BA=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
|
||||
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
|
||||
|
@ -188,8 +190,6 @@ github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUH
|
|||
github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ=
|
||||
github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA=
|
||||
github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg=
|
||||
github.com/webview/webview_go v0.0.0-20240220051247-56f456ca3a43 h1:PwbNdNumoKba+ZgrE6ZpSluJfNJfyMuqwVyUB5+iLDI=
|
||||
github.com/webview/webview_go v0.0.0-20240220051247-56f456ca3a43/go.mod h1:yE65LFCeWf4kyWD5re+h4XNvOHJEXOCOuJZ4v8l5sgk=
|
||||
github.com/wissance/stringFormatter v1.2.0 h1:lB0zcJkTA1O4Eb2qSTJmyapla/LihQt6NpJLghwWSb0=
|
||||
github.com/wissance/stringFormatter v1.2.0/go.mod h1:H7Mz15+5i8ypmv6bLknM/uD+U1teUW99PlW0DNCNscA=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
|
|
|
@ -596,10 +596,22 @@ func (m *Manager) calculateResultScore(ctx context.Context, pluginId, title, sub
|
|||
func (m *Manager) PolishRefreshableResult(ctx context.Context, pluginInstance *Instance, resultId string, result RefreshableResult) RefreshableResult {
|
||||
// convert icon
|
||||
result.Icon = ConvertIcon(ctx, result.Icon, pluginInstance.PluginDirectory)
|
||||
for i := range result.Tails {
|
||||
if result.Tails[i].Type == QueryResultTailTypeImage {
|
||||
result.Tails[i].Image = ConvertIcon(ctx, result.Tails[i].Image, pluginInstance.PluginDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
// translate title
|
||||
result.Title = m.translatePlugin(ctx, pluginInstance, result.Title)
|
||||
// translate subtitle
|
||||
result.SubTitle = m.translatePlugin(ctx, pluginInstance, result.SubTitle)
|
||||
// translate tail text
|
||||
for i := range result.Tails {
|
||||
if result.Tails[i].Type == QueryResultTailTypeText {
|
||||
result.Tails[i].Text = m.translatePlugin(ctx, pluginInstance, result.Tails[i].Text)
|
||||
}
|
||||
}
|
||||
// translate preview properties
|
||||
var previewProperties = make(map[string]string)
|
||||
for key, value := range result.Preview.PreviewProperties {
|
||||
|
@ -928,6 +940,7 @@ func (m *Manager) ExecuteRefresh(ctx context.Context, refreshableResultWithId Re
|
|||
Title: newResult.Title,
|
||||
SubTitle: newResult.SubTitle,
|
||||
Icon: newResult.Icon,
|
||||
Tails: newResult.Tails,
|
||||
Preview: newResult.Preview,
|
||||
ContextData: newResult.ContextData,
|
||||
RefreshInterval: newResult.RefreshInterval,
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
type QueryType = string
|
||||
type QueryVariable = string
|
||||
type QueryResultTailType = string
|
||||
|
||||
const (
|
||||
QueryTypeInput QueryType = "input" // user input query
|
||||
|
@ -20,6 +21,11 @@ const (
|
|||
QueryVariableActiveBrowserUrl QueryVariable = "{wox:active_browser_url}"
|
||||
)
|
||||
|
||||
const (
|
||||
QueryResultTailTypeText QueryResultTailType = "text" // string type
|
||||
QueryResultTailTypeImage QueryResultTailType = "image" // WoxImage type
|
||||
)
|
||||
|
||||
// Query from Wox. See "Doc/Query.md" for details.
|
||||
type Query struct {
|
||||
// By default, Wox will only pass QueryTypeInput query to plugin.
|
||||
|
@ -90,9 +96,13 @@ type QueryResult struct {
|
|||
Icon WoxImage
|
||||
Preview WoxPreview
|
||||
// Score of the result, the higher the score, the more relevant the result is, more likely to be displayed on top
|
||||
Score int64
|
||||
Group string
|
||||
Score int64
|
||||
// Group results, Wox will group results by group name
|
||||
Group string
|
||||
// Score of the group, the higher the score, the more relevant the group is, more likely to be displayed on top
|
||||
GroupScore int64
|
||||
// Tails are additional results associate with this result, can be displayed in result detail view
|
||||
Tails []QueryResultTail
|
||||
// Additional data associate with this result, can be retrieved in Action function
|
||||
ContextData string
|
||||
Actions []QueryResultAction
|
||||
|
@ -104,6 +114,12 @@ type QueryResult struct {
|
|||
OnRefresh func(ctx context.Context, current RefreshableResult) RefreshableResult
|
||||
}
|
||||
|
||||
type QueryResultTail struct {
|
||||
Type QueryResultTailType
|
||||
Text string // only available when type is QueryResultTailTypeText
|
||||
Image WoxImage // only available when type is QueryResultTailTypeImage
|
||||
}
|
||||
|
||||
type QueryResultAction struct {
|
||||
// Result id, should be unique. It's optional, if you don't set it, Wox will assign a random id for you
|
||||
Id string
|
||||
|
@ -133,6 +149,7 @@ func (q *QueryResult) ToUI() QueryResultUI {
|
|||
Score: q.Score,
|
||||
Group: q.Group,
|
||||
GroupScore: q.GroupScore,
|
||||
Tails: q.Tails,
|
||||
ContextData: q.ContextData,
|
||||
Actions: lo.Map(q.Actions, func(action QueryResultAction, index int) QueryResultActionUI {
|
||||
return QueryResultActionUI{
|
||||
|
@ -157,6 +174,7 @@ type QueryResultUI struct {
|
|||
Score int64
|
||||
Group string
|
||||
GroupScore int64
|
||||
Tails []QueryResultTail
|
||||
ContextData string
|
||||
Actions []QueryResultActionUI
|
||||
RefreshInterval int
|
||||
|
|
|
@ -5,6 +5,7 @@ type RefreshableResult struct {
|
|||
SubTitle string
|
||||
Icon WoxImage
|
||||
Preview WoxPreview
|
||||
Tails []QueryResultTail
|
||||
ContextData string
|
||||
RefreshInterval int // set to 0 if you don't want to refresh this result anymore
|
||||
}
|
||||
|
@ -15,6 +16,7 @@ type RefreshableResultWithResultId struct {
|
|||
SubTitle string
|
||||
Icon WoxImage
|
||||
Preview WoxPreview
|
||||
Tails []QueryResultTail
|
||||
ContextData string
|
||||
RefreshInterval int
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/google/uuid"
|
||||
"github.com/samber/lo"
|
||||
"github.com/struCoder/pidusage"
|
||||
"github.com/tidwall/pretty"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -133,16 +134,18 @@ func (a *ApplicationPlugin) Query(ctx context.Context, query plugin.Query) []plu
|
|||
isNameMatch, nameScore := system.IsStringMatchScore(ctx, info.Name, query.Search)
|
||||
isPathNameMatch, pathNameScore := system.IsStringMatchScore(ctx, filepath.Base(info.Path), query.Search)
|
||||
if isNameMatch || isPathNameMatch {
|
||||
subTitle := info.Path
|
||||
var tails []plugin.QueryResultTail
|
||||
// get cpu and mem info
|
||||
if info.IsRunning() {
|
||||
subTitle = fmt.Sprintf("%s, pid: %d", subTitle, info.Pid)
|
||||
tails = a.getRunningProcessResult(info.Pid)
|
||||
}
|
||||
|
||||
result := plugin.QueryResult{
|
||||
Id: uuid.NewString(),
|
||||
Title: info.Name,
|
||||
SubTitle: subTitle,
|
||||
SubTitle: info.Path,
|
||||
Icon: info.Icon,
|
||||
Tails: tails,
|
||||
Score: util.MaxInt64(nameScore, pathNameScore),
|
||||
Preview: plugin.WoxPreview{
|
||||
PreviewType: plugin.WoxPreviewTypeText,
|
||||
|
@ -188,18 +191,25 @@ func (a *ApplicationPlugin) Query(ctx context.Context, query plugin.Query) []plu
|
|||
Icon: plugin.NewWoxImageSvg(`<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 20 20"><path fill="#f33939" d="M2.93 17.07A10 10 0 1 1 17.07 2.93A10 10 0 0 1 2.93 17.07m1.41-1.41A8 8 0 1 0 15.66 4.34A8 8 0 0 0 4.34 15.66m9.9-8.49L11.41 10l2.83 2.83l-1.41 1.41L10 11.41l-2.83 2.83l-1.41-1.41L8.59 10L5.76 7.17l1.41-1.41L10 8.59l2.83-2.83z"/></svg>`),
|
||||
Action: func(ctx context.Context, actionContext plugin.ActionContext) {
|
||||
// peacefully kill the process
|
||||
process, getErr := os.FindProcess(info.Pid)
|
||||
p, getErr := os.FindProcess(info.Pid)
|
||||
if getErr != nil {
|
||||
a.api.Log(ctx, plugin.LogLevelError, fmt.Sprintf("error finding process %d: %s", info.Pid, getErr.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
killErr := process.Kill()
|
||||
killErr := p.Kill()
|
||||
if killErr != nil {
|
||||
a.api.Log(ctx, plugin.LogLevelError, fmt.Sprintf("error killing process %d: %s", info.Pid, killErr.Error()))
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
// refresh cpu and mem
|
||||
result.RefreshInterval = 1000
|
||||
result.OnRefresh = func(ctx context.Context, result plugin.RefreshableResult) plugin.RefreshableResult {
|
||||
result.Tails = a.getRunningProcessResult(info.Pid)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
results = append(results, result)
|
||||
|
@ -209,6 +219,45 @@ func (a *ApplicationPlugin) Query(ctx context.Context, query plugin.Query) []plu
|
|||
return results
|
||||
}
|
||||
|
||||
func (a *ApplicationPlugin) getRunningProcessResult(pid int) (tails []plugin.QueryResultTail) {
|
||||
stat, err := pidusage.GetStat(pid)
|
||||
if err != nil {
|
||||
a.api.Log(context.Background(), plugin.LogLevelError, fmt.Sprintf("error getting process %d stat: %s", pid, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
tails = append(tails, plugin.QueryResultTail{
|
||||
Type: plugin.QueryResultTailTypeText,
|
||||
Text: fmt.Sprintf("CPU: %.1f%%", stat.CPU),
|
||||
})
|
||||
|
||||
memSize := stat.Memory
|
||||
// if mem size is too large, it's probably in bytes, convert it to MB
|
||||
unit := "B"
|
||||
if memSize > 1024*1024*1024 {
|
||||
memSize = memSize / 1024 / 1024 / 1024 // convert to GB
|
||||
unit = "GB"
|
||||
} else if memSize > 1024*1024 {
|
||||
memSize = memSize / 1024 / 1024 // convert to MB
|
||||
unit = "MB"
|
||||
} else if memSize > 1024 {
|
||||
memSize = memSize / 1024 // convert to KB
|
||||
unit = "KB"
|
||||
}
|
||||
|
||||
tails = append(tails, plugin.QueryResultTail{
|
||||
Type: plugin.QueryResultTailTypeText,
|
||||
Text: fmt.Sprintf("Mem: %.1f %s", memSize, unit),
|
||||
})
|
||||
|
||||
tails = append(tails, plugin.QueryResultTail{
|
||||
Type: plugin.QueryResultTailTypeImage,
|
||||
Image: plugin.NewWoxImageEmoji(`🖥️`),
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a *ApplicationPlugin) getRetriever(ctx context.Context) Retriever {
|
||||
return appRetriever
|
||||
}
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
"ResultItemPaddingBottom": 0,
|
||||
"ResultItemTitleColor": "#f0f0f0",
|
||||
"ResultItemSubTitleColor": "#dbd9d9",
|
||||
"ResultItemTailTextColor": "#dbd9d9",
|
||||
"ResultItemBorderLeft": "0",
|
||||
"ResultItemActiveBackgroundColor": "rgba(31, 118, 124, 0.8)",
|
||||
"ResultItemActiveTitleColor": "#f0f0f0",
|
||||
"ResultItemActiveSubTitleColor": "#dbd9d9",
|
||||
"ResultItemActiveTailTextColor": "#dbd9d9",
|
||||
"ResultItemActiveBorderLeft": "0",
|
||||
"QueryBoxFontColor": "#e4e7e7",
|
||||
"QueryBoxBackgroundColor": "rgba(24, 25, 26, 0.4)",
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
"ResultItemPaddingBottom": 0,
|
||||
"ResultItemTitleColor": "#454545",
|
||||
"ResultItemSubTitleColor": "#5f6060",
|
||||
"ResultItemTailTextColor": "#5f6060",
|
||||
"ResultItemBorderLeft": "0",
|
||||
"ResultItemActiveBackgroundColor": "#0061d5",
|
||||
"ResultItemActiveTitleColor": "#ffffff",
|
||||
"ResultItemActiveSubTitleColor": "rgba(236, 240, 240)",
|
||||
"ResultItemActiveTailTextColor": "rgba(236, 240, 240)",
|
||||
"ResultItemActiveBorderLeft": "0",
|
||||
"QueryBoxFontColor": "#000000",
|
||||
"QueryBoxBackgroundColor": "rgba(255,255,255,0.5)",
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
"ResultItemPaddingBottom": 0,
|
||||
"ResultItemTitleColor": "#663399",
|
||||
"ResultItemSubTitleColor": "#999999",
|
||||
"ResultItemTailTextColor": "#999999",
|
||||
"ResultItemBorderLeft": "0",
|
||||
"ResultItemActiveBackgroundColor": "rgba(255, 192, 203, 0.8)",
|
||||
"ResultItemActiveTitleColor": "#663399",
|
||||
"ResultItemActiveSubTitleColor": "#999999",
|
||||
"ResultItemActiveTailTextColor": "#999999",
|
||||
"ResultItemActiveBorderLeft": "0",
|
||||
"QueryBoxFontColor": "#663399",
|
||||
"QueryBoxBackgroundColor": "rgba(255, 235, 205, 0.4)",
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
"ResultItemPaddingBottom": 0,
|
||||
"ResultItemTitleColor": "#455A64",
|
||||
"ResultItemSubTitleColor": "#788494",
|
||||
"ResultItemTailTextColor": "#788494",
|
||||
"ResultItemBorderLeft": "0",
|
||||
"ResultItemActiveBackgroundColor": "rgba(173, 216, 230, 0.8)",
|
||||
"ResultItemActiveTitleColor": "#455A64",
|
||||
"ResultItemActiveSubTitleColor": "#788494",
|
||||
"ResultItemActiveTailTextColor": "#788494",
|
||||
"ResultItemActiveBorderLeft": "0",
|
||||
"QueryBoxFontColor": "#455A64",
|
||||
"QueryBoxBackgroundColor": "rgba(240, 235, 225, 0.4)",
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
"ResultItemPaddingBottom": 0,
|
||||
"ResultItemTitleColor": "#663300",
|
||||
"ResultItemSubTitleColor": "#999999",
|
||||
"ResultItemTailTextColor": "#999999",
|
||||
"ResultItemBorderLeft": "0",
|
||||
"ResultItemActiveBackgroundColor": "rgba(255, 215, 0, 0.8)",
|
||||
"ResultItemActiveTitleColor": "#663300",
|
||||
"ResultItemActiveSubTitleColor": "#999999",
|
||||
"ResultItemActiveTailTextColor": "#999999",
|
||||
"ResultItemActiveBorderLeft": "0",
|
||||
"QueryBoxFontColor": "#663300",
|
||||
"QueryBoxBackgroundColor": "rgba(245, 245, 220, 0.4)",
|
||||
|
|
|
@ -25,11 +25,13 @@ type Theme struct {
|
|||
ResultItemPaddingBottom int
|
||||
ResultItemTitleColor string
|
||||
ResultItemSubTitleColor string
|
||||
ResultItemTailTextColor string
|
||||
ResultItemBorderLeft string
|
||||
ResultItemActiveBackgroundColor string
|
||||
ResultItemActiveTitleColor string
|
||||
ResultItemActiveSubTitleColor string
|
||||
ResultItemActiveBorderLeft string
|
||||
ResultItemActiveTailTextColor string
|
||||
QueryBoxFontColor string
|
||||
QueryBoxBackgroundColor string
|
||||
QueryBoxBorderRadius int
|
||||
|
|
|
@ -26,11 +26,13 @@ type ThemeDto struct {
|
|||
ResultItemPaddingBottom int
|
||||
ResultItemTitleColor string
|
||||
ResultItemSubTitleColor string
|
||||
ResultItemTailTextColor string
|
||||
ResultItemBorderLeft string
|
||||
ResultItemActiveBackgroundColor string
|
||||
ResultItemActiveTitleColor string
|
||||
ResultItemActiveSubTitleColor string
|
||||
ResultItemActiveBorderLeft string
|
||||
ResultItemActiveTailTextColor string
|
||||
QueryBoxFontColor string
|
||||
QueryBoxBackgroundColor string
|
||||
QueryBoxBorderRadius int
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
"ResultItemPaddingBottom": 0,
|
||||
"ResultItemTitleColor": "#f0f0f0",
|
||||
"ResultItemSubTitleColor": "#dbd9d9",
|
||||
"ResultItemTailTextColor": "#dbd9d9",
|
||||
"ResultItemBorderLeft": "0",
|
||||
"ResultItemActiveBackgroundColor": "rgba(31, 118, 124, 0.8)",
|
||||
"ResultItemActiveTitleColor": "#f0f0f0",
|
||||
"ResultItemActiveSubTitleColor": "#dbd9d9",
|
||||
"ResultItemActiveTailTextColor": "#dbd9d9",
|
||||
"ResultItemActiveBorderLeft": "0",
|
||||
"QueryBoxFontColor": "#e4e7e7",
|
||||
"QueryBoxBackgroundColor": "rgba(24, 25, 26, 0.4)",
|
||||
|
|
Loading…
Reference in New Issue