Add tail component to query result

This commit is contained in:
qianlifeng 2024-07-05 22:10:34 +08:00
parent b10322f1d7
commit 213671919a
No known key found for this signature in database
23 changed files with 247 additions and 14 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@wox-launcher/wox-plugin", "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", "description": "All nodejs plugin for Wox should use types in this package",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -85,6 +85,7 @@ export interface Result {
Score?: number Score?: number
Group?: string Group?: string
GroupScore?: number GroupScore?: number
Tails?: ResultTail[]
ContextData?: string ContextData?: string
Actions?: ResultAction[] Actions?: ResultAction[]
// refresh result after specified interval, in milliseconds. If this value is 0, Wox will not refresh this result // 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> OnRefresh?: (current: RefreshableResult) => Promise<RefreshableResult>
} }
export interface ResultTail {
Type: "text" | "image"
Text: string
Image: WoxImage
}
export interface RefreshableResult { export interface RefreshableResult {
Title: string Title: string
SubTitle: string SubTitle: string

View File

@ -30,7 +30,7 @@ class WoxImageView extends StatelessWidget {
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_SVG.code) { } else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_SVG.code) {
return SvgPicture.string(woxImage.imageData, width: width, height: height); return SvgPicture.string(woxImage.imageData, width: width, height: height);
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_EMOJI.code) { } 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) { } else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_BASE64.code) {
if (!woxImage.imageData.contains(";base64,")) { if (!woxImage.imageData.contains(";base64,")) {
return Text("Invalid image data: ${woxImage.imageData}", style: const TextStyle(color: Colors.red)); return Text("Invalid image data: ${woxImage.imageData}", style: const TextStyle(color: Colors.red));

View File

@ -4,15 +4,19 @@ import 'package:get/get.dart';
import 'package:uuid/v4.dart'; import 'package:uuid/v4.dart';
import 'package:wox/components/wox_image_view.dart'; import 'package:wox/components/wox_image_view.dart';
import 'package:wox/entity/wox_image.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/entity/wox_theme.dart';
import 'package:wox/enums/wox_list_view_type_enum.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/log.dart';
import 'package:wox/utils/wox_setting_util.dart';
class WoxListItemView extends StatelessWidget { class WoxListItemView extends StatelessWidget {
final bool isActive; final bool isActive;
final Rx<WoxImage> icon; final Rx<WoxImage> icon;
final Rx<String> title; final Rx<String> title;
final Rx<String> subTitle; final Rx<String> subTitle;
final RxList<WoxQueryResultTail> tails;
final WoxTheme woxTheme; final WoxTheme woxTheme;
final WoxListViewType listViewType; final WoxListViewType listViewType;
final bool isGroup; final bool isGroup;
@ -23,6 +27,7 @@ class WoxListItemView extends StatelessWidget {
required this.icon, required this.icon,
required this.title, required this.title,
required this.subTitle, required this.subTitle,
required this.tails,
required this.isActive, required this.isActive,
required this.listViewType, required this.listViewType,
required this.isGroup, 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,
),
),
],
),
);
}),
),
),
], ],
), ),
); );

View File

