mirror of
https://github.com/mii443/vrclipboard-ime-gui.git
synced 2025-08-22 16:15:32 +00:00
update to tauri 2.0
This commit is contained in:
119
package-lock.json
generated
119
package-lock.json
generated
@ -8,12 +8,14 @@
|
||||
"name": "vrclipboard-ime-gui",
|
||||
"version": "1.9.0",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1",
|
||||
"@tauri-apps/api": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-shell": "^2.0.0",
|
||||
"@tauri-apps/plugin-updater": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^1",
|
||||
"@tauri-apps/cli": "^2.0.0-rc.18",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
@ -1069,23 +1071,18 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@tauri-apps/api": {
|
||||
"version": "1.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.5.6.tgz",
|
||||
"integrity": "sha512-LH5ToovAHnDVe5Qa9f/+jW28I6DeMhos8bNDtBOmmnaDpPmJmYLyHdeDblAWWWYc7KKRDg9/66vMuKyq0WIeFA==",
|
||||
"engines": {
|
||||
"node": ">= 14.6.0",
|
||||
"npm": ">= 6.6.0",
|
||||
"yarn": ">= 1.19.1"
|
||||
},
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.0.1.tgz",
|
||||
"integrity": "sha512-eoQWT+Tq1qSwQpHV+nw1eNYe5B/nm1PoRjQCRiEOS12I1b+X4PUcREfXVX8dPcBT6GrzWGDtaecY0+1p0Rfqlw==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/tauri"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.14.tgz",
|
||||
"integrity": "sha512-JOSMKymlg116UdEXSj69eg5p1OtZnQkUE0qIGbtNDO1sk3X/KgBN6+oHBW0BzPStp/W0AjBgrMWCqjHPwEpOug==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-43PjSEISHI3uH2jyR7QlEJUv1yQYlCOvm5eEdadhHIooV5Dqjs6zkddwEJuHYRpSLI/IfiQ8VPBYrw/GfyvhCA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tauri": "tauri.js"
|
||||
@ -1098,22 +1095,22 @@
|
||||
"url": "https://opencollective.com/tauri"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tauri-apps/cli-darwin-arm64": "1.5.14",
|
||||
"@tauri-apps/cli-darwin-x64": "1.5.14",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "1.5.14",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "1.5.14",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "1.5.14",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "1.5.14",
|
||||
"@tauri-apps/cli-linux-x64-musl": "1.5.14",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "1.5.14",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "1.5.14",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "1.5.14"
|
||||
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.18",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.14.tgz",
|
||||
"integrity": "sha512-lxoSOp3KKSqzHJa7iT32dukPGMlfsTuja1xXSgwR8o/fqzpYJY7FY/3ZxesP8HR66FcK+vtqa//HNqeOQ0mHkA==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-L2/VQ4q1pZyhqOifarVDJf/+JabU6DSUMj6979wXrUOOxmyfLCZaw5qGGsbirYOfxWMo+qcXEFRF411YIv9qWw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1127,9 +1124,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-x64": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.14.tgz",
|
||||
"integrity": "sha512-EXSwN1n5spfG8FoXuyc90ACtmDJXzaZ1gxyENaq9xEpQoo7j/Q1vb6qXxmr6azKr8zmqY4h08ZFbv3exh93xJg==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-ri0NrRAh2CqejoKym67m9Devpqppnn4SrwWnuqV68oHXan3ibn2CeY+g3ygkb6Ch0v5ZcbxJEtop5fZwUTFH4w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1143,9 +1140,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.14.tgz",
|
||||
"integrity": "sha512-Yb8BH/KYR7Tl+de40sZPfrqbhcU3Jlu+UPIrnXt05sjn48xqIps74Xjz8zzVp0TuHxUp8FmIGtCVhQgsbrsvvg==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-+dDZQIHXufqq3WVrKycudVeJa8xfRzIY2XHSYunWS5RMRx1PrcvLbZLBcm3BMtwuY9pwbzrpDHL4K/1+Maj4JQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -1159,9 +1156,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.14.tgz",
|
||||
"integrity": "sha512-QrKHP4gRaHiup478rPBZ+BmNd88yze9jMmheoNy9mN1K/aECRmTHO+tWhsxv5moFHZzRhO0QDWxxvTtiaPXaGg==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-pti3FmMAJKArbr8FyoU8eFbcRHRcFRaD16crjNfXfGFGUGNXeMcrAAZptDpGZ9fPfMYBQYzUN/uKqHvrlrYFIw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1175,9 +1172,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.14.tgz",
|
||||
"integrity": "sha512-Hb1C1VMxmUcyGjW/K/INKF87zzzgLEVRmWZZnQd7M1P4uue4xPyIwUELSdX12Z2jREPgmLW4AXPD0m6wsNu7iw==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-1e+h543bXRnLLhUwhglnnH6eN4dgtbxKS48oHsBCpLEqLNrovHTHEd1xSZgUAEOh9J9hpIh6Bme7loCwOps9ZQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1191,9 +1188,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.14.tgz",
|
||||
"integrity": "sha512-kD9v/UwPDuhIgq2TJj/s2/7rqk+vmExVV6xHPKI8vVbIvlNAOZqmx3fpxjej1241vhJ/piGd/m6q6YMWGsL0oQ==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-5lwBuY06s5J1iCOZq+hM6spBhaGejkh8zn8HdVjnL0mqZ+cH/qbC1Uss6HO/gC1Q53JQFoYeam2P2/8UuNjlHQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1207,9 +1204,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.14.tgz",
|
||||
"integrity": "sha512-204Drgg9Zx0+THKndqASz4+iPCwqA3gQVF9C0CDIArNXrjPyJjVvW8VP5CHiZYaTNWxlz/ltyxluM6UFWbXNFw==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-jtJ1EP6GhW258MKujampDbPWX+El26m8yGBzEcZxurrhFvN8d3QHgle4eT/cgqlVT+AZ9DVrhDwTfXilGjERZA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1223,9 +1220,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.14.tgz",
|
||||
"integrity": "sha512-sqPSni2MnWNCm+8YZnLdWCclxfSHaYqKuPFSz8q7Tn1G1m/cA9gyPoC1G0esHftY7bu/ZM5lB4kM3I4U0KlLiA==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-E9PSjWwvUnhnW/wjXti0UQgXDYLTUBKWtT2yOS2dXLspmvh1vwdRgZn/AjhjMM2HwZzhBW94Qys06mQAz6z2vg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1239,9 +1236,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.14.tgz",
|
||||
"integrity": "sha512-8xN8W0zTs8oFsQmvYLxHFeqhzVI7oTaPK1xQMc5gbpFP45jN41c21aCXfjnvzT+h90EfCHUF9EWj2HTEJSb7Iw==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-I+r88I/Dyqex7oV1NOtW3kxYoRegjxtQrQLILGsn6xcirTERnX0pPl1GYW5ooTxvs/H+qt4tuW5iL8Fp1lpmuQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@ -1255,9 +1252,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
||||
"version": "1.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.14.tgz",
|
||||
"integrity": "sha512-U0slee5tNM2PYECBpPHavLSwkT3szGMZ+qhcikQQbDan84bQdLn/kHWjyXOgLJs4KSve4+KxcrN+AVqj0VyHnw==",
|
||||
"version": "2.0.0-rc.18",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.18.tgz",
|
||||
"integrity": "sha512-IEl0dDc10ln1rt2SGoNxKiYJIDS/fBsS1hTKT4cfZeeKCgHOqMqpdGq25RaVmkkk0UhW/9WeyjxIyFGO3ll4TA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1270,6 +1267,22 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-shell": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.0.0.tgz",
|
||||
"integrity": "sha512-OpW2+ycgJLrEoZityWeWYk+6ZWP9VyiAfbO+N/O8VfLkqyOym8kXh7odKDfINx9RAotkSGBtQM4abyKfJDkcUg==",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-updater": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.0.0.tgz",
|
||||
"integrity": "sha512-N0cl71g7RPr7zK2Fe5aoIwzw14NcdLcz7XMGFWZVjprsqgDRWoxbnUkknyCQMZthjhGkppCd/wN2MIsUz+eAhQ==",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||
|
@ -10,12 +10,14 @@
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1",
|
||||
"@tauri-apps/api": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-shell": "^2.0.0",
|
||||
"@tauri-apps/plugin-updater": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^1",
|
||||
"@tauri-apps/cli": "^2.0.0-rc.18",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
|
7
src-tauri/2.0.0-rc
Normal file
7
src-tauri/2.0.0-rc
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
added 1 package, and audited 194 packages in 4s
|
||||
|
||||
38 packages are looking for funding
|
||||
run `npm fund` for details
|
||||
|
||||
found 0 vulnerabilities
|
2003
src-tauri/Cargo.lock
generated
2003
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -8,10 +8,10 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1", features = [] }
|
||||
tauri-build = { version = "2.0.0-rc", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "1", features = [ "updater", "window-close", "window-start-dragging", "window-show", "window-unmaximize", "window-minimize", "window-maximize", "window-hide", "window-unminimize", "shell-open"] }
|
||||
tauri = { version = "2.0.0-rc", features = [] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
chrono = "0.4.38"
|
||||
@ -29,6 +29,7 @@ regex = "1"
|
||||
windows-core = "0.58.0"
|
||||
tracing = "0.1"
|
||||
tracing-appender = "0.2"
|
||||
tauri-plugin-shell = "2.0.0-rc"
|
||||
|
||||
[dependencies.tracing-subscriber]
|
||||
version = "0.3.16"
|
||||
@ -49,3 +50,6 @@ features = [
|
||||
[features]
|
||||
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-updater = "2.0.0-rc"
|
||||
|
11
src-tauri/capabilities/desktop.json
Normal file
11
src-tauri/capabilities/desktop.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"identifier": "desktop-capability",
|
||||
"platforms": [
|
||||
"macOS",
|
||||
"windows",
|
||||
"linux"
|
||||
],
|
||||
"permissions": [
|
||||
"updater:default"
|
||||
]
|
||||
}
|
20
src-tauri/capabilities/migrated.json
Normal file
20
src-tauri/capabilities/migrated.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"core:window:allow-maximize",
|
||||
"core:window:allow-unmaximize",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-unminimize",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-start-dragging",
|
||||
"shell:allow-open"
|
||||
]
|
||||
}
|
@ -16,7 +16,9 @@ impl Drop for Com {
|
||||
|
||||
impl Com {
|
||||
pub fn new() -> Result<Self> {
|
||||
unsafe { let _ = CoInitialize(None); };
|
||||
unsafe {
|
||||
let _ = CoInitialize(None);
|
||||
};
|
||||
Ok(Com)
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,25 @@
|
||||
use std::{fs::File, io::{Read, Write}, path::{Path, PathBuf}};
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use platform_dirs::AppDirs;
|
||||
use serde::Serialize;
|
||||
use serde_derive::Deserialize;
|
||||
use anyhow::Result;
|
||||
use tauri::State;
|
||||
use tracing::{info, error, debug, trace};
|
||||
use tracing::{debug, error, info, trace};
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
#[serde(default = "semicolon" )]
|
||||
#[serde(default = "semicolon")]
|
||||
pub prefix: String,
|
||||
#[serde(default = "slash" )]
|
||||
#[serde(default = "slash")]
|
||||
pub split: String,
|
||||
#[serde(default = "semicolon" )]
|
||||
#[serde(default = "semicolon")]
|
||||
pub command: String,
|
||||
#[serde(default = "bool_true")]
|
||||
pub ignore_prefix: bool,
|
||||
@ -45,19 +49,27 @@ impl Default for Config {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slash() -> String { String::from("/") }
|
||||
fn slash() -> String {
|
||||
String::from("/")
|
||||
}
|
||||
#[inline]
|
||||
fn semicolon() -> String { String::from(";") }
|
||||
fn semicolon() -> String {
|
||||
String::from(";")
|
||||
}
|
||||
#[inline]
|
||||
fn bool_true() -> bool { true }
|
||||
fn bool_true() -> bool {
|
||||
true
|
||||
}
|
||||
#[inline]
|
||||
fn bool_false() -> bool { false }
|
||||
fn bool_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub enum OnCopyMode {
|
||||
ReturnToClipboard,
|
||||
ReturnToChatbox,
|
||||
SendDirectly
|
||||
SendDirectly,
|
||||
}
|
||||
|
||||
impl Default for OnCopyMode {
|
||||
@ -94,8 +106,8 @@ impl Config {
|
||||
Ok(file) => file,
|
||||
Err(e) => {
|
||||
error!("Failed to create config file: {}", e);
|
||||
return Err(format!("Failed to create config file: {}", e))
|
||||
},
|
||||
return Err(format!("Failed to create config file: {}", e));
|
||||
}
|
||||
};
|
||||
|
||||
match serde_yaml::to_string(&self) {
|
||||
@ -109,11 +121,11 @@ impl Config {
|
||||
*app_config = self.clone();
|
||||
info!("Config saved successfully");
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to serialize config: {}", e);
|
||||
Err(format!("Failed to serialize config: {}", e))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::{config::Config, converter::converter::{get_custom_converter, Converter}, STATE};
|
||||
use crate::{
|
||||
config::Config,
|
||||
converter::converter::{get_custom_converter, Converter},
|
||||
STATE,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use tracing::{info, debug, trace, warn};
|
||||
use tracing::{debug, info, trace, warn};
|
||||
|
||||
pub struct ConversionBlock {
|
||||
pub text: String,
|
||||
@ -29,7 +33,12 @@ impl Conversion {
|
||||
for (index, block) in blocks.iter().enumerate() {
|
||||
trace!("Processing block {}/{}", index + 1, blocks.len());
|
||||
let converted = self.convert_block(&block)?;
|
||||
debug!("Converted block - {}: {} -> {}", block.converter.name(), block.text, converted);
|
||||
debug!(
|
||||
"Converted block - {}: {} -> {}",
|
||||
block.converter.name(),
|
||||
block.text,
|
||||
converted
|
||||
);
|
||||
result.push_str(&converted);
|
||||
trace!("Current result length: {}", result.len());
|
||||
}
|
||||
@ -56,7 +65,11 @@ impl Conversion {
|
||||
let mut current_converter = 'r';
|
||||
|
||||
let config = self.get_config();
|
||||
trace!("Config command: {}, split: {}", config.command, config.split);
|
||||
trace!(
|
||||
"Config command: {}, split: {}",
|
||||
config.command,
|
||||
config.split
|
||||
);
|
||||
|
||||
if text.starts_with(&config.command) {
|
||||
trace!("Text starts with command");
|
||||
@ -80,20 +93,30 @@ impl Conversion {
|
||||
}
|
||||
|
||||
for splitted in command_splitted.split(&config.split) {
|
||||
trace!("Creating ConversionBlock - text: {}, converter: {}", splitted, current_converter);
|
||||
trace!(
|
||||
"Creating ConversionBlock - text: {}, converter: {}",
|
||||
splitted,
|
||||
current_converter
|
||||
);
|
||||
let converter = get_custom_converter(current_converter).unwrap_or_else(|| {
|
||||
warn!("Failed to get custom converter for '{}', using default", current_converter);
|
||||
warn!(
|
||||
"Failed to get custom converter for '{}', using default",
|
||||
current_converter
|
||||
);
|
||||
get_custom_converter('n').unwrap()
|
||||
});
|
||||
blocks.push(ConversionBlock {
|
||||
text: splitted.to_string(),
|
||||
converter
|
||||
converter,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Split text into {} blocks", blocks.len());
|
||||
trace!("Blocks: {:?}", blocks.iter().map(|b| &b.text).collect::<Vec<_>>());
|
||||
trace!(
|
||||
"Blocks: {:?}",
|
||||
blocks.iter().map(|b| &b.text).collect::<Vec<_>>()
|
||||
);
|
||||
Ok(blocks)
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@ impl Converter for CalculatorConverter {
|
||||
let formatted = format!("{} = {}", text, result.to_string());
|
||||
info!("Evaluation successful: {}", formatted);
|
||||
formatted
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("Evaluation failed: {}", e);
|
||||
e.to_string()
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
|
@ -1,7 +1,10 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use super::{calculator::CalculatorConverter, hiragana::HiraganaConverter, katakana::KatakanaConverter, none_converter::NoneConverter, roman_to_kanji::RomanToKanjiConverter};
|
||||
use super::{
|
||||
calculator::CalculatorConverter, hiragana::HiraganaConverter, katakana::KatakanaConverter,
|
||||
none_converter::NoneConverter, roman_to_kanji::RomanToKanjiConverter,
|
||||
};
|
||||
|
||||
pub trait Converter {
|
||||
fn convert(&self, text: &str) -> Result<String>;
|
||||
|
@ -1,5 +1,7 @@
|
||||
use windows::Win32::UI::Input::Ime::{FELANG_CMODE_HIRAGANAOUT, FELANG_CMODE_NOINVISIBLECHAR, FELANG_CMODE_PRECONV, FELANG_REQ_REV};
|
||||
use tracing::{debug, info, trace};
|
||||
use windows::Win32::UI::Input::Ime::{
|
||||
FELANG_CMODE_HIRAGANAOUT, FELANG_CMODE_NOINVISIBLECHAR, FELANG_CMODE_PRECONV, FELANG_REQ_REV,
|
||||
};
|
||||
|
||||
use crate::felanguage::FElanguage;
|
||||
|
||||
@ -14,7 +16,11 @@ impl Converter for HiraganaConverter {
|
||||
let felanguage = FElanguage::new()?;
|
||||
trace!("FElanguage instance created");
|
||||
|
||||
let result = felanguage.j_morph_result(text, FELANG_REQ_REV, FELANG_CMODE_HIRAGANAOUT | FELANG_CMODE_PRECONV | FELANG_CMODE_NOINVISIBLECHAR);
|
||||
let result = felanguage.j_morph_result(
|
||||
text,
|
||||
FELANG_REQ_REV,
|
||||
FELANG_CMODE_HIRAGANAOUT | FELANG_CMODE_PRECONV | FELANG_CMODE_NOINVISIBLECHAR,
|
||||
);
|
||||
|
||||
match &result {
|
||||
Ok(converted) => info!("Conversion successful: {} -> {}", text, converted),
|
||||
|
@ -1,5 +1,7 @@
|
||||
use windows::Win32::UI::Input::Ime::{FELANG_CMODE_KATAKANAOUT, FELANG_CMODE_NOINVISIBLECHAR, FELANG_CMODE_PRECONV, FELANG_REQ_REV};
|
||||
use tracing::{debug, info, trace};
|
||||
use windows::Win32::UI::Input::Ime::{
|
||||
FELANG_CMODE_KATAKANAOUT, FELANG_CMODE_NOINVISIBLECHAR, FELANG_CMODE_PRECONV, FELANG_REQ_REV,
|
||||
};
|
||||
|
||||
use crate::felanguage::FElanguage;
|
||||
|
||||
@ -14,7 +16,11 @@ impl Converter for KatakanaConverter {
|
||||
let felanguage = FElanguage::new()?;
|
||||
trace!("FElanguage instance created");
|
||||
|
||||
let result = felanguage.j_morph_result(text, FELANG_REQ_REV, FELANG_CMODE_KATAKANAOUT | FELANG_CMODE_PRECONV | FELANG_CMODE_NOINVISIBLECHAR);
|
||||
let result = felanguage.j_morph_result(
|
||||
text,
|
||||
FELANG_REQ_REV,
|
||||
FELANG_CMODE_KATAKANAOUT | FELANG_CMODE_PRECONV | FELANG_CMODE_NOINVISIBLECHAR,
|
||||
);
|
||||
|
||||
match &result {
|
||||
Ok(converted) => info!("Conversion successful: {} -> {}", text, converted),
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub mod calculator;
|
||||
pub mod converter;
|
||||
pub mod hiragana;
|
||||
pub mod katakana;
|
||||
pub mod roman_to_kanji;
|
||||
pub mod calculator;
|
||||
mod none_converter;
|
||||
pub mod roman_to_kanji;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use tracing::{debug, trace};
|
||||
use super::converter::Converter;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
pub struct NoneConverter;
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
use windows::Win32::UI::Input::Ime::{FELANG_CMODE_HIRAGANAOUT, FELANG_CMODE_NOINVISIBLECHAR, FELANG_CMODE_PRECONV, FELANG_CMODE_ROMAN, FELANG_REQ_CONV};
|
||||
use tracing::{debug, info, trace};
|
||||
use windows::Win32::UI::Input::Ime::{
|
||||
FELANG_CMODE_HIRAGANAOUT, FELANG_CMODE_NOINVISIBLECHAR, FELANG_CMODE_PRECONV,
|
||||
FELANG_CMODE_ROMAN, FELANG_REQ_CONV,
|
||||
};
|
||||
|
||||
use crate::felanguage::FElanguage;
|
||||
|
||||
@ -13,10 +16,14 @@ impl Converter for RomanToKanjiConverter {
|
||||
let felanguage = FElanguage::new()?;
|
||||
trace!("FElanguage instance created");
|
||||
|
||||
let result = felanguage.j_morph_result(text, FELANG_REQ_CONV, FELANG_CMODE_HIRAGANAOUT
|
||||
let result = felanguage.j_morph_result(
|
||||
text,
|
||||
FELANG_REQ_CONV,
|
||||
FELANG_CMODE_HIRAGANAOUT
|
||||
| FELANG_CMODE_ROMAN
|
||||
| FELANG_CMODE_NOINVISIBLECHAR
|
||||
| FELANG_CMODE_PRECONV);
|
||||
| FELANG_CMODE_PRECONV,
|
||||
);
|
||||
|
||||
match &result {
|
||||
Ok(converted) => info!("Conversion successful: {} -> {}", text, converted),
|
||||
|
@ -43,7 +43,10 @@ impl FElanguage {
|
||||
}
|
||||
|
||||
pub fn j_morph_result(&self, input: &str, request: u32, mode: u32) -> Result<String> {
|
||||
debug!("Calling j_morph_result with input: {}, request: {}, mode: {}", input, request, mode);
|
||||
debug!(
|
||||
"Calling j_morph_result with input: {}, request: {}, mode: {}",
|
||||
input, request, mode
|
||||
);
|
||||
let input_utf16: Vec<u16> = input.encode_utf16().chain(Some(0)).collect();
|
||||
let input_len = input_utf16.len();
|
||||
let input_pcwstr = PCWSTR::from_raw(input_utf16.as_ptr());
|
||||
@ -75,7 +78,8 @@ impl FElanguage {
|
||||
return Err(anyhow::anyhow!("Output BSTR pointer is null"));
|
||||
}
|
||||
|
||||
let output_slice = unsafe { std::slice::from_raw_parts(output_bstr_ptr.as_ptr(), output_len) };
|
||||
let output_slice =
|
||||
unsafe { std::slice::from_raw_parts(output_bstr_ptr.as_ptr(), output_len) };
|
||||
let output_string = String::from_utf16_lossy(output_slice);
|
||||
|
||||
trace!("j_morph_result output: {}", output_string);
|
||||
|
@ -1,15 +1,20 @@
|
||||
use std::net::UdpSocket;
|
||||
|
||||
use crate::{
|
||||
config::{Config, OnCopyMode},
|
||||
conversion::Conversion,
|
||||
tsf_conversion::TsfConversion,
|
||||
Log, STATE,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use chrono::Local;
|
||||
use clipboard::{ClipboardContext, ClipboardProvider};
|
||||
use clipboard_master::{ClipboardHandler, CallbackResult};
|
||||
use clipboard_master::{CallbackResult, ClipboardHandler};
|
||||
use regex::Regex;
|
||||
use rosc::{encoder, OscMessage, OscPacket, OscType};
|
||||
use tauri::{AppHandle, Manager};
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tracing::{error, info, warn};
|
||||
use windows::Win32::System::DataExchange::GetClipboardOwner;
|
||||
use crate::{config::{Config, OnCopyMode}, conversion::Conversion, tsf_conversion::TsfConversion, Log, STATE};
|
||||
use anyhow::Result;
|
||||
use tracing::{info, warn, error};
|
||||
|
||||
pub struct ConversionHandler {
|
||||
app_handle: AppHandle,
|
||||
@ -26,7 +31,13 @@ impl ConversionHandler {
|
||||
let clipboard_ctx = ClipboardProvider::new().unwrap();
|
||||
|
||||
info!("ConversionHandler created");
|
||||
Ok(Self { app_handle, conversion, tsf_conversion, clipboard_ctx, last_text: String::new() })
|
||||
Ok(Self {
|
||||
app_handle,
|
||||
conversion,
|
||||
tsf_conversion,
|
||||
clipboard_ctx,
|
||||
last_text: String::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_config(&self) -> Config {
|
||||
@ -44,7 +55,11 @@ impl ConversionHandler {
|
||||
info!("Content exceeds 140 characters, skipping TSF conversion");
|
||||
return Ok(());
|
||||
}
|
||||
if config.skip_url && Regex::new(r"(http://|https://){1}[\w\.\-/:\#\?=\&;%\~\+]+").unwrap().is_match(&contents) {
|
||||
if config.skip_url
|
||||
&& Regex::new(r"(http://|https://){1}[\w\.\-/:\#\?=\&;%\~\+]+")
|
||||
.unwrap()
|
||||
.is_match(&contents)
|
||||
{
|
||||
info!("URL detected, skipping TSF conversion");
|
||||
return Ok(());
|
||||
}
|
||||
@ -79,7 +94,7 @@ impl ConversionHandler {
|
||||
count += 1;
|
||||
}
|
||||
info!("Conversion returned to clipboard");
|
||||
},
|
||||
}
|
||||
OnCopyMode::ReturnToChatbox => {
|
||||
let sock = UdpSocket::bind("127.0.0.1:0").unwrap();
|
||||
let msg_buf = encoder::encode(&OscPacket::Message(OscMessage {
|
||||
@ -87,16 +102,17 @@ impl ConversionHandler {
|
||||
args: vec![
|
||||
OscType::String(converted.clone()),
|
||||
OscType::Bool(false),
|
||||
OscType::Bool(true)
|
||||
]
|
||||
})).unwrap();
|
||||
OscType::Bool(true),
|
||||
],
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
if let Err(e) = sock.send_to(&msg_buf, "127.0.0.1:9000") {
|
||||
error!("Failed to send UDP packet: {}", e);
|
||||
} else {
|
||||
info!("Conversion returned to chatbox");
|
||||
}
|
||||
},
|
||||
}
|
||||
OnCopyMode::SendDirectly => {
|
||||
let sock = UdpSocket::bind("127.0.0.1:0").unwrap();
|
||||
let msg_buf = encoder::encode(&OscPacket::Message(OscMessage {
|
||||
@ -104,25 +120,32 @@ impl ConversionHandler {
|
||||
args: vec![
|
||||
OscType::String(converted.clone()),
|
||||
OscType::Bool(true),
|
||||
OscType::Bool(true)
|
||||
]
|
||||
})).unwrap();
|
||||
OscType::Bool(true),
|
||||
],
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
if let Err(e) = sock.send_to(&msg_buf, "127.0.0.1:9000") {
|
||||
error!("Failed to send UDP packet: {}", e);
|
||||
} else {
|
||||
info!("Conversion sent directly");
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
let datetime = Local::now();
|
||||
if self.app_handle
|
||||
.emit_all("addLog", Log {
|
||||
if self
|
||||
.app_handle
|
||||
.emit(
|
||||
"addLog",
|
||||
Log {
|
||||
time: datetime.format("%Y %m/%d %H:%M:%S").to_string(),
|
||||
original: parsed_contents,
|
||||
converted
|
||||
}).is_err() {
|
||||
converted,
|
||||
},
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
error!("App handle add log failed");
|
||||
}
|
||||
}
|
||||
@ -146,12 +169,20 @@ impl ClipboardHandler for ConversionHandler {
|
||||
|
||||
if contents != self.last_text {
|
||||
if contents.starts_with(&config.prefix) || config.ignore_prefix {
|
||||
if config.skip_url && Regex::new(r"(http://|https://){1}[\w\.\-/:\#\?=\&;%\~\+]+").unwrap().is_match(&contents) {
|
||||
if config.skip_url
|
||||
&& Regex::new(r"(http://|https://){1}[\w\.\-/:\#\?=\&;%\~\+]+")
|
||||
.unwrap()
|
||||
.is_match(&contents)
|
||||
{
|
||||
info!("URL detected, skipping conversion");
|
||||
return CallbackResult::Next;
|
||||
}
|
||||
|
||||
let parsed_contents = if config.ignore_prefix { contents } else { contents.split_off(1) };
|
||||
let parsed_contents = if config.ignore_prefix {
|
||||
contents
|
||||
} else {
|
||||
contents.split_off(1)
|
||||
};
|
||||
let converted = match self.conversion.convert_text(&parsed_contents) {
|
||||
Ok(converted) => converted,
|
||||
Err(err) => {
|
||||
|
@ -2,11 +2,11 @@
|
||||
//#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
mod com;
|
||||
mod config;
|
||||
mod conversion;
|
||||
mod converter;
|
||||
mod felanguage;
|
||||
mod handler;
|
||||
mod conversion;
|
||||
mod config;
|
||||
mod converter;
|
||||
mod transform_rule;
|
||||
mod tsf;
|
||||
mod tsf_conversion;
|
||||
@ -43,7 +43,7 @@ fn load_settings(state: State<AppState>) -> Result<Config, String> {
|
||||
let mut app_config = state.config.lock().unwrap();
|
||||
*app_config = config.clone();
|
||||
Ok(config)
|
||||
},
|
||||
}
|
||||
Err(e) => Err(format!("Failed to load settings: {}", e)),
|
||||
}
|
||||
}
|
||||
@ -56,8 +56,12 @@ fn save_settings(config: Config, state: State<AppState>) -> Result<(), String> {
|
||||
|
||||
fn main() {
|
||||
println!("VRClipboard-IME Logs\nバグがあった場合はこのログを送ってください。");
|
||||
tracing_subscriber::fmt().with_max_level(Level::TRACE).init();
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(Level::TRACE)
|
||||
.init();
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_updater::Builder::new().build())
|
||||
.manage(AppState {
|
||||
config: Mutex::new(Config::load().unwrap_or_else(|_| {
|
||||
Config::generate_default_config().expect("Failed to generate default config");
|
||||
@ -68,7 +72,7 @@ fn main() {
|
||||
.setup(|app| {
|
||||
let _span = tracing::span!(tracing::Level::INFO, "main");
|
||||
app.manage(STATE.lock().unwrap().clone());
|
||||
let app_handle = app.app_handle();
|
||||
let app_handle = app.app_handle().clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let _com = Com::new().unwrap();
|
||||
|
@ -1,3 +1 @@
|
||||
pub struct TransformRule {
|
||||
|
||||
}
|
||||
pub struct TransformRule {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, info, error};
|
||||
use tracing::{debug, error, info};
|
||||
use windows::{
|
||||
core::Interface,
|
||||
Win32::UI::TextServices::{ITfFnSearchCandidateProvider, ITfFunctionProvider},
|
||||
@ -20,20 +20,23 @@ impl FunctionProvider {
|
||||
pub fn get_search_candidate_provider(&self) -> Result<SearchCandidateProvider> {
|
||||
debug!("Getting search candidate provider");
|
||||
let zeroed_guid = windows_core::GUID::zeroed();
|
||||
match unsafe { self.function_provider.GetFunction(&zeroed_guid, &ITfFnSearchCandidateProvider::IID) } {
|
||||
match unsafe {
|
||||
self.function_provider
|
||||
.GetFunction(&zeroed_guid, &ITfFnSearchCandidateProvider::IID)
|
||||
} {
|
||||
Ok(search_candidate_provider) => {
|
||||
info!("Search candidate provider obtained successfully");
|
||||
match search_candidate_provider.cast() {
|
||||
Ok(provider) => {
|
||||
debug!("Successfully cast search candidate provider");
|
||||
Ok(SearchCandidateProvider::new(provider))
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to cast search candidate provider: {:?}", e);
|
||||
Err(e.into())
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to get search candidate provider: {:?}", e);
|
||||
Err(e.into())
|
||||
|
@ -1,8 +1,15 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, info, error};
|
||||
use tracing::{debug, error, info};
|
||||
use windows::Win32::{
|
||||
System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER},
|
||||
UI::{Input::KeyboardAndMouse::HKL, TextServices::{CLSID_TF_InputProcessorProfiles, ITfInputProcessorProfileMgr, GUID_TFCAT_TIP_KEYBOARD, TF_INPUTPROCESSORPROFILE, TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE, TF_PROFILETYPE_INPUTPROCESSOR}},
|
||||
UI::{
|
||||
Input::KeyboardAndMouse::HKL,
|
||||
TextServices::{
|
||||
CLSID_TF_InputProcessorProfiles, ITfInputProcessorProfileMgr, GUID_TFCAT_TIP_KEYBOARD,
|
||||
TF_INPUTPROCESSORPROFILE, TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE,
|
||||
TF_PROFILETYPE_INPUTPROCESSOR,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
pub struct InputProcessorProfileMgr {
|
||||
@ -12,9 +19,13 @@ pub struct InputProcessorProfileMgr {
|
||||
impl InputProcessorProfileMgr {
|
||||
pub fn new() -> Result<Self> {
|
||||
debug!("Creating new InputProcessorProfileMgr");
|
||||
let input_processor_profile_mgr = unsafe { CoCreateInstance(&CLSID_TF_InputProcessorProfiles, None, CLSCTX_INPROC_SERVER)? };
|
||||
let input_processor_profile_mgr = unsafe {
|
||||
CoCreateInstance(&CLSID_TF_InputProcessorProfiles, None, CLSCTX_INPROC_SERVER)?
|
||||
};
|
||||
info!("InputProcessorProfileMgr created successfully");
|
||||
Ok(InputProcessorProfileMgr { input_processor_profile_mgr })
|
||||
Ok(InputProcessorProfileMgr {
|
||||
input_processor_profile_mgr,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_active_profile(&self) -> Result<TF_INPUTPROCESSORPROFILE> {
|
||||
@ -22,11 +33,14 @@ impl InputProcessorProfileMgr {
|
||||
let keyboard_guid = GUID_TFCAT_TIP_KEYBOARD;
|
||||
let mut profile = TF_INPUTPROCESSORPROFILE::default();
|
||||
|
||||
match unsafe { self.input_processor_profile_mgr.GetActiveProfile(&keyboard_guid, &mut profile) } {
|
||||
match unsafe {
|
||||
self.input_processor_profile_mgr
|
||||
.GetActiveProfile(&keyboard_guid, &mut profile)
|
||||
} {
|
||||
Ok(_) => {
|
||||
info!("Active profile retrieved successfully");
|
||||
Ok(profile)
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to get active profile: {:?}", e);
|
||||
Err(e.into())
|
||||
@ -36,11 +50,20 @@ impl InputProcessorProfileMgr {
|
||||
|
||||
pub fn activate_profile(&self, profile: &TF_INPUTPROCESSORPROFILE) -> Result<()> {
|
||||
debug!("Activating profile: {:?}", profile);
|
||||
match unsafe { self.input_processor_profile_mgr.ActivateProfile(TF_PROFILETYPE_INPUTPROCESSOR, profile.langid, &profile.clsid, &profile.guidProfile, HKL::default(), TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE) } {
|
||||
match unsafe {
|
||||
self.input_processor_profile_mgr.ActivateProfile(
|
||||
TF_PROFILETYPE_INPUTPROCESSOR,
|
||||
profile.langid,
|
||||
&profile.clsid,
|
||||
&profile.guidProfile,
|
||||
HKL::default(),
|
||||
TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE,
|
||||
)
|
||||
} {
|
||||
Ok(_) => {
|
||||
info!("Profile activated successfully");
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to activate profile: {:?}", e);
|
||||
Err(e.into())
|
||||
|
@ -1,20 +1,32 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, error};
|
||||
use windows::Win32::UI::WindowsAndMessaging::{SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS};
|
||||
use windows::Win32::UI::WindowsAndMessaging::{
|
||||
SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS,
|
||||
};
|
||||
|
||||
pub mod input_processor_profile_mgr;
|
||||
pub mod function_provider;
|
||||
pub mod input_processor_profile_mgr;
|
||||
pub mod search_candidate_provider;
|
||||
pub mod thread_mgr;
|
||||
|
||||
pub fn set_thread_local_input_settings(thread_local_input_settings: bool) -> Result<()> {
|
||||
debug!("Setting thread local input settings to: {}", thread_local_input_settings);
|
||||
debug!(
|
||||
"Setting thread local input settings to: {}",
|
||||
thread_local_input_settings
|
||||
);
|
||||
let mut result = thread_local_input_settings;
|
||||
match unsafe { SystemParametersInfoW(SPI_SETTHREADLOCALINPUTSETTINGS, 0, Some(&mut result as *mut _ as *const _ as *mut _), SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0)) } {
|
||||
match unsafe {
|
||||
SystemParametersInfoW(
|
||||
SPI_SETTHREADLOCALINPUTSETTINGS,
|
||||
0,
|
||||
Some(&mut result as *mut _ as *const _ as *mut _),
|
||||
SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0),
|
||||
)
|
||||
} {
|
||||
Ok(_) => {
|
||||
debug!("Successfully set thread local input settings");
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to set thread local input settings: {:?}", e);
|
||||
Err(e.into())
|
||||
|
@ -1,8 +1,13 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, info, error, trace};
|
||||
use windows::Win32::UI::TextServices::{ITfFnSearchCandidateProvider, TF_TMAE_NOACTIVATEKEYBOARDLAYOUT};
|
||||
use tracing::{debug, error, info, trace};
|
||||
use windows::Win32::UI::TextServices::{
|
||||
ITfFnSearchCandidateProvider, TF_TMAE_NOACTIVATEKEYBOARDLAYOUT,
|
||||
};
|
||||
|
||||
use super::{function_provider::FunctionProvider, input_processor_profile_mgr::InputProcessorProfileMgr, thread_mgr::ThreadMgr};
|
||||
use super::{
|
||||
function_provider::FunctionProvider, input_processor_profile_mgr::InputProcessorProfileMgr,
|
||||
thread_mgr::ThreadMgr,
|
||||
};
|
||||
|
||||
pub struct SearchCandidateProvider {
|
||||
search_candidate_provider: ITfFnSearchCandidateProvider,
|
||||
@ -11,7 +16,9 @@ pub struct SearchCandidateProvider {
|
||||
impl SearchCandidateProvider {
|
||||
pub fn new(search_candidate_provider: ITfFnSearchCandidateProvider) -> Self {
|
||||
debug!("Creating new SearchCandidateProvider");
|
||||
Self { search_candidate_provider }
|
||||
Self {
|
||||
search_candidate_provider,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create() -> Result<Self> {
|
||||
@ -29,7 +36,8 @@ impl SearchCandidateProvider {
|
||||
let function_provider = thread_mgr.get_function_provider(&profile.clsid)?;
|
||||
|
||||
debug!("Getting search candidate provider");
|
||||
let search_candidate_provider = FunctionProvider::new(function_provider).get_search_candidate_provider()?;
|
||||
let search_candidate_provider =
|
||||
FunctionProvider::new(function_provider).get_search_candidate_provider()?;
|
||||
|
||||
info!("SearchCandidateProvider created successfully");
|
||||
Ok(search_candidate_provider)
|
||||
@ -44,7 +52,10 @@ impl SearchCandidateProvider {
|
||||
let input_bstr_empty = windows_core::BSTR::from_wide(&input_utf16)?;
|
||||
|
||||
trace!("Calling GetSearchCandidates");
|
||||
let candidates = unsafe { self.search_candidate_provider.GetSearchCandidates(&input_bstr, &input_bstr_empty)? };
|
||||
let candidates = unsafe {
|
||||
self.search_candidate_provider
|
||||
.GetSearchCandidates(&input_bstr, &input_bstr_empty)?
|
||||
};
|
||||
let candidates_enum = unsafe { candidates.EnumCandidates()? };
|
||||
|
||||
let mut candidates = vec![None; max];
|
||||
@ -54,7 +65,9 @@ impl SearchCandidateProvider {
|
||||
|
||||
candidates.resize(candidates_count as usize, None);
|
||||
|
||||
let candidates: Vec<String> = candidates.iter().map(|candidate| unsafe {
|
||||
let candidates: Vec<String> = candidates
|
||||
.iter()
|
||||
.map(|candidate| unsafe {
|
||||
match candidate.as_ref().unwrap().GetString() {
|
||||
Ok(s) => s.to_string(),
|
||||
Err(e) => {
|
||||
@ -62,7 +75,8 @@ impl SearchCandidateProvider {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
info!("Retrieved {} candidates", candidates.len());
|
||||
Ok(candidates)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use tracing::{debug, error, info};
|
||||
use windows::Win32::{
|
||||
System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER},
|
||||
UI::TextServices::{CLSID_TF_ThreadMgr, ITfFunctionProvider, ITfThreadMgr2},
|
||||
};
|
||||
};
|
||||
|
||||
pub struct ThreadMgr {
|
||||
thread_mgr: ITfThreadMgr2,
|
||||
@ -12,7 +12,8 @@ pub struct ThreadMgr {
|
||||
impl ThreadMgr {
|
||||
pub fn new() -> Result<Self> {
|
||||
debug!("Creating new ThreadMgr");
|
||||
let thread_mgr = unsafe { CoCreateInstance(&CLSID_TF_ThreadMgr, None, CLSCTX_INPROC_SERVER)? };
|
||||
let thread_mgr =
|
||||
unsafe { CoCreateInstance(&CLSID_TF_ThreadMgr, None, CLSCTX_INPROC_SERVER)? };
|
||||
info!("ThreadMgr created successfully");
|
||||
Ok(ThreadMgr { thread_mgr })
|
||||
}
|
||||
@ -20,7 +21,10 @@ impl ThreadMgr {
|
||||
pub fn activate_ex(&self, flags: u32) -> Result<u32> {
|
||||
debug!("Activating ThreadMgr with flags: {}", flags);
|
||||
let mut client_id = 0;
|
||||
unsafe { self.thread_mgr.ActivateEx(&mut client_id as *mut _ as *const _ as *mut _, flags)? };
|
||||
unsafe {
|
||||
self.thread_mgr
|
||||
.ActivateEx(&mut client_id as *mut _ as *const _ as *mut _, flags)?
|
||||
};
|
||||
info!("ThreadMgr activated with client_id: {}", client_id);
|
||||
Ok(client_id)
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
use crate::{
|
||||
converter::{
|
||||
converter::Converter, hiragana::HiraganaConverter, roman_to_kanji::RomanToKanjiConverter,
|
||||
},
|
||||
tsf::{search_candidate_provider::SearchCandidateProvider, set_thread_local_input_settings},
|
||||
};
|
||||
use anyhow::Result;
|
||||
use tracing::{info, debug, error, trace};
|
||||
use crate::{converter::{converter::Converter, hiragana::HiraganaConverter, roman_to_kanji::RomanToKanjiConverter}, tsf::{search_candidate_provider::SearchCandidateProvider, set_thread_local_input_settings}};
|
||||
use tracing::{debug, error, info, trace};
|
||||
|
||||
pub struct TsfConversion {
|
||||
pub conversion_history: Vec<String>,
|
||||
@ -45,23 +50,48 @@ impl TsfConversion {
|
||||
|
||||
fn convert_roman_to_kanji(&mut self, text: &str) -> Result<String> {
|
||||
debug!("Converting roman to kanji: {}", text);
|
||||
let o_minus_1 = self.conversion_history.get(if self.conversion_history.len() > 0 { self.conversion_history.len() - 1 } else { 0 }).unwrap_or(&("".to_string())).clone();
|
||||
let o_minus_1 = self
|
||||
.conversion_history
|
||||
.get(if self.conversion_history.len() > 0 {
|
||||
self.conversion_history.len() - 1
|
||||
} else {
|
||||
0
|
||||
})
|
||||
.unwrap_or(&("".to_string()))
|
||||
.clone();
|
||||
trace!("Previous conversion (o_minus_1): {}", o_minus_1);
|
||||
let mut first_diff_position = o_minus_1.chars().zip(text.chars()).position(|(a, b)| a != b);
|
||||
let mut first_diff_position = o_minus_1
|
||||
.chars()
|
||||
.zip(text.chars())
|
||||
.position(|(a, b)| a != b);
|
||||
|
||||
if o_minus_1 != text && first_diff_position.is_none() {
|
||||
first_diff_position = Some(o_minus_1.chars().count());
|
||||
}
|
||||
trace!("First difference position: {:?}", first_diff_position);
|
||||
let diff = text.chars().skip(first_diff_position.unwrap_or(0)).collect::<String>();
|
||||
let diff = text
|
||||
.chars()
|
||||
.skip(first_diff_position.unwrap_or(0))
|
||||
.collect::<String>();
|
||||
debug!("Difference to convert: {}", diff);
|
||||
|
||||
let roman_to_kanji_converter = RomanToKanjiConverter;
|
||||
let converted = roman_to_kanji_converter.convert(&diff)?;
|
||||
trace!("Converted difference: {}", converted);
|
||||
self.conversion_history.push(o_minus_1.chars().zip(text.chars()).take_while(|(a, b)| a == b).map(|(a, _)| a).collect::<String>() + &converted);
|
||||
self.conversion_history.push(
|
||||
o_minus_1
|
||||
.chars()
|
||||
.zip(text.chars())
|
||||
.take_while(|(a, b)| a == b)
|
||||
.map(|(a, _)| a)
|
||||
.collect::<String>()
|
||||
+ &converted,
|
||||
);
|
||||
self.clipboard_history.push(text.to_string());
|
||||
info!("Roman to kanji conversion result: {}", self.conversion_history.last().unwrap());
|
||||
info!(
|
||||
"Roman to kanji conversion result: {}",
|
||||
self.conversion_history.last().unwrap()
|
||||
);
|
||||
trace!("Updated conversion history: {:?}", self.conversion_history);
|
||||
trace!("Updated clipboard history: {:?}", self.clipboard_history);
|
||||
Ok(self.conversion_history.last().unwrap().clone())
|
||||
@ -73,26 +103,56 @@ impl TsfConversion {
|
||||
let mut diff_hiragana = String::new();
|
||||
let mut diff = String::new();
|
||||
if self.reconversion_prefix.is_none() {
|
||||
let o_minus_2 = self.conversion_history.get(if self.conversion_history.len() > 1 { self.conversion_history.len() - 2 } else { 0 }).unwrap_or(&("".to_string())).clone();
|
||||
let i_minus_1 = self.clipboard_history.get(if self.clipboard_history.len() > 0 { self.clipboard_history.len() - 1 } else { 0 }).unwrap_or(&("".to_string())).clone();
|
||||
let o_minus_2 = self
|
||||
.conversion_history
|
||||
.get(if self.conversion_history.len() > 1 {
|
||||
self.conversion_history.len() - 2
|
||||
} else {
|
||||
0
|
||||
})
|
||||
.unwrap_or(&("".to_string()))
|
||||
.clone();
|
||||
let i_minus_1 = self
|
||||
.clipboard_history
|
||||
.get(if self.clipboard_history.len() > 0 {
|
||||
self.clipboard_history.len() - 1
|
||||
} else {
|
||||
0
|
||||
})
|
||||
.unwrap_or(&("".to_string()))
|
||||
.clone();
|
||||
trace!("o_minus_2: {}, i_minus_1: {}", o_minus_2, i_minus_1);
|
||||
let mut first_diff_position = i_minus_1.chars().zip(o_minus_2.chars()).position(|(a, b)| a != b);
|
||||
let mut first_diff_position = i_minus_1
|
||||
.chars()
|
||||
.zip(o_minus_2.chars())
|
||||
.position(|(a, b)| a != b);
|
||||
trace!("First difference position: {:?}", first_diff_position);
|
||||
if o_minus_2 != i_minus_1 && first_diff_position.is_none() {
|
||||
first_diff_position = Some(o_minus_2.chars().count());
|
||||
}
|
||||
diff = i_minus_1.chars().skip(first_diff_position.unwrap_or(0)).collect::<String>();
|
||||
diff = i_minus_1
|
||||
.chars()
|
||||
.skip(first_diff_position.unwrap_or(0))
|
||||
.collect::<String>();
|
||||
debug!("Difference to convert: {}", diff);
|
||||
diff_hiragana = HiraganaConverter.convert(&diff)?;
|
||||
trace!("Hiragana conversion: {}", diff_hiragana);
|
||||
let prefix = i_minus_1.chars().zip(o_minus_2.chars()).take_while(|(a, b)| a == b).map(|(a, _)| a).collect::<String>();
|
||||
let prefix = i_minus_1
|
||||
.chars()
|
||||
.zip(o_minus_2.chars())
|
||||
.take_while(|(a, b)| a == b)
|
||||
.map(|(a, _)| a)
|
||||
.collect::<String>();
|
||||
self.reconversion_prefix = Some(prefix.clone());
|
||||
trace!("Set reconversion prefix: {:?}", self.reconversion_prefix);
|
||||
}
|
||||
|
||||
let candidates = self.reconversion_candidates.get_or_insert_with(|| {
|
||||
debug!("Generating new candidates");
|
||||
let mut candidates = self.search_candidate_provider.get_candidates(&diff_hiragana, 10).unwrap_or_default();
|
||||
let mut candidates = self
|
||||
.search_candidate_provider
|
||||
.get_candidates(&diff_hiragana, 10)
|
||||
.unwrap_or_default();
|
||||
trace!("Initial candidates: {:?}", candidates);
|
||||
if candidates.is_empty() {
|
||||
candidates.push(diff_hiragana.clone());
|
||||
@ -115,7 +175,12 @@ impl TsfConversion {
|
||||
}
|
||||
debug!("Updated reconversion index: {}", index);
|
||||
|
||||
self.conversion_history.push(self.reconversion_prefix.clone().unwrap() + &self.reconversion_candidates.as_ref().unwrap()[self.reconversion_index.unwrap() as usize].clone());
|
||||
self.conversion_history.push(
|
||||
self.reconversion_prefix.clone().unwrap()
|
||||
+ &self.reconversion_candidates.as_ref().unwrap()
|
||||
[self.reconversion_index.unwrap() as usize]
|
||||
.clone(),
|
||||
);
|
||||
self.clipboard_history.push(text.to_string());
|
||||
trace!("Updated conversion history: {:?}", self.conversion_history);
|
||||
trace!("Updated clipboard history: {:?}", self.clipboard_history);
|
||||
@ -129,7 +194,10 @@ impl TsfConversion {
|
||||
trace!("Trimmed conversion history: {:?}", self.conversion_history);
|
||||
trace!("Trimmed clipboard history: {:?}", self.clipboard_history);
|
||||
|
||||
info!("TSF conversion result: {}", self.conversion_history.last().unwrap());
|
||||
info!(
|
||||
"TSF conversion result: {}",
|
||||
self.conversion_history.last().unwrap()
|
||||
);
|
||||
Ok(self.conversion_history.last().unwrap().clone())
|
||||
}
|
||||
|
||||
@ -137,7 +205,12 @@ impl TsfConversion {
|
||||
debug!("Starting conversion for: {}", text);
|
||||
trace!("Current conversion history: {:?}", self.conversion_history);
|
||||
trace!("Current clipboard history: {:?}", self.clipboard_history);
|
||||
let same_as_last_conversion = text.to_string() == self.conversion_history.last().unwrap_or(&("".to_string())).clone();
|
||||
let same_as_last_conversion = text.to_string()
|
||||
== self
|
||||
.conversion_history
|
||||
.last()
|
||||
.unwrap_or(&("".to_string()))
|
||||
.clone();
|
||||
trace!("Same as last conversion: {}", same_as_last_conversion);
|
||||
|
||||
self.target_text = text.to_string();
|
||||
|
@ -2,39 +2,42 @@
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
"beforeBuildCommand": "npm run build",
|
||||
"devPath": "http://localhost:1420",
|
||||
"distDir": "../dist"
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:1420"
|
||||
},
|
||||
"package": {
|
||||
"productName": "vrclipboard-ime-gui",
|
||||
"version": "1.9.0"
|
||||
},
|
||||
"tauri": {
|
||||
"updater": {
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"windows": {
|
||||
"wix": {
|
||||
"language": "ja-JP"
|
||||
}
|
||||
},
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"createUpdaterArtifacts": "v1Compatible"
|
||||
},
|
||||
"productName": "vrclipboard-ime-gui",
|
||||
"mainBinaryName": "vrclipboard-ime-gui",
|
||||
"version": "1.9.0",
|
||||
"identifier": "dev.mii.vrclipboard-ime",
|
||||
"plugins": {
|
||||
"updater": {
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEE5QTI2MDRDNTlENUY5OEMKUldTTStkVlpUR0NpcVIrMXZqOHFpNzNXMFVKT0d3aHJIWFlOUVJubGN5VTAzUkVwYW95bVlMYUQK",
|
||||
"endpoints": [
|
||||
"https://r2-vrime.mii.dev/release.json"
|
||||
],
|
||||
"dialog": true,
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEE5QTI2MDRDNTlENUY5OEMKUldTTStkVlpUR0NpcVIrMXZqOHFpNzNXMFVKT0d3aHJIWFlOUVJubGN5VTAzUkVwYW95bVlMYUQK"
|
||||
},
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"shell": {
|
||||
"all": false,
|
||||
"open": true
|
||||
},
|
||||
"window": {
|
||||
"maximize": true,
|
||||
"minimize": true,
|
||||
"hide": true,
|
||||
"startDragging": true,
|
||||
"show": true,
|
||||
"unmaximize": true,
|
||||
"unminimize": true,
|
||||
"close": true
|
||||
]
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"title": "VRClipboard IME",
|
||||
@ -44,26 +47,6 @@
|
||||
"decorations": false,
|
||||
"transparent": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "dev.mii.vrclipboard-ime",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"windows": {
|
||||
"wix": {
|
||||
"language": "ja-JP"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { invoke } from '@tauri-apps/api/tauri';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
|
||||
interface Config {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { appWindow } from '@tauri-apps/api/window';
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||
import { X, Minus, Square } from 'lucide-react';
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
|
||||
const TitleBar = () => {
|
||||
const handleClose = () => appWindow.close();
|
||||
|
Reference in New Issue
Block a user