Skip to content

Commit

Permalink
Implement dynamic query icon display for text and file input types
Browse files Browse the repository at this point in the history
Code enhancements have been made to the Wox launcher controller, wox_api, and various UI views to handle dynamic display of query icons based on input type. This update allows for more intuitive user feedback, with specialized icons for file and text input types. Adjustments have also been made to error handling in the plugin manager for improved stability.
  • Loading branch information
qianlifeng committed May 7, 2024
1 parent 49923f1 commit d51916d
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 56 deletions.
7 changes: 7 additions & 0 deletions Wox.UI.Flutter/wox/lib/api/wox_api.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:core';

import 'package:wox/entity/wox_image.dart';
import 'package:wox/entity/wox_plugin.dart';
import 'package:wox/entity/wox_query.dart';
import 'package:wox/entity/wox_setting.dart';
Expand Down Expand Up @@ -90,4 +91,10 @@ class WoxApi {
"query": query.toJson(),
});
}

Future<WoxImage> getQueryIcon(PlainQuery query) async {
return await WoxHttpUtil.instance.postData("/query/icon", {
"query": query.toJson(),
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:from_css_color/from_css_color.dart';
import 'package:get/get.dart';
import 'package:uuid/v4.dart';
import 'package:window_manager/window_manager.dart';
import 'package:wox/api/wox_api.dart';
import 'package:wox/components/wox_image_view.dart';
import 'package:wox/entity/wox_image.dart';
import 'package:wox/enums/wox_image_type_enum.dart';
Expand All @@ -16,28 +17,6 @@ import '../wox_launcher_controller.dart';
class WoxQueryBoxView extends GetView<WoxLauncherController> {
const WoxQueryBoxView({super.key});

Widget getQueryTypeIcon() {
if (controller.getCurrentQuery().queryType == WoxQueryTypeEnum.WOX_QUERY_TYPE_SELECTION.code) {
if (controller.getCurrentQuery().querySelection.type == WoxSelectionTypeEnum.WOX_SELECTION_TYPE_FILE.code) {
return WoxImageView(
woxImage: WoxImage(
imageType: WoxImageTypeEnum.WOX_IMAGE_TYPE_SVG.code,
imageData:
'<svg t="1704957058350" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4383" width="200" height="200"><path d="M127.921872 233.342828H852.118006c24.16765 0 43.960122 19.792472 43.960122 43.960122v522.104578c0 24.16765-19.792472 43.960122-43.960122 43.960122H172.090336c-24.16765 0-43.960122-19.792472-43.960122-43.960122L127.921872 233.342828z" fill="#FFB300" p-id="4384"></path><path d="M156.4647 180.63235h312.721058c15.625636 0 28.334486 13.125534 28.334486 29.376195V233.342828H127.921872v-23.334283c0-16.250661 12.917192-29.376195 28.542828-29.376195z" fill="#FFA000" p-id="4385"></path><path d="M361.889725 258.343845h348.347508v535.855138H312.512716V303.137335z" fill="#FFFFFF" p-id="4386"></path><path d="M170.631943 372.723499h282.719837l59.7941-47.918616H852.118006c23.542625 0 42.710071 19.792472 42.710071 43.960122v430.642523c0 24.16765-19.167447 43.960122-42.710071 43.960122H170.631943c-23.542625 0-42.710071-19.792472-42.710071-43.960122V416.683622c0-24.16765 19.375788-43.960122 42.710071-43.960123z" fill="#FFD54F" p-id="4387"></path><path d="M361.473042 303.76236l-48.960326-0.625025 48.960326-44.79349z" fill="#BDBDBD" p-id="4388"></path></svg>'));
}
if (controller.getCurrentQuery().querySelection.type == WoxSelectionTypeEnum.WOX_SELECTION_TYPE_TEXT.code) {
return WoxImageView(
woxImage: WoxImage(
imageType: WoxImageTypeEnum.WOX_IMAGE_TYPE_SVG.code,
imageData:
'<svg t="1704958243895" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5762" width="200" height="200"><path d="M925.48105 1024H98.092461a98.51895 98.51895 0 0 1-97.879217-98.945439V98.732195A98.732195 98.732195 0 0 1 98.092461 0.426489h827.388589a98.732195 98.732195 0 0 1 98.305706 98.305706v826.322366a98.51895 98.51895 0 0 1-98.305706 98.945439z m-829.094544-959.600167a33.052895 33.052895 0 0 0-32.199917 32.626406v829.734277a32.83965 32.83965 0 0 0 32.199917 33.26614h831.653477a32.83965 32.83965 0 0 0 31.773428-33.26614V97.026239a33.266139 33.266139 0 0 0-32.626406-32.626406z" fill="#0077F0" p-id="5763"></path><path d="M281.69596 230.943773h460.60808v73.569347h-187.655144v488.969596h-85.297792V304.51312h-187.655144z" fill="#0077F0" opacity=".5" p-id="5764"></path></svg>'),
);
}
}

return const SizedBox(width: 24, height: 24);
}

@override
Widget build(BuildContext context) {
if (LoggerSwitch.enablePaintLog) Logger.instance.info(const UuidV4().generate(), "repaint: query box view");
Expand Down Expand Up @@ -138,7 +117,7 @@ class WoxQueryBoxView extends GetView<WoxLauncherController> {
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: getQueryTypeIcon(),
child: WoxImageView(woxImage: controller.queryIcon.value, width: 24, height: 24),
),
)),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import 'package:lpinyin/lpinyin.dart';
import 'package:uuid/v4.dart';
import 'package:window_manager/window_manager.dart';
import 'package:wox/api/wox_api.dart';
import 'package:wox/components/wox_image_view.dart';
import 'package:wox/entity/wox_image.dart';
import 'package:wox/entity/wox_preview.dart';
import 'package:wox/entity/wox_query.dart';
import 'package:wox/entity/wox_setting.dart';
import 'package:wox/entity/wox_theme.dart';
import 'package:wox/entity/wox_websocket_msg.dart';
import 'package:wox/enums/wox_direction_enum.dart';
import 'package:wox/enums/wox_event_device_type_enum.dart';
import 'package:wox/enums/wox_image_type_enum.dart';
import 'package:wox/enums/wox_last_query_mode_enum.dart';
import 'package:wox/enums/wox_msg_method_enum.dart';
import 'package:wox/enums/wox_msg_type_enum.dart';
Expand All @@ -32,6 +35,7 @@ import 'package:wox/utils/wox_websocket_msg_util.dart';

class WoxLauncherController extends GetxController implements WoxLauncherInterface {
final _query = PlainQuery.empty().obs;
final queryIcon = WoxImage.empty().obs;
final _activeResultIndex = 0.obs;
final _activeActionIndex = 0.obs;
final _resultItemGlobalKeys = <GlobalKey>[];
Expand All @@ -45,8 +49,6 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa
final resultActionListViewScrollController = ScrollController(initialScrollOffset: 0.0);
final currentPreview = WoxPreview.empty().obs;
final Rx<WoxTheme> woxTheme = WoxThemeUtil.instance.currentTheme.obs;
final activeResultIndex = 0.obs;
final activeActionIndex = 0.obs;
final isShowActionPanel = false.obs;
final isShowPreviewPanel = false.obs;
final queryResults = <WoxQueryResult>[].obs;
Expand All @@ -59,7 +61,7 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa
var lastQueryMode = WoxLastQueryModeEnum.WOX_LAST_QUERY_MODE_PRESERVE.code;
var canArrowUpHistory = true;
final isInSettingView = false.obs;
var positionBeforeOpenSetting = Offset(0, 0);
var positionBeforeOpenSetting = const Offset(0, 0);

@override
Future<void> toggleApp(String traceId, ShowAppParams params) async {
Expand Down Expand Up @@ -219,7 +221,7 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa
void onQueryBoxTextChanged(String value) {
canArrowUpHistory = false;

PlainQuery woxChangeQuery = PlainQuery(
PlainQuery plainQuery = PlainQuery(
queryId: const UuidV4().generate(),
queryType: WoxQueryTypeEnum.WOX_QUERY_TYPE_INPUT.code,
queryText: value,
Expand All @@ -228,17 +230,19 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa

// do filter if query type is selection
if (_query.value.queryType == WoxQueryTypeEnum.WOX_QUERY_TYPE_SELECTION.code) {
woxChangeQuery.queryType = WoxQueryTypeEnum.WOX_QUERY_TYPE_SELECTION.code;
woxChangeQuery.querySelection = _query.value.querySelection;
plainQuery.queryType = WoxQueryTypeEnum.WOX_QUERY_TYPE_SELECTION.code;
plainQuery.querySelection = _query.value.querySelection;
}

onQueryChanged(const UuidV4().generate(), woxChangeQuery, "user input changed");
onQueryChanged(const UuidV4().generate(), plainQuery, "user input changed");
}

@override
void onQueryChanged(String traceId, PlainQuery query, String changeReason, {bool moveCursorToEnd = false}) {
Logger.instance.debug(traceId, "query changed: ${query.queryText}, reason: $changeReason");

changeQueryIcon(traceId, query);

//hide setting view if query changed
if (isInSettingView.value) {
isInSettingView.value = false;
Expand Down Expand Up @@ -717,4 +721,31 @@ class WoxLauncherController extends GetxController implements WoxLauncherInterfa

onQueryChanged(const UuidV4().generate(), woxChangeQuery, "user drop files");
}

Future<void> changeQueryIcon(String traceId, PlainQuery query) async {
if (query.queryType == WoxQueryTypeEnum.WOX_QUERY_TYPE_SELECTION.code) {
if (query.querySelection.type == WoxSelectionTypeEnum.WOX_SELECTION_TYPE_FILE.code) {
queryIcon.value = WoxImage(
imageType: WoxImageTypeEnum.WOX_IMAGE_TYPE_SVG.code,
imageData:
'<svg t="1704957058350" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4383" width="200" height="200"><path d="M127.921872 233.342828H852.118006c24.16765 0 43.960122 19.792472 43.960122 43.960122v522.104578c0 24.16765-19.792472 43.960122-43.960122 43.960122H172.090336c-24.16765 0-43.960122-19.792472-43.960122-43.960122L127.921872 233.342828z" fill="#FFB300" p-id="4384"></path><path d="M156.4647 180.63235h312.721058c15.625636 0 28.334486 13.125534 28.334486 29.376195V233.342828H127.921872v-23.334283c0-16.250661 12.917192-29.376195 28.542828-29.376195z" fill="#FFA000" p-id="4385"></path><path d="M361.889725 258.343845h348.347508v535.855138H312.512716V303.137335z" fill="#FFFFFF" p-id="4386"></path><path d="M170.631943 372.723499h282.719837l59.7941-47.918616H852.118006c23.542625 0 42.710071 19.792472 42.710071 43.960122v430.642523c0 24.16765-19.167447 43.960122-42.710071 43.960122H170.631943c-23.542625 0-42.710071-19.792472-42.710071-43.960122V416.683622c0-24.16765 19.375788-43.960122 42.710071-43.960123z" fill="#FFD54F" p-id="4387"></path><path d="M361.473042 303.76236l-48.960326-0.625025 48.960326-44.79349z" fill="#BDBDBD" p-id="4388"></path></svg>');
return;
}
if (query.querySelection.type == WoxSelectionTypeEnum.WOX_SELECTION_TYPE_TEXT.code) {
queryIcon.value = WoxImage(
imageType: WoxImageTypeEnum.WOX_IMAGE_TYPE_SVG.code,
imageData:
'<svg t="1704958243895" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5762" width="200" height="200"><path d="M925.48105 1024H98.092461a98.51895 98.51895 0 0 1-97.879217-98.945439V98.732195A98.732195 98.732195 0 0 1 98.092461 0.426489h827.388589a98.732195 98.732195 0 0 1 98.305706 98.305706v826.322366a98.51895 98.51895 0 0 1-98.305706 98.945439z m-829.094544-959.600167a33.052895 33.052895 0 0 0-32.199917 32.626406v829.734277a32.83965 32.83965 0 0 0 32.199917 33.26614h831.653477a32.83965 32.83965 0 0 0 31.773428-33.26614V97.026239a33.266139 33.266139 0 0 0-32.626406-32.626406z" fill="#0077F0" p-id="5763"></path><path d="M281.69596 230.943773h460.60808v73.569347h-187.655144v488.969596h-85.297792V304.51312h-187.655144z" fill="#0077F0" opacity=".5" p-id="5764"></path></svg>');
return;
}
}

if (query.queryType == WoxQueryTypeEnum.WOX_QUERY_TYPE_INPUT.code) {
var img = await WoxApi.instance.getQueryIcon(query);
queryIcon.value = img;
return;
}

queryIcon.value = WoxImage.empty();
}
}
3 changes: 3 additions & 0 deletions Wox.UI.Flutter/wox/lib/utils/entity_factory.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:wox/entity/wox_image.dart';
import 'package:wox/entity/wox_plugin.dart';
import 'package:wox/entity/wox_preview.dart';
import 'package:wox/entity/wox_setting.dart';
Expand All @@ -12,6 +13,8 @@ class EntityFactory {
return WoxSetting.fromJson(json) as T;
} else if (T.toString() == "WoxPreview") {
return WoxPreview.fromJson(json) as T;
} else if (T.toString() == "WoxImage") {
return WoxImage.fromJson(json) as T;
} else if (T.toString() == "List<PluginDetail>") {
return (json as List).map((e) => PluginDetail.fromJson(e)).toList() as T;
} else if (T.toString() == "List<WoxSettingTheme>") {
Expand Down
26 changes: 13 additions & 13 deletions Wox/plugin/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,35 +681,35 @@ func (m *Manager) GetUI() share.UI {
return m.ui
}

func (m *Manager) NewQuery(ctx context.Context, changedQuery share.PlainQuery) (Query, error) {
if changedQuery.QueryType == QueryTypeInput {
newQuery := changedQuery.QueryText
func (m *Manager) NewQuery(ctx context.Context, plainQuery share.PlainQuery) (Query, *Instance, error) {
if plainQuery.QueryType == QueryTypeInput {
newQuery := plainQuery.QueryText
woxSetting := setting.GetSettingManager().GetWoxSetting(ctx)
if len(woxSetting.QueryShortcuts) > 0 {
originQuery := changedQuery.QueryText
expandedQuery := m.expandQueryShortcut(ctx, changedQuery.QueryText, woxSetting.QueryShortcuts)
originQuery := plainQuery.QueryText
expandedQuery := m.expandQueryShortcut(ctx, plainQuery.QueryText, woxSetting.QueryShortcuts)
if originQuery != expandedQuery {
logger.Info(ctx, fmt.Sprintf("expand query shortcut: %s -> %s", originQuery, expandedQuery))
newQuery = expandedQuery
}
}
query := newQueryInputWithPlugins(newQuery, GetPluginManager().GetPluginInstances())
query, instance := newQueryInputWithPlugins(newQuery, GetPluginManager().GetPluginInstances())
query.Env.ActiveWindowTitle = m.GetUI().GetActiveWindowName()
return query, nil
return query, instance, nil
}

if changedQuery.QueryType == QueryTypeSelection {
if plainQuery.QueryType == QueryTypeSelection {
query := Query{
Type: QueryTypeSelection,
RawQuery: changedQuery.QueryText,
Search: changedQuery.QueryText,
Selection: changedQuery.QuerySelection,
RawQuery: plainQuery.QueryText,
Search: plainQuery.QueryText,
Selection: plainQuery.QuerySelection,
}
query.Env.ActiveWindowTitle = window.GetActiveWindowName()
return query, nil
return query, nil, nil
}

return Query{}, errors.New("invalid query type")
return Query{}, nil, errors.New("invalid query type")
}

func (m *Manager) expandQueryShortcut(ctx context.Context, query string, queryShorts []setting.QueryShortcut) (newQuery string) {
Expand Down
7 changes: 4 additions & 3 deletions Wox/plugin/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,13 @@ type QueryResultCache struct {
Actions *util.HashMap[string, func(ctx context.Context, actionContext ActionContext)]
}

func newQueryInputWithPlugins(query string, pluginInstances []*Instance) Query {
func newQueryInputWithPlugins(query string, pluginInstances []*Instance) (Query, *Instance) {
var terms = strings.Split(query, " ")
if len(terms) == 0 {
return Query{
Type: QueryTypeInput,
RawQuery: query,
}
}, nil
}

var rawQuery = query
Expand Down Expand Up @@ -220,6 +220,7 @@ func newQueryInputWithPlugins(query string, pluginInstances []*Instance) Query {
triggerKeyword = ""
command = ""
search = rawQuery
pluginInstance = nil
}

return Query{
Expand All @@ -228,5 +229,5 @@ func newQueryInputWithPlugins(query string, pluginInstances []*Instance) Query {
TriggerKeyword: triggerKeyword,
Command: command,
Search: search,
}
}, pluginInstance
}
10 changes: 5 additions & 5 deletions Wox/plugin/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,27 @@ func getFakePluginInstances() []*Instance {
}

func Test_NewQuery(t *testing.T) {
q := newQueryInputWithPlugins("wpm", getFakePluginInstances())
q, _ := newQueryInputWithPlugins("wpm", getFakePluginInstances())
assert.Equal(t, q.TriggerKeyword, "")
assert.Equal(t, q.Command, "")
assert.Equal(t, q.Search, "wpm")

q = newQueryInputWithPlugins("wpm install", getFakePluginInstances())
q, _ = newQueryInputWithPlugins("wpm install", getFakePluginInstances())
assert.Equal(t, q.TriggerKeyword, "wpm")
assert.Equal(t, q.Command, "")
assert.Equal(t, q.Search, "install")

q = newQueryInputWithPlugins("wpm install ", getFakePluginInstances())
q, _ = newQueryInputWithPlugins("wpm install ", getFakePluginInstances())
assert.Equal(t, q.TriggerKeyword, "wpm")
assert.Equal(t, q.Command, "install")
assert.Equal(t, q.Search, "")

q = newQueryInputWithPlugins("wpm install q q1", getFakePluginInstances())
q, _ = newQueryInputWithPlugins("wpm install q q1", getFakePluginInstances())
assert.Equal(t, q.TriggerKeyword, "wpm")
assert.Equal(t, q.Command, "install")
assert.Equal(t, q.Search, "q q1")

q = newQueryInputWithPlugins("other install q q1", getFakePluginInstances())
q, _ = newQueryInputWithPlugins("other install q q1", getFakePluginInstances())
assert.Equal(t, q.TriggerKeyword, "")
assert.Equal(t, q.Command, "")
assert.Equal(t, q.Search, "other install q q1")
Expand Down
3 changes: 2 additions & 1 deletion Wox/plugin/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ func (s *Store) Uninstall(ctx context.Context, plugin *Instance) error {
}
}
if wpmPlugin != nil {
wpmPlugin.Plugin.Query(ctx, newQueryInputWithPlugins("wpm dev.remove "+plugin.DevPluginDirectory, GetPluginManager().GetPluginInstances()))
query, _ := newQueryInputWithPlugins("wpm dev.remove "+plugin.DevPluginDirectory, GetPluginManager().GetPluginInstances())
wpmPlugin.Plugin.Query(ctx, query)
}
} else {
removeErr := os.RemoveAll(plugin.PluginDirectory)
Expand Down
49 changes: 46 additions & 3 deletions Wox/ui/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var routers = map[string]func(w http.ResponseWriter, r *http.Request){
"/backup/restore": handleBackupRestore,
"/backup/all": handleBackupAll,
"/hotkey/available": handleHotkeyAvailable,
"/query/icon": handleQueryIcon,
}

func handleHome(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -664,14 +665,56 @@ func handleOnHide(w http.ResponseWriter, r *http.Request) {
return
}

var changedQuery share.PlainQuery
unmarshalErr := json.Unmarshal([]byte(queryResult.String()), &changedQuery)
var plainQuery share.PlainQuery
unmarshalErr := json.Unmarshal([]byte(queryResult.String()), &plainQuery)
if unmarshalErr != nil {
logger.Error(ctx, unmarshalErr.Error())
writeErrorResponse(w, unmarshalErr.Error())
return
}

GetUIManager().PostOnHide(ctx, changedQuery)
GetUIManager().PostOnHide(ctx, plainQuery)
writeSuccessResponse(w, "")
}

func handleQueryIcon(w http.ResponseWriter, r *http.Request) {
ctx := util.NewTraceContext()

body, _ := io.ReadAll(r.Body)
queryResult := gjson.GetBytes(body, "query")
if !queryResult.Exists() {
writeErrorResponse(w, "query is empty")
return
}

var plainQuery share.PlainQuery
unmarshalErr := json.Unmarshal([]byte(queryResult.String()), &plainQuery)
if unmarshalErr != nil {
logger.Error(ctx, unmarshalErr.Error())
writeErrorResponse(w, unmarshalErr.Error())
return
}

_, pluginInstance, err := plugin.GetPluginManager().NewQuery(ctx, plainQuery)
if err != nil {
logger.Error(ctx, fmt.Sprintf("failed to new query: %s", err.Error()))
writeSuccessResponse(w, plugin.WoxImage{})
return
}

if pluginInstance == nil {
// this query is not for any plugin (now a global query)
writeSuccessResponse(w, plugin.WoxImage{})
return
}

iconImg, parseErr := plugin.ParseWoxImage(pluginInstance.Metadata.Icon)
if parseErr != nil {
logger.Error(ctx, fmt.Sprintf("failed to parse icon: %s", parseErr.Error()))
writeSuccessResponse(w, plugin.WoxImage{})
return
}

iconImage := plugin.ConvertIcon(ctx, iconImg, pluginInstance.PluginDirectory)
writeSuccessResponse(w, iconImage)
}
2 changes: 1 addition & 1 deletion Wox/ui/ui_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func handleWebsocketQuery(ctx context.Context, request WebsocketMsg) {
return
}

query, queryErr := plugin.GetPluginManager().NewQuery(ctx, changedQuery)
query, _, queryErr := plugin.GetPluginManager().NewQuery(ctx, changedQuery)
if queryErr != nil {
logger.Error(ctx, queryErr.Error())
responseUIError(ctx, request, queryErr.Error())
Expand Down

0 comments on commit d51916d

Please sign in to comment.