From 42b3c5d8512fb574bc83cb1f12d4454c35e477ac Mon Sep 17 00:00:00 2001 From: Qijia Liu Date: Tue, 30 Jul 2024 00:17:13 -0400 Subject: [PATCH] initial plugin system --- assets/po/zh_CN.po | 176 ++++++++++++++++-------------- fcitx5-webview | 2 +- src/config/config.swift | 3 + src/config/optionmodels.swift | 2 + src/config/optionviews.swift | 7 ++ src/config/pluginoptionview.swift | 34 ++++++ src/config/util.swift | 1 + webpanel/webpanel.cpp | 4 + webpanel/webpanel.h | 14 +++ 9 files changed, 160 insertions(+), 83 deletions(-) create mode 100644 src/config/pluginoptionview.swift diff --git a/assets/po/zh_CN.po b/assets/po/zh_CN.po index 19103a1..86c00b5 100644 --- a/assets/po/zh_CN.po +++ b/assets/po/zh_CN.po @@ -44,330 +44,342 @@ msgstr "轮询剪贴板的间隔(秒)" msgid "Hidden Notifications" msgstr "隐藏通知" -#: webpanel/webpanel.h:68 +#: webpanel/webpanel.h:76 msgid "Follow cursor" msgstr "跟随光标" -#: webpanel/webpanel.h:69 +#: webpanel/webpanel.h:77 msgid "Theme" msgstr "主题" -#: webpanel/webpanel.h:72 +#: webpanel/webpanel.h:80 msgid "User theme" msgstr "用户主题" -#: webpanel/webpanel.h:74 +#: webpanel/webpanel.h:82 msgid "Export current theme" msgstr "导出当前主题" -#: webpanel/webpanel.h:78 webpanel/webpanel.h:125 +#: webpanel/webpanel.h:86 webpanel/webpanel.h:133 msgid "Override default" msgstr "覆盖默认值" -#: webpanel/webpanel.h:79 webpanel/webpanel.h:128 +#: webpanel/webpanel.h:87 webpanel/webpanel.h:136 msgid "Highlight color" msgstr "高亮颜色" -#: webpanel/webpanel.h:82 webpanel/webpanel.h:131 +#: webpanel/webpanel.h:90 webpanel/webpanel.h:139 msgid "Highlight color on hover" msgstr "悬停时高亮颜色" -#: webpanel/webpanel.h:85 webpanel/webpanel.h:134 +#: webpanel/webpanel.h:93 webpanel/webpanel.h:142 msgid "Highlight text color" msgstr "高亮文本颜色" -#: webpanel/webpanel.h:88 webpanel/webpanel.h:137 +#: webpanel/webpanel.h:96 webpanel/webpanel.h:145 msgid "Highlight text color on press" msgstr "按下时高亮文本颜色" -#: webpanel/webpanel.h:91 webpanel/webpanel.h:140 +#: webpanel/webpanel.h:99 webpanel/webpanel.h:148 msgid "Highlight label color" msgstr "高亮标签颜色" -#: webpanel/webpanel.h:94 webpanel/webpanel.h:143 +#: webpanel/webpanel.h:102 webpanel/webpanel.h:151 msgid "Highlight comment color" msgstr "高亮注释颜色" -#: webpanel/webpanel.h:97 webpanel/webpanel.h:146 +#: webpanel/webpanel.h:105 webpanel/webpanel.h:154 msgid "Highlight mark color" msgstr "高亮标记颜色" -#: webpanel/webpanel.h:99 webpanel/webpanel.h:148 +#: webpanel/webpanel.h:107 webpanel/webpanel.h:156 msgid "Panel color" msgstr "面板颜色" -#: webpanel/webpanel.h:101 webpanel/webpanel.h:150 +#: webpanel/webpanel.h:109 webpanel/webpanel.h:158 msgid "Text color" msgstr "文本颜色" -#: webpanel/webpanel.h:103 webpanel/webpanel.h:152 +#: webpanel/webpanel.h:111 webpanel/webpanel.h:160 msgid "Label color" msgstr "标签颜色" -#: webpanel/webpanel.h:105 webpanel/webpanel.h:154 +#: webpanel/webpanel.h:113 webpanel/webpanel.h:162 msgid "Comment color" msgstr "注释颜色" -#: webpanel/webpanel.h:108 webpanel/webpanel.h:157 +#: webpanel/webpanel.h:116 webpanel/webpanel.h:165 msgid "Paging button color" msgstr "翻页按钮颜色" -#: webpanel/webpanel.h:111 webpanel/webpanel.h:160 +#: webpanel/webpanel.h:119 webpanel/webpanel.h:168 msgid "Disabled paging button color" msgstr "禁用的翻页按钮颜色" -#: webpanel/webpanel.h:113 webpanel/webpanel.h:162 +#: webpanel/webpanel.h:121 webpanel/webpanel.h:170 msgid "Preedit color" msgstr "预编辑颜色" -#: webpanel/webpanel.h:116 webpanel/webpanel.h:165 +#: webpanel/webpanel.h:124 webpanel/webpanel.h:173 msgid "Preedit color pre-cursor" msgstr "光标前的预编辑颜色" -#: webpanel/webpanel.h:118 webpanel/webpanel.h:167 +#: webpanel/webpanel.h:126 webpanel/webpanel.h:175 msgid "Border color" msgstr "边框颜色" -#: webpanel/webpanel.h:120 webpanel/webpanel.h:169 +#: webpanel/webpanel.h:128 webpanel/webpanel.h:177 msgid "Divider color" msgstr "分隔线颜色" -#: webpanel/webpanel.h:127 +#: webpanel/webpanel.h:135 msgid "Same with light mode" msgstr "与浅色模式相同" -#: webpanel/webpanel.h:174 +#: webpanel/webpanel.h:182 msgid "Enable scroll" msgstr "启用卷轴" -#: webpanel/webpanel.h:175 +#: webpanel/webpanel.h:183 msgid "Expand" msgstr "展开" -#: webpanel/webpanel.h:176 +#: webpanel/webpanel.h:184 msgid "Collapse" msgstr "折叠" -#: webpanel/webpanel.h:177 +#: webpanel/webpanel.h:185 msgid "Up" msgstr "上" -#: webpanel/webpanel.h:178 +#: webpanel/webpanel.h:186 msgid "Down" msgstr "下" -#: webpanel/webpanel.h:179 +#: webpanel/webpanel.h:187 msgid "Left" msgstr "左" -#: webpanel/webpanel.h:180 +#: webpanel/webpanel.h:188 msgid "Right" msgstr "右" -#: webpanel/webpanel.h:182 +#: webpanel/webpanel.h:190 msgid "Row start" msgstr "行首" -#: webpanel/webpanel.h:183 +#: webpanel/webpanel.h:191 msgid "Row end" msgstr "行尾" -#: webpanel/webpanel.h:185 +#: webpanel/webpanel.h:193 msgid "Page up" msgstr "上一页" -#: webpanel/webpanel.h:187 +#: webpanel/webpanel.h:195 msgid "Page down" msgstr "下一页" -#: webpanel/webpanel.h:189 +#: webpanel/webpanel.h:197 msgid "Commit" msgstr "提交" -#: webpanel/webpanel.h:194 +#: webpanel/webpanel.h:202 msgid "Layout" msgstr "布局" -#: webpanel/webpanel.h:196 +#: webpanel/webpanel.h:204 msgid "Writing mode" msgstr "书写模式" -#: webpanel/webpanel.h:199 +#: webpanel/webpanel.h:207 msgid "Paging buttons style" msgstr "翻页按钮样式" -#: webpanel/webpanel.h:204 +#: webpanel/webpanel.h:212 msgid "Image" msgstr "图片" -#: webpanel/webpanel.h:205 +#: webpanel/webpanel.h:213 msgid "Blur" msgstr "模糊" -#: webpanel/webpanel.h:207 +#: webpanel/webpanel.h:215 msgid "Radius of blur (px)" msgstr "模糊半径(px)" -#: webpanel/webpanel.h:209 +#: webpanel/webpanel.h:217 msgid "Shadow" msgstr "阴影" -#: webpanel/webpanel.h:217 +#: webpanel/webpanel.h:225 msgid "Text font family" msgstr "文本字体族" -#: webpanel/webpanel.h:219 +#: webpanel/webpanel.h:227 msgid "Text font size" msgstr "文本字号" -#: webpanel/webpanel.h:221 +#: webpanel/webpanel.h:229 msgid "Label font family" msgstr "标签字体族" -#: webpanel/webpanel.h:223 +#: webpanel/webpanel.h:231 msgid "Label font size" msgstr "标签字号" -#: webpanel/webpanel.h:225 +#: webpanel/webpanel.h:233 msgid "Comment font family" msgstr "注释字体族" -#: webpanel/webpanel.h:227 +#: webpanel/webpanel.h:235 msgid "Comment font size" msgstr "注释字号" -#: webpanel/webpanel.h:230 +#: webpanel/webpanel.h:238 msgid "Preedit font family" msgstr "预编辑字体族" -#: webpanel/webpanel.h:232 +#: webpanel/webpanel.h:240 msgid "Preedit font size" msgstr "预编辑字号" -#: webpanel/webpanel.h:234 +#: webpanel/webpanel.h:242 msgid "User font dir" msgstr "用户字体目录" -#: webpanel/webpanel.h:235 +#: webpanel/webpanel.h:243 msgid "System font dir" msgstr "系统字体目录" -#: webpanel/webpanel.h:239 +#: webpanel/webpanel.h:247 msgid "Style" msgstr "样式" -#: webpanel/webpanel.h:241 +#: webpanel/webpanel.h:249 msgid "Text" msgstr "文本" -#: webpanel/webpanel.h:245 +#: webpanel/webpanel.h:253 msgid "Mark style" msgstr "标记样式" -#: webpanel/webpanel.h:247 +#: webpanel/webpanel.h:255 msgid "Mark text" msgstr "标记文本" -#: webpanel/webpanel.h:249 +#: webpanel/webpanel.h:257 msgid "Hover behavior" msgstr "悬停行为" -#: webpanel/webpanel.h:254 +#: webpanel/webpanel.h:262 msgid "Border width (px)" msgstr "边框宽度(px)" -#: webpanel/webpanel.h:257 +#: webpanel/webpanel.h:265 msgid "Border radius (px)" msgstr "边框半径(px)" -#: webpanel/webpanel.h:258 +#: webpanel/webpanel.h:266 msgid "Margin (px)" msgstr "外边距(px)" -#: webpanel/webpanel.h:261 +#: webpanel/webpanel.h:269 msgid "Highlight radius (px)" msgstr "高亮半径(px)" -#: webpanel/webpanel.h:264 +#: webpanel/webpanel.h:272 msgid "Top padding (px)" msgstr "顶填充(px)" -#: webpanel/webpanel.h:266 +#: webpanel/webpanel.h:274 msgid "Right padding (px)" msgstr "右填充(px)" -#: webpanel/webpanel.h:268 +#: webpanel/webpanel.h:276 msgid "Bottom padding (px)" msgstr "底填充(px)" -#: webpanel/webpanel.h:271 +#: webpanel/webpanel.h:279 msgid "Left padding (px)" msgstr "左填充(px)" -#: webpanel/webpanel.h:273 +#: webpanel/webpanel.h:281 msgid "Gap between label, text and comment (px)" msgstr "标签、文本、注释间隔(px)" -#: webpanel/webpanel.h:276 +#: webpanel/webpanel.h:284 msgid "Vertical minimum width (px)" msgstr "垂直时最小宽度(px)" -#: webpanel/webpanel.h:279 +#: webpanel/webpanel.h:287 msgid "Horizontal divider width (px)" msgstr "水平分隔线宽度(px)" -#: webpanel/webpanel.h:288 +#: webpanel/webpanel.h:296 msgid "User CSS" msgstr "用户 CSS" -#: webpanel/webpanel.h:290 +#: webpanel/webpanel.h:297 msgid "Copy HTML" msgstr "复制 HTML" -#: webpanel/webpanel.h:291 +#: webpanel/webpanel.h:298 +msgid "Plugin dir" +msgstr "插件目录" + +#: webpanel/webpanel.h:300 +msgid "I know there may be risks for using plugins" +msgstr "我知道使用插件可能有风险" + +#: webpanel/webpanel.h:303 +msgid "Plugins" +msgstr "插件" + +#: webpanel/webpanel.h:305 msgid "Dangerous API for JavaScript plugins" msgstr "用于 JavaScript 插件的危险 API" -#: webpanel/webpanel.h:295 +#: webpanel/webpanel.h:308 msgid "Basic" msgstr "基础" -#: webpanel/webpanel.h:296 +#: webpanel/webpanel.h:309 msgid "Light mode" msgstr "浅色模式" -#: webpanel/webpanel.h:297 +#: webpanel/webpanel.h:310 msgid "Dark mode" msgstr "深色模式" -#: webpanel/webpanel.h:298 +#: webpanel/webpanel.h:311 msgid "Typography" msgstr "版式" -#: webpanel/webpanel.h:299 +#: webpanel/webpanel.h:312 msgid "Scroll mode" msgstr "卷轴模式" -#: webpanel/webpanel.h:300 +#: webpanel/webpanel.h:313 msgid "Background" msgstr "背景" -#: webpanel/webpanel.h:301 +#: webpanel/webpanel.h:314 msgid "Font" msgstr "字体" -#: webpanel/webpanel.h:302 +#: webpanel/webpanel.h:315 msgid "Cursor" msgstr "光标" -#: webpanel/webpanel.h:303 +#: webpanel/webpanel.h:316 msgid "Highlight" msgstr "高亮" -#: webpanel/webpanel.h:304 +#: webpanel/webpanel.h:317 msgid "Size" msgstr "尺寸" -#: webpanel/webpanel.h:305 +#: webpanel/webpanel.h:318 msgid "Advanced" msgstr "高级" diff --git a/fcitx5-webview b/fcitx5-webview index 452209e..067d631 160000 --- a/fcitx5-webview +++ b/fcitx5-webview @@ -1 +1 @@ -Subproject commit 452209ef825cfa1f08d7f6321509aa689671ba1e +Subproject commit 067d631cde44f7109dd95634bb443e6057c99959 diff --git a/src/config/config.swift b/src/config/config.swift index 2f5dbcf..f745525 100644 --- a/src/config/config.swift +++ b/src/config/config.swift @@ -103,6 +103,9 @@ private func jsonToOption(_ json: JSON, _ type: String) throws -> any Option { if let appIM = json["AppIM"].string, appIM == "True" { return try ListOption.decode(json: json) } + if let plugin = json["Plugin"].string, plugin == "True" { + return try ListOption.decode(json: json) + } return try ListOption.decode(json: json) } else if type == "List|Key" { return try ListOption.decode(json: json) diff --git a/src/config/optionmodels.swift b/src/config/optionmodels.swift index 80106fa..d75938c 100644 --- a/src/config/optionmodels.swift +++ b/src/config/optionmodels.swift @@ -333,6 +333,8 @@ class UserThemeOption: StringOption {} class CssOption: StringOption {} +class PluginOption: StringOption {} + private func bundleIdentifier(_ appPath: String) -> String { guard let bundle = Bundle(path: appPath) else { return "" diff --git a/src/config/optionviews.swift b/src/config/optionviews.swift index 377026b..188416d 100644 --- a/src/config/optionviews.swift +++ b/src/config/optionviews.swift @@ -207,6 +207,9 @@ struct ExternalOptionView: OptionView { case "UserDataDir": mkdirP(rimeLocalDir.localPath()) NSWorkspace.shared.open(rimeLocalDir) + case "PluginDir": + mkdirP(pluginDir.localPath()) + NSWorkspace.shared.open(pluginDir) case "CustomPhrase": showCustomPhrase = true case "DictManager": @@ -547,6 +550,8 @@ func buildViewImpl(label: String, option: any Option) -> any OptionView { return CssOptionView(label: label, model: option) } else if let option = option as? AppIMOption { return AppIMOptionView(label: label, model: option) + } else if let option = option as? PluginOption { + return PluginOptionView(label: label, model: option) } else if let option = option as? KeyOption { return KeyOptionView(label: label, model: option) } else if let option = option as? StringOption { @@ -565,6 +570,8 @@ func buildViewImpl(label: String, option: any Option) -> any OptionView { return ListOptionView(label: label, model: option) } else if let option = option as? ListOption { return ListOptionView(label: label, model: option) + } else if let option = option as? ListOption { + return ListOptionView(label: label, model: option) } else if let option = option as? ListOption { return ListOptionView(label: label, model: option) } else if let option = option as? ListOption { diff --git a/src/config/pluginoptionview.swift b/src/config/pluginoptionview.swift new file mode 100644 index 0000000..5594a3c --- /dev/null +++ b/src/config/pluginoptionview.swift @@ -0,0 +1,34 @@ +import Logging +import SwiftUI + +struct PluginOptionView: OptionView { + let label: String + let overrideLabel: String? = nil + @ObservedObject var model: PluginOption + @State private var availablePlugins = [String]() + + var body: some View { + Picker("", selection: $model.value) { + ForEach(availablePlugins, id: \.self) { plugin in + Text(plugin) + } + }.onAppear { + for fileName in getFileNamesWithExtension(pluginDir.localPath()) { + let url = pluginDir.appendingPathComponent(fileName) + if !url.isDirectory { + continue + } + let packageJsonURL = url.appendingPathComponent("package.json") + if let json = readJSON(packageJsonURL) { + if json["license"].stringValue.hasPrefix("GPL-3.0") { + availablePlugins.append(fileName) + } else { + FCITX_WARN("Rejecting plugin \(fileName) which is not GPLv3") + } + } else { + FCITX_WARN("Invalid package.json for plugin \(fileName)") + } + } + } + } +} diff --git a/src/config/util.swift b/src/config/util.swift index 30c453a..261fe13 100644 --- a/src/config/util.swift +++ b/src/config/util.swift @@ -8,6 +8,7 @@ let cacheDir = libraryDir.appendingPathComponent("cache") let configDir = homeDir.appendingPathComponent(".config/fcitx5") let localDir = homeDir.appendingPathComponent(".local/share/fcitx5") let wwwDir = localDir.appendingPathComponent("www") +let pluginDir = wwwDir.appendingPathComponent("plugin") let imLocalDir = localDir.appendingPathComponent("inputmethod") let pinyinLocalDir = localDir.appendingPathComponent("pinyin") let tableLocalDir = localDir.appendingPathComponent("table") diff --git a/webpanel/webpanel.cpp b/webpanel/webpanel.cpp index bc141f8..6794854 100644 --- a/webpanel/webpanel.cpp +++ b/webpanel/webpanel.cpp @@ -231,9 +231,13 @@ void WebPanel::updateConfig() { window_->set_style(style.c_str()); if (auto web = dynamic_cast( window_.get())) { + web->unload_plugins(); using namespace candidate_window; uint64_t apis = (config_.advanced->unsafeAPI->curl.value() ? kCurl : 0); web->set_api(apis); + if (*config_.advanced->pluginNotice) { + web->load_plugins({*config_.advanced->plugins}); + } } } diff --git a/webpanel/webpanel.h b/webpanel/webpanel.h index 461d5a5..0c215e2 100644 --- a/webpanel/webpanel.h +++ b/webpanel/webpanel.h @@ -63,6 +63,14 @@ struct CssAnnotation { } }; +struct PluginAnnotation { + bool skipDescription() { return false; } + bool skipSave() { return false; } + void dumpDescription(RawConfig &config) { + config.setValueByPath("Plugin", "True"); + } +}; + FCITX_CONFIGURATION( BasicConfig, Option followCursor{this, "FollowCursor", _("Follow cursor"), false}; @@ -287,6 +295,12 @@ FCITX_CONFIGURATION( OptionWithAnnotation userCss{ this, "UserCss", _("User CSS"), {}}; Option copyHtml{this, "CopyHtml", _("Copy HTML"), {}}; + ExternalOption pluginDir{this, "PluginDir", _("Plugin dir"), ""}; + Option pluginNotice{this, "PluginNotice", + _("I know there may be risks for using plugins"), + false}; + OptionWithAnnotation, PluginAnnotation> plugins{ + this, "Plugins", _("Plugins"), {}}; Option unsafeAPI{this, "UnsafeAPI", _("Dangerous API for JavaScript plugins")};);