Skip to content

Commit

Permalink
Improve AI Commands plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
qianlifeng committed Jun 24, 2024
1 parent 28f7ba2 commit 5b0c18c
Show file tree
Hide file tree
Showing 17 changed files with 253 additions and 181 deletions.
5 changes: 5 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_ai.dart';
import 'package:wox/entity/wox_image.dart';
import 'package:wox/entity/wox_plugin.dart';
import 'package:wox/entity/wox_query.dart';
Expand Down Expand Up @@ -104,4 +105,8 @@ class WoxApi {
"arguments": arguments,
});
}

Future<List<AIModel>> findAIModels() async {
return await WoxHttpUtil.instance.postData("/ai/models", null);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:wox/components/wox_tooltip_view.dart';
import 'package:wox/entity/setting/wox_plugin_setting_select.dart';
import 'package:wox/entity/setting/wox_plugin_setting_textbox.dart';

import 'wox_setting_plugin_item_view.dart';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'dart:convert';

import 'package:fluent_ui/fluent_ui.dart';
import 'package:fluent_ui/l10n/generated/fluent_localizations_en.dart';
import 'package:uuid/v4.dart';
import 'package:wox/api/wox_api.dart';
import 'package:wox/components/wox_hotkey_recorder_view.dart';
import 'package:wox/entity/setting/wox_plugin_setting_select.dart';
import 'package:wox/entity/setting/wox_plugin_setting_table.dart';
import 'package:wox/entity/wox_hotkey.dart';
import 'package:wox/utils/picker.dart';
Expand Down Expand Up @@ -111,6 +114,13 @@ class _WoxSettingPluginTableUpdateState extends State<WoxSettingPluginTableUpdat
return max > 0 ? max : 100;
}

Future<List<PluginSettingValueSelectOption>> getSelectionAIModelOptions() async {
final models = await WoxApi.instance.findAIModels();
return models.map((e) {
return PluginSettingValueSelectOption(value: jsonEncode(e), label: "${e.provider} - ${e.name}");
}).toList();
}

Widget buildColumn(PluginSettingValueTableColumn column) {
switch (column.type) {
case PluginSettingValueType.pluginSettingValueTableColumnTypeText:
Expand Down Expand Up @@ -201,6 +211,7 @@ class _WoxSettingPluginTableUpdateState extends State<WoxSettingPluginTableUpdat
value: getValue(column.key),
onChanged: (value) {
updateValue(column.key, value);
setState(() {});
},
items: column.selectOptions.map((e) {
return ComboBoxItem(
Expand All @@ -210,6 +221,31 @@ class _WoxSettingPluginTableUpdateState extends State<WoxSettingPluginTableUpdat
}).toList(),
),
);
case PluginSettingValueType.pluginSettingValueTableColumnTypeSelectAIModel:
return Expanded(
child: FutureBuilder(
future: getSelectionAIModelOptions(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ComboBox<String>(
value: getValue(column.key),
onChanged: (value) {
updateValue(column.key, value);
setState(() {});
},
items: snapshot.data?.map((e) {
return ComboBoxItem(
value: e.value,
child: Text(e.label),
);
}).toList(),
);
} else {
return const SizedBox();
}
},
),
);
case PluginSettingValueType.pluginSettingValueTableColumnTypeWoxImage:
return Text("wox image...");
case PluginSettingValueType.pluginSettingValueTableColumnTypeTextList:
Expand Down Expand Up @@ -321,100 +357,103 @@ class _WoxSettingPluginTableUpdateState extends State<WoxSettingPluginTableUpdat