@ -91,7 +91,9 @@ class WoxQueryResult {
late int score; late int score;
late String group; late String group;
late int groupScore; late int groupScore;
late RxList<WoxQueryResultTail> tails;
late String contextData; late String contextData;
late List<WoxResultAction> actions; late List<WoxResultAction> actions;
late int refreshInterval; late int refreshInterval;
@ -108,6 +110,7 @@ class WoxQueryResult {
required this.score, required this.score,
required this.group, required this.group,
required this.groupScore, required this.groupScore,
required this.tails,
required this.contextData, required this.contextData,
required this.actions, required this.actions,
required this.refreshInterval, required this.refreshInterval,
@ -123,6 +126,7 @@ class WoxQueryResult {
score = 0; score = 0;
group = ""; group = "";
groupScore = 0; groupScore = 0;
tails = RxList<WoxQueryResultTail>();
contextData = ""; contextData = "";
actions = <WoxResultAction>[]; actions = <WoxResultAction>[];
refreshInterval = 0; refreshInterval = 0;
@ -140,12 +144,25 @@ class WoxQueryResult {
group = json['Group']; group = json['Group'];
groupScore = json['GroupScore']; groupScore = json['GroupScore'];
contextData = json['ContextData']; 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) { if (json['Actions'] != null) {
actions = <WoxResultAction>[]; actions = <WoxResultAction>[];
json['Actions'].forEach((v) { json['Actions'].forEach((v) {
actions.add(WoxResultAction.fromJson(v)); actions.add(WoxResultAction.fromJson(v));
}); });
} else {
actions = <WoxResultAction>[];
} }
refreshInterval = json['RefreshInterval']; refreshInterval = json['RefreshInterval'];
isGroup = false; 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 { class WoxResultAction {
late String id; late String id;
late Rx<String> name; late Rx<String> name;
@ -257,11 +296,20 @@ class WoxRefreshableResult {
late String subTitle; late String subTitle;
late WoxImage icon; late WoxImage icon;
late WoxPreview preview; late WoxPreview preview;
late List<WoxQueryResultTail> tails;
late String contextData; late String contextData;
late int refreshInterval; late int refreshInterval;
WoxRefreshableResult( WoxRefreshableResult({
{required this.resultId, required this.title, required this.subTitle, required this.icon, required this.preview, required this.contextData, required this.refreshInterval}); 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) { WoxRefreshableResult.fromJson(Map<String, dynamic> json) {
resultId = json['ResultId']; resultId = json['ResultId'];
@ -269,6 +317,12 @@ class WoxRefreshableResult {
subTitle = json['SubTitle'] ?? ""; subTitle = json['SubTitle'] ?? "";
icon = WoxImage.fromJson(json['Icon']); icon = WoxImage.fromJson(json['Icon']);
preview = WoxPreview.fromJson(json['Preview']); preview = WoxPreview.fromJson(json['Preview']);
tails = <WoxQueryResultTail>[];
if (json['Tails'] != null) {
json['Tails'].forEach((v) {
tails.add(WoxQueryResultTail.fromJson(v));
});
}
contextData = json['ContextData']; contextData = json['ContextData'];
refreshInterval = json['RefreshInterval']; refreshInterval = json['RefreshInterval'];
} }
@ -280,6 +334,7 @@ class WoxRefreshableResult {
data['SubTitle'] = subTitle; data['SubTitle'] = subTitle;
data['Icon'] = icon.toJson(); data['Icon'] = icon.toJson();
data['Preview'] = preview.toJson(); data['Preview'] = preview.toJson();
data['Tails'] = tails.map((v) => v.toJson()).toList();
data['ContextData'] = contextData; data['ContextData'] = contextData;
data['RefreshInterval'] = refreshInterval; data['RefreshInterval'] = refreshInterval;
return data; return data;

View File

@ -22,11 +22,13 @@ class WoxTheme {
late int resultItemPaddingBottom; late int resultItemPaddingBottom;
late String resultItemTitleColor; late String resultItemTitleColor;
late String resultItemSubTitleColor; late String resultItemSubTitleColor;
late String resultItemTailTextColor;
late String resultItemBorderLeft; late String resultItemBorderLeft;
late String resultItemActiveBackgroundColor; late String resultItemActiveBackgroundColor;
late String resultItemActiveTitleColor; late String resultItemActiveTitleColor;
late String resultItemActiveSubTitleColor; late String resultItemActiveSubTitleColor;
late String resultItemActiveBorderLeft; late String resultItemActiveBorderLeft;
late String resultItemActiveTailTextColor;
late String queryBoxFontColor; late String queryBoxFontColor;
late String queryBoxBackgroundColor; late String queryBoxBackgroundColor;
late int queryBoxBorderRadius; late int queryBoxBorderRadius;
@ -122,11 +124,13 @@ class WoxTheme {
resultItemPaddingBottom = json['ResultItemPaddingBottom']; resultItemPaddingBottom = json['ResultItemPaddingBottom'];
resultItemTitleColor = json['ResultItemTitleColor']; resultItemTitleColor = json['ResultItemTitleColor'];
resultItemSubTitleColor = json['ResultItemSubTitleColor']; resultItemSubTitleColor = json['ResultItemSubTitleColor'];
resultItemTailTextColor = json['ResultItemTailTextColor'];
resultItemBorderLeft = json['ResultItemBorderLeft']; resultItemBorderLeft = json['ResultItemBorderLeft'];
resultItemActiveBackgroundColor = json['ResultItemActiveBackgroundColor']; resultItemActiveBackgroundColor = json['ResultItemActiveBackgroundColor'];
resultItemActiveTitleColor = json['ResultItemActiveTitleColor']; resultItemActiveTitleColor = json['ResultItemActiveTitleColor'];
resultItemActiveSubTitleColor = json['ResultItemActiveSubTitleColor']; resultItemActiveSubTitleColor = json['ResultItemActiveSubTitleColor'];
resultItemActiveBorderLeft = json['ResultItemActiveBorderLeft']; resultItemActiveBorderLeft = json['ResultItemActiveBorderLeft'];
resultItemActiveTailTextColor = json['ResultItemActiveTailTextColor'];
queryBoxFontColor = json['QueryBoxFontColor']; queryBoxFontColor = json['QueryBoxFontColor'];
queryBoxBackgroundColor = json['QueryBoxBackgroundColor']; queryBoxBackgroundColor = json['QueryBoxBackgroundColor'];
queryBoxBorderRadius = json['QueryBoxBorderRadius']; queryBoxBorderRadius = json['QueryBoxBorderRadius'];
@ -174,11 +178,13 @@ class WoxTheme {
data['ResultItemPaddingBottom'] = resultItemPaddingBottom; data['ResultItemPaddingBottom'] = resultItemPaddingBottom;
data['ResultItemTitleColor'] = resultItemTitleColor; data['ResultItemTitleColor'] = resultItemTitleColor;
data['ResultItemSubTitleColor'] = resultItemSubTitleColor; data['ResultItemSubTitleColor'] = resultItemSubTitleColor;
data['ResultItemTailTextColor'] = resultItemTailTextColor;
data['ResultItemBorderLeft'] = resultItemBorderLeft; data['ResultItemBorderLeft'] = resultItemBorderLeft;
data['ResultItemActiveBackgroundColor'] = resultItemActiveBackgroundColor; data['ResultItemActiveBackgroundColor'] = resultItemActiveBackgroundColor;
data['ResultItemActiveTitleColor'] = resultItemActiveTitleColor; data['ResultItemActiveTitleColor'] = resultItemActiveTitleColor;
data['ResultItemActiveSubTitleColor'] = resultItemActiveSubTitleColor; data['ResultItemActiveSubTitleColor'] = resultItemActiveSubTitleColor;
data['ResultItemActiveBorderLeft'] = resultItemActiveBorderLeft; data['ResultItemActiveBorderLeft'] = resultItemActiveBorderLeft;
data['ResultItemActiveTailTextColor'] = resultItemActiveTailTextColor;
data['QueryBoxFontColor'] = queryBoxFontColor; data['QueryBoxFontColor'] = queryBoxFontColor;
data['QueryBoxBackgroundColor'] = queryBoxBackgroundColor; data['QueryBoxBackgroundColor'] = queryBoxBackgroundColor;
data['QueryBoxBorderRadius'] = queryBoxBorderRadius; data['QueryBoxBorderRadius'] = queryBoxBorderRadius;

View File

@ -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;
}

View File

@ -38,6 +38,7 @@ class WoxQueryResultView extends GetView<WoxLauncherController> {
woxTheme: controller.woxTheme.value, woxTheme: controller.woxTheme.value,
icon: woxResultAction.icon, icon: woxResultAction.icon,
title: woxResultAction.name, title: woxResultAction.name,
tails: RxList<WoxQueryResultTail>(),
subTitle: "".obs, subTitle: "".obs,
isActive: controller.isResultActionActiveByIndex(index), isActive: controller.isResultActionActiveByIndex(index),
listViewType: WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_ACTION.code, listViewType: WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_ACTION.code,
@ -123,6 +124,7 @@ class WoxQueryResultView extends GetView<WoxLauncherController> {
woxTheme: controller.woxTheme.value, woxTheme: controller.woxTheme.value,
icon: woxQueryResult.icon, icon: woxQueryResult.icon,
title: woxQueryResult.title, title: woxQueryResult.title,
tails: woxQueryResult.tails,
subTitle: woxQueryResult.subTitle, subTitle: woxQueryResult.subTitle,
isActive: controller.isQueryResultActiveByIndex(index), isActive: controller.isQueryResultActiveByIndex(index),
listViewType: WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_RESULT.code, listViewType: WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_RESULT.code,

View File

@ -645,6 +645,7 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa
subTitle: result.subTitle.value, subTitle: result.subTitle.value,
icon: result.icon.value, icon: result.icon.value,
preview: result.preview, preview: result.preview,
tails: result.tails,
contextData: result.contextData, contextData: result.contextData,
refreshInterval: result.refreshInterval, refreshInterval: result.refreshInterval,
).toJson(), ).toJson(),
@ -669,6 +670,7 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa
result.subTitle.value = refreshResult.subTitle; result.subTitle.value = refreshResult.subTitle;
result.icon.value = refreshResult.icon; result.icon.value = refreshResult.icon;
result.preview = refreshResult.preview; result.preview = refreshResult.preview;
result.tails.assignAll(refreshResult.tails);
// only update preview data when current result is active // only update preview data when current result is active
final resultIndex = queryResults.indexWhere((element) => element.id == result.id); final resultIndex = queryResults.indexWhere((element) => element.id == result.id);

View File

@ -38,10 +38,10 @@ require (
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/struCoder/pidusage v0.2.1
github.com/tidwall/gjson v1.17.1 github.com/tidwall/gjson v1.17.1
github.com/tidwall/pretty v1.2.1 github.com/tidwall/pretty v1.2.1
github.com/tmc/langchaingo v0.1.8 github.com/tmc/langchaingo v0.1.8
github.com/webview/webview_go v0.0.0-20240220051247-56f456ca3a43
github.com/wissance/stringFormatter v1.2.0 github.com/wissance/stringFormatter v1.2.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.design/x/hotkey v0.4.1 golang.design/x/hotkey v0.4.1

View File

@ -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.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 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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 h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= 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= 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/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 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA=
github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= 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 h1:lB0zcJkTA1O4Eb2qSTJmyapla/LihQt6NpJLghwWSb0=
github.com/wissance/stringFormatter v1.2.0/go.mod h1:H7Mz15+5i8ypmv6bLknM/uD+U1teUW99PlW0DNCNscA= 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= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=

View File

@ -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 { func (m *Manager) PolishRefreshableResult(ctx context.Context, pluginInstance *Instance, resultId string, result RefreshableResult) RefreshableResult {
// convert icon // convert icon
result.Icon = ConvertIcon(ctx, result.Icon, pluginInstance.PluginDirectory) 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 // translate title
result.Title = m.translatePlugin(ctx, pluginInstance, result.Title) result.Title = m.translatePlugin(ctx, pluginInstance, result.Title)
// translate subtitle // translate subtitle
result.SubTitle = m.translatePlugin(ctx, pluginInstance, result.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 // translate preview properties
var previewProperties = make(map[string]string) var previewProperties = make(map[string]string)
for key, value := range result.Preview.PreviewProperties { for key, value := range result.Preview.PreviewProperties {
@ -928,6 +940,7 @@ func (m *Manager) ExecuteRefresh(ctx context.Context, refreshableResultWithId Re
Title: newResult.Title, Title: newResult.Title,
SubTitle: newResult.SubTitle, SubTitle: newResult.SubTitle,
Icon: newResult.Icon, Icon: newResult.Icon,
Tails: newResult.Tails,
Preview: newResult.Preview, Preview: newResult.Preview,
ContextData: newResult.ContextData, ContextData: newResult.ContextData,
RefreshInterval: newResult.RefreshInterval, RefreshInterval: newResult.RefreshInterval,

View File

@ -9,6 +9,7 @@ import (
type QueryType = string type QueryType = string
type QueryVariable = string type QueryVariable = string
type QueryResultTailType = string
const ( const (
QueryTypeInput QueryType = "input" // user input query QueryTypeInput QueryType = "input" // user input query
@ -20,6 +21,11 @@ const (
QueryVariableActiveBrowserUrl QueryVariable = "{wox:active_browser_url}" 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. // Query from Wox. See "Doc/Query.md" for details.
type Query struct { type Query struct {
// By default, Wox will only pass QueryTypeInput query to plugin. // By default, Wox will only pass QueryTypeInput query to plugin.
@ -90,9 +96,13 @@ type QueryResult struct {
Icon WoxImage Icon WoxImage
Preview WoxPreview Preview WoxPreview
// Score of the result, the higher the score, the more relevant the result is, more likely to be displayed on top // Score of the result, the higher the score, the more relevant the result is, more likely to be displayed on top
Score int64 Score int64
Group string // 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 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 // Additional data associate with this result, can be retrieved in Action function
ContextData string ContextData string
Actions []QueryResultAction Actions []QueryResultAction
@ -104,6 +114,12 @@ type QueryResult struct {
OnRefresh func(ctx context.Context, current RefreshableResult) RefreshableResult 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 { 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 // Result id, should be unique. It's optional, if you don't set it, Wox will assign a random id for you
Id string Id string
@ -133,6 +149,7 @@ func (q *QueryResult) ToUI() QueryResultUI {
Score: q.Score, Score: q.Score,
Group: q.Group, Group: q.Group,
GroupScore: q.GroupScore, GroupScore: q.GroupScore,
Tails: q.Tails,
ContextData: q.ContextData, ContextData: q.ContextData,
Actions: lo.Map(q.Actions, func(action QueryResultAction, index int) QueryResultActionUI { Actions: lo.Map(q.Actions, func(action QueryResultAction, index int) QueryResultActionUI {
return QueryResultActionUI{ return QueryResultActionUI{
@ -157,6 +174,7 @@ type QueryResultUI struct {
Score int64 Score int64
Group string Group string
GroupScore int64 GroupScore int64
Tails []QueryResultTail
ContextData string ContextData string
Actions []QueryResultActionUI Actions []QueryResultActionUI
RefreshInterval int RefreshInterval int

View File

@ -5,6 +5,7 @@ type RefreshableResult struct {
SubTitle string SubTitle string
Icon WoxImage Icon WoxImage
Preview WoxPreview Preview WoxPreview
Tails []QueryResultTail
ContextData string ContextData string
RefreshInterval int // set to 0 if you don't want to refresh this result anymore RefreshInterval int // set to 0 if you don't want to refresh this result anymore
} }
@ -15,6 +16,7 @@ type RefreshableResultWithResultId struct {
SubTitle string SubTitle string
Icon WoxImage Icon WoxImage
Preview WoxPreview Preview WoxPreview
Tails []QueryResultTail
ContextData string ContextData string
RefreshInterval int RefreshInterval int
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/struCoder/pidusage"
"github.com/tidwall/pretty" "github.com/tidwall/pretty"
"os" "os"
"path" "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) isNameMatch, nameScore := system.IsStringMatchScore(ctx, info.Name, query.Search)
isPathNameMatch, pathNameScore := system.IsStringMatchScore(ctx, filepath.Base(info.Path), query.Search) isPathNameMatch, pathNameScore := system.IsStringMatchScore(ctx, filepath.Base(info.Path), query.Search)
if isNameMatch || isPathNameMatch { if isNameMatch || isPathNameMatch {
subTitle := info.Path var tails []plugin.QueryResultTail
// get cpu and mem info
if info.IsRunning() { if info.IsRunning() {
subTitle = fmt.Sprintf("%s, pid: %d", subTitle, info.Pid) tails = a.getRunningProcessResult(info.Pid)
} }
result := plugin.QueryResult{ result := plugin.QueryResult{
Id: uuid.NewString(), Id: uuid.NewString(),
Title: info.Name, Title: info.Name,
SubTitle: subTitle, SubTitle: info.Path,
Icon: info.Icon, Icon: info.Icon,
Tails: tails,
Score: util.MaxInt64(nameScore, pathNameScore), Score: util.MaxInt64(nameScore, pathNameScore),
Preview: plugin.WoxPreview{ Preview: plugin.WoxPreview{
PreviewType: plugin.WoxPreviewTypeText, 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>`), 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) { Action: func(ctx context.Context, actionContext plugin.ActionContext) {
// peacefully kill the process // peacefully kill the process
process, getErr := os.FindProcess(info.Pid) p, getErr := os.FindProcess(info.Pid)
if getErr != nil { if getErr != nil {
a.api.Log(ctx, plugin.LogLevelError, fmt.Sprintf("error finding process %d: %s", info.Pid, getErr.Error())) a.api.Log(ctx, plugin.LogLevelError, fmt.Sprintf("error finding process %d: %s", info.Pid, getErr.Error()))
return return
} }
killErr := process.Kill() killErr := p.Kill()
if killErr != nil { if killErr != nil {
a.api.Log(ctx, plugin.LogLevelError, fmt.Sprintf("error killing process %d: %s", info.Pid, killErr.Error())) 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) results = append(results, result)
@ -209,6 +219,45 @@ func (a *ApplicationPlugin) Query(ctx context.Context, query plugin.Query) []plu
return results 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 { func (a *ApplicationPlugin) getRetriever(ctx context.Context) Retriever {
return appRetriever return appRetriever
} }

View File

@ -23,10 +23,12 @@
"ResultItemPaddingBottom": 0, "ResultItemPaddingBottom": 0,
"ResultItemTitleColor": "#f0f0f0", "ResultItemTitleColor": "#f0f0f0",
"ResultItemSubTitleColor": "#dbd9d9", "ResultItemSubTitleColor": "#dbd9d9",
"ResultItemTailTextColor": "#dbd9d9",
"ResultItemBorderLeft": "0", "ResultItemBorderLeft": "0",
"ResultItemActiveBackgroundColor": "rgba(31, 118, 124, 0.8)", "ResultItemActiveBackgroundColor": "rgba(31, 118, 124, 0.8)",
"ResultItemActiveTitleColor": "#f0f0f0", "ResultItemActiveTitleColor": "#f0f0f0",
"ResultItemActiveSubTitleColor": "#dbd9d9", "ResultItemActiveSubTitleColor": "#dbd9d9",
"ResultItemActiveTailTextColor": "#dbd9d9",
"ResultItemActiveBorderLeft": "0", "ResultItemActiveBorderLeft": "0",
"QueryBoxFontColor": "#e4e7e7", "QueryBoxFontColor": "#e4e7e7",
"QueryBoxBackgroundColor": "rgba(24, 25, 26, 0.4)", "QueryBoxBackgroundColor": "rgba(24, 25, 26, 0.4)",

View File

@ -23,10 +23,12 @@
"ResultItemPaddingBottom": 0, "ResultItemPaddingBottom": 0,
"ResultItemTitleColor": "#454545", "ResultItemTitleColor": "#454545",
"ResultItemSubTitleColor": "#5f6060", "ResultItemSubTitleColor": "#5f6060",
"ResultItemTailTextColor": "#5f6060",
"ResultItemBorderLeft": "0", "ResultItemBorderLeft": "0",
"ResultItemActiveBackgroundColor": "#0061d5", "ResultItemActiveBackgroundColor": "#0061d5",
"ResultItemActiveTitleColor": "#ffffff", "ResultItemActiveTitleColor": "#ffffff",
"ResultItemActiveSubTitleColor": "rgba(236, 240, 240)", "ResultItemActiveSubTitleColor": "rgba(236, 240, 240)",
"ResultItemActiveTailTextColor": "rgba(236, 240, 240)",
"ResultItemActiveBorderLeft": "0", "ResultItemActiveBorderLeft": "0",
"QueryBoxFontColor": "#000000", "QueryBoxFontColor": "#000000",
"QueryBoxBackgroundColor": "rgba(255,255,255,0.5)", "QueryBoxBackgroundColor": "rgba(255,255,255,0.5)",

View File

@ -23,10 +23,12 @@
"ResultItemPaddingBottom": 0, "ResultItemPaddingBottom": 0,
"ResultItemTitleColor": "#663399", "ResultItemTitleColor": "#663399",
"ResultItemSubTitleColor": "#999999", "ResultItemSubTitleColor": "#999999",
"ResultItemTailTextColor": "#999999",
"ResultItemBorderLeft": "0", "ResultItemBorderLeft": "0",
"ResultItemActiveBackgroundColor": "rgba(255, 192, 203, 0.8)", "ResultItemActiveBackgroundColor": "rgba(255, 192, 203, 0.8)",
"ResultItemActiveTitleColor": "#663399", "ResultItemActiveTitleColor": "#663399",
"ResultItemActiveSubTitleColor": "#999999", "ResultItemActiveSubTitleColor": "#999999",
"ResultItemActiveTailTextColor": "#999999",
"ResultItemActiveBorderLeft": "0", "ResultItemActiveBorderLeft": "0",
"QueryBoxFontColor": "#663399", "QueryBoxFontColor": "#663399",
"QueryBoxBackgroundColor": "rgba(255, 235, 205, 0.4)", "QueryBoxBackgroundColor": "rgba(255, 235, 205, 0.4)",

View File

@ -23,10 +23,12 @@
"ResultItemPaddingBottom": 0, "ResultItemPaddingBottom": 0,
"ResultItemTitleColor": "#455A64", "ResultItemTitleColor": "#455A64",
"ResultItemSubTitleColor": "#788494", "ResultItemSubTitleColor": "#788494",
"ResultItemTailTextColor": "#788494",
"ResultItemBorderLeft": "0", "ResultItemBorderLeft": "0",
"ResultItemActiveBackgroundColor": "rgba(173, 216, 230, 0.8)", "ResultItemActiveBackgroundColor": "rgba(173, 216, 230, 0.8)",
"ResultItemActiveTitleColor": "#455A64", "ResultItemActiveTitleColor": "#455A64",
"ResultItemActiveSubTitleColor": "#788494", "ResultItemActiveSubTitleColor": "#788494",
"ResultItemActiveTailTextColor": "#788494",
"ResultItemActiveBorderLeft": "0", "ResultItemActiveBorderLeft": "0",
"QueryBoxFontColor": "#455A64", "QueryBoxFontColor": "#455A64",
"QueryBoxBackgroundColor": "rgba(240, 235, 225, 0.4)", "QueryBoxBackgroundColor": "rgba(240, 235, 225, 0.4)",

View File

@ -23,10 +23,12 @@
"ResultItemPaddingBottom": 0, "ResultItemPaddingBottom": 0,
"ResultItemTitleColor": "#663300", "ResultItemTitleColor": "#663300",
"ResultItemSubTitleColor": "#999999", "ResultItemSubTitleColor": "#999999",
"ResultItemTailTextColor": "#999999",
"ResultItemBorderLeft": "0", "ResultItemBorderLeft": "0",
"ResultItemActiveBackgroundColor": "rgba(255, 215, 0, 0.8)", "ResultItemActiveBackgroundColor": "rgba(255, 215, 0, 0.8)",
"ResultItemActiveTitleColor": "#663300", "ResultItemActiveTitleColor": "#663300",
"ResultItemActiveSubTitleColor": "#999999", "ResultItemActiveSubTitleColor": "#999999",
"ResultItemActiveTailTextColor": "#999999",
"ResultItemActiveBorderLeft": "0", "ResultItemActiveBorderLeft": "0",
"QueryBoxFontColor": "#663300", "QueryBoxFontColor": "#663300",
"QueryBoxBackgroundColor": "rgba(245, 245, 220, 0.4)", "QueryBoxBackgroundColor": "rgba(245, 245, 220, 0.4)",

View File

@ -25,11 +25,13 @@ type Theme struct {
ResultItemPaddingBottom int ResultItemPaddingBottom int
ResultItemTitleColor string ResultItemTitleColor string
ResultItemSubTitleColor string ResultItemSubTitleColor string
ResultItemTailTextColor string
ResultItemBorderLeft string ResultItemBorderLeft string
ResultItemActiveBackgroundColor string ResultItemActiveBackgroundColor string
ResultItemActiveTitleColor string ResultItemActiveTitleColor string
ResultItemActiveSubTitleColor string ResultItemActiveSubTitleColor string
ResultItemActiveBorderLeft string ResultItemActiveBorderLeft string
ResultItemActiveTailTextColor string
QueryBoxFontColor string QueryBoxFontColor string
QueryBoxBackgroundColor string QueryBoxBackgroundColor string
QueryBoxBorderRadius int QueryBoxBorderRadius int

View File

@ -26,11 +26,13 @@ type ThemeDto struct {
ResultItemPaddingBottom int ResultItemPaddingBottom int
ResultItemTitleColor string ResultItemTitleColor string
ResultItemSubTitleColor string ResultItemSubTitleColor string
ResultItemTailTextColor string
ResultItemBorderLeft string ResultItemBorderLeft string
ResultItemActiveBackgroundColor string ResultItemActiveBackgroundColor string
ResultItemActiveTitleColor string ResultItemActiveTitleColor string
ResultItemActiveSubTitleColor string ResultItemActiveSubTitleColor string
ResultItemActiveBorderLeft string ResultItemActiveBorderLeft string
ResultItemActiveTailTextColor string
QueryBoxFontColor string QueryBoxFontColor string
QueryBoxBackgroundColor string QueryBoxBackgroundColor string
QueryBoxBorderRadius int QueryBoxBorderRadius int

View File

@ -22,10 +22,12 @@
"ResultItemPaddingBottom": 0, "ResultItemPaddingBottom": 0,
"ResultItemTitleColor": "#f0f0f0", "ResultItemTitleColor": "#f0f0f0",
"ResultItemSubTitleColor": "#dbd9d9", "ResultItemSubTitleColor": "#dbd9d9",
"ResultItemTailTextColor": "#dbd9d9",
"ResultItemBorderLeft": "0", "ResultItemBorderLeft": "0",
"ResultItemActiveBackgroundColor": "rgba(31, 118, 124, 0.8)", "ResultItemActiveBackgroundColor": "rgba(31, 118, 124, 0.8)",
"ResultItemActiveTitleColor": "#f0f0f0", "ResultItemActiveTitleColor": "#f0f0f0",
"ResultItemActiveSubTitleColor": "#dbd9d9", "ResultItemActiveSubTitleColor": "#dbd9d9",
"ResultItemActiveTailTextColor": "#dbd9d9",
"ResultItemActiveBorderLeft": "0", "ResultItemActiveBorderLeft": "0",
"QueryBoxFontColor": "#e4e7e7", "QueryBoxFontColor": "#e4e7e7",
"QueryBoxBackgroundColor": "rgba(24, 25, 26, 0.4)", "QueryBoxBackgroundColor": "rgba(24, 25, 26, 0.4)",