@override
Widget build(BuildContext context) {
return ContentDialog(
constraints: const BoxConstraints(maxWidth: 800, maxHeight: 600),
content: SingleChildScrollView(
child: Column(children: [
for (var column in columns)
if (!column.hideInUpdate)
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: getMaxColumnWidth(),
return FluentApp(
debugShowCheckedModeBanner: false,
home: ContentDialog(
constraints: const BoxConstraints(maxWidth: 800, maxHeight: 600),
content: SingleChildScrollView(
child: Column(children: [
for (var column in columns)
if (!column.hideInUpdate)
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: getMaxColumnWidth(),
child: Text(
column.label,
style: const TextStyle(overflow: TextOverflow.ellipsis),
textAlign: TextAlign.right,
),
),
const SizedBox(width: 16),
buildColumn(column),
],
),
if (column.tooltip != "")
Padding(
padding: EdgeInsets.only(left: getMaxColumnWidth() + 16, top: 4),
child: Text(
column.label,
style: const TextStyle(overflow: TextOverflow.ellipsis),
textAlign: TextAlign.right,
column.tooltip,
style: TextStyle(color: Colors.grey[90], fontSize: 12),
),
),
const SizedBox(width: 16),
buildColumn(column),
],
),
if (column.tooltip != "")
Padding(
padding: EdgeInsets.only(left: getMaxColumnWidth() + 16, top: 4),
child: Text(
column.tooltip,
style: TextStyle(color: Colors.grey[90], fontSize: 12),
),
),
if (fieldValidationErrors.containsKey(column.key))
Padding(
padding: EdgeInsets.only(left: getMaxColumnWidth() + 16, top: 4),
child: Text(
fieldValidationErrors[column.key]!,
style: TextStyle(color: Colors.red, fontSize: 12),
if (fieldValidationErrors.containsKey(column.key))
Padding(
padding: EdgeInsets.only(left: getMaxColumnWidth() + 16, top: 4),
child: Text(
fieldValidationErrors[column.key]!,
style: TextStyle(color: Colors.red, fontSize: 12),
),
),
),
],
],
),
),
]),
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Button(
child: const Text('Cancel'),
onPressed: () => Navigator.pop(context),
),
]),
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Button(
child: const Text('Cancel'),
onPressed: () => Navigator.pop(context),
),
const SizedBox(width: 16),
FilledButton(
child: const Text('Confirm'),
onPressed: () {
// validate
for (var column in columns) {
if (column.validators.isNotEmpty) {
for (var element in column.validators) {
var errMsg = element.validator.validate(getValue(column.key));
if (errMsg != "") {
fieldValidationErrors[column.key] = errMsg;
} else {
fieldValidationErrors.remove(column.key);
const SizedBox(width: 16),
FilledButton(
child: const Text('Confirm'),
onPressed: () {
// validate
for (var column in columns) {
if (column.validators.isNotEmpty) {
for (var element in column.validators) {
var errMsg = element.validator.validate(getValue(column.key));
if (errMsg != "") {
fieldValidationErrors[column.key] = errMsg;
} else {
fieldValidationErrors.remove(column.key);
}
}
}
}
}
if (fieldValidationErrors.isNotEmpty) {
setState(() {});
return;
}
if (fieldValidationErrors.isNotEmpty) {
setState(() {});
return;
}

// remove empty text list
for (var column in columns) {
if (column.type == PluginSettingValueType.pluginSettingValueTableColumnTypeTextList) {
var columnValues = getValue(column.key);
if (columnValues is List) {
columnValues.removeWhere((element) => element == "");
// remove empty text list
for (var column in columns) {
if (column.type == PluginSettingValueType.pluginSettingValueTableColumnTypeTextList) {
var columnValues = getValue(column.key);
if (columnValues is List) {
columnValues.removeWhere((element) => element == "");
}
}
}
}

widget.onUpdate(widget.item.key, values);
widget.onUpdate(widget.item.key, values);

Navigator.pop(context);
},
),
],
)
],
Navigator.pop(context);
},
),
],
)
],
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:wox/components/wox_image_view.dart';
import 'package:wox/components/wox_tooltip_view.dart';
import 'package:wox/entity/setting/wox_plugin_setting_select.dart';
import 'package:wox/entity/setting/wox_plugin_setting_table.dart';
import 'package:wox/entity/wox_ai.dart';
import 'package:wox/entity/wox_image.dart';
import 'package:flutter/material.dart' as material;

Expand All @@ -16,12 +17,12 @@ import 'wox_setting_plugin_table_update_view.dart';
class WoxSettingPluginTable extends WoxSettingPluginItem {
final PluginSettingValueTable item;
static const String rowUniqueIdKey = "wox_table_row_id";
final tableWidth = 650.0;
final double tableWidth;
final operationWidth = 75.0;
final columnSpacing = 10.0;
final columnTooltipWidth = 20.0;

const WoxSettingPluginTable({super.key, required this.item, required super.value, required super.onUpdate});
const WoxSettingPluginTable({super.key, required this.item, required super.value, required super.onUpdate, this.tableWidth = 650.0});

double calculateColumnWidthForZeroWidth(PluginSettingValueTableColumn column) {
// if there are multiple columns which have width set to 0, we will set the max width to 100 for each column
Expand Down Expand Up @@ -186,6 +187,20 @@ class WoxSettingPluginTable extends WoxSettingPluginItem {
),
);
}
if (column.type == PluginSettingValueType.pluginSettingValueTableColumnTypeSelectAIModel) {
var model = AIModel.fromJson(json.decode(value));
return columnWidth(
column: column,
isHeader: false,
isOperation: false,
child: Text(
"${model.provider} - ${model.name}",
style: const TextStyle(
overflow: TextOverflow.ellipsis,
),
),
);
}

return Text("Unknown column type: ${column.type}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class PluginSettingValueSelectOption {
late String label;
late String value;

PluginSettingValueSelectOption({required this.label, required this.value});

PluginSettingValueSelectOption.fromJson(Map<String, dynamic> json) {
label = json['Label'];
value = json['Value'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class PluginSettingValueType {
static const pluginSettingValueTableColumnTypeCheckbox = "checkbox";
static const pluginSettingValueTableColumnTypeDirPath = "dirPath";
static const pluginSettingValueTableColumnTypeSelect = "select";
static const pluginSettingValueTableColumnTypeSelectAIModel = "selectAIModel";
static const pluginSettingValueTableColumnTypeWoxImage = "woxImage";
static const pluginSettingValueTableColumnTypeHotkey = "hotkey";
}
Expand Down
18 changes: 18 additions & 0 deletions Wox.UI.Flutter/wox/lib/entity/wox_ai.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class AIModel {
late String name;
late String provider;

AIModel({required this.name, required this.provider});

AIModel.fromJson(Map<String, dynamic> json) {
name = json['Name'];
provider = json['Provider'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['Name'] = name;
data['Provider'] = provider;
return data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class WoxSettingAIView extends GetView<WoxSettingController> {
child: Obx(() {
return WoxSettingPluginTable(
value: json.encode(controller.woxSetting.value.aiProviders),
tableWidth: 750,
item: PluginSettingValueTable.fromJson({
"Key": "AIProviders",
"Columns": [
Expand Down Expand Up @@ -98,7 +99,13 @@ class WoxSettingAIView extends GetView<WoxSettingController> {
{"Type": "not_empty"}
],
},
{"Key": "Host", "Label": "Host", "Tooltip": "The host of the AI provider.", "Width": 60, "Type": "text"}
{
"Key": "Host",
"Label": "Host",
"Tooltip": "The host of the AI provider.",
"Width": 200,
"Type": "text",
}
],
"SortColumnKey": "Name"
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,13 @@ class WoxSettingPluginView extends GetView<WoxSettingController> {
'E.g. you are using google chrome to view webpages, you activate Wox and this plugin will get the active window name as "Google Chrome"',
);
}
if (e == "requireActiveWindowPid") {
return privacyItem(
material.Icons.window,
'Active window process id',
'E.g. you are using google chrome to view webpages, you activate Wox and this plugin will get the active window process id as "1234"',
);
}
if (e == "requireActiveBrowserUrl") {
return privacyItem(
material.Icons.web_sharp,
Expand Down
Loading

0 comments on commit 5b0c18c

Please sign in to comment.