update to tauri 2.0

This commit is contained in:
mii443
2024-10-04 13:46:42 +09:00
parent b66a7a1e24
commit 655c42617e
30 changed files with 1742 additions and 1057 deletions

119
package-lock.json generated
View File

@ -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",

View File

@ -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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -0,0 +1,11 @@
{
"identifier": "desktop-capability",
"platforms": [
"macOS",
"windows",
"linux"
],
"permissions": [
"updater:default"
]
}

View 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"
]
}

View File

@ -7,7 +7,7 @@ pub struct Com;
impl Drop for Com {
fn drop(&mut self) {
debug!("Dropping Com instance");
unsafe {
unsafe {
CoUninitialize();
debug!("CoUninitialize called");
};
@ -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)
}
}

View File

@ -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,
@ -31,11 +35,11 @@ pub struct Config {
impl Default for Config {
fn default() -> Self {
Self {
prefix: ";".to_string(),
split: "/".to_string(),
command: ";".to_string(),
ignore_prefix: true,
Self {
prefix: ";".to_string(),
split: "/".to_string(),
command: ";".to_string(),
ignore_prefix: true,
on_copy_mode: OnCopyMode::ReturnToChatbox,
skip_url: true,
use_tsf_reconvert: false,
@ -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,10 +106,10 @@ 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) {
Ok(yaml) => {
trace!("Config to be saved: {}", yaml);
@ -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))
},
}
}
}

View File

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

View File

@ -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)

View File

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

View File

@ -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;
@ -13,14 +15,18 @@ impl Converter for HiraganaConverter {
debug!("Converting to hiragana: {}", text);
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),
Err(e) => debug!("Conversion failed: {}", e),
}
result
}

View File

@ -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;
@ -13,14 +15,18 @@ impl Converter for KatakanaConverter {
debug!("Converting to katakana: {}", text);
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),
Err(e) => debug!("Conversion failed: {}", e),
}
result
}

View File

@ -1,6 +1,6 @@
pub mod calculator;
pub mod converter;
pub mod hiragana;
pub mod katakana;
mod none_converter;
pub mod roman_to_kanji;
pub mod calculator;
mod none_converter;

View File

@ -1,5 +1,5 @@
use tracing::{debug, trace};
use super::converter::Converter;
use tracing::{debug, trace};
pub struct NoneConverter;
@ -8,7 +8,7 @@ impl Converter for NoneConverter {
debug!("Converting with NoneConverter: {}", text);
Ok(text.to_string())
}
fn name(&self) -> String {
trace!("Getting converter name");
"none".to_string()

View File

@ -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;
@ -12,17 +15,21 @@ impl Converter for RomanToKanjiConverter {
debug!("Converting roman to kanji: {}", text);
let felanguage = FElanguage::new()?;
trace!("FElanguage instance created");
let result = felanguage.j_morph_result(text, FELANG_REQ_CONV, FELANG_CMODE_HIRAGANAOUT
| FELANG_CMODE_ROMAN
| FELANG_CMODE_NOINVISIBLECHAR
| FELANG_CMODE_PRECONV);
let result = felanguage.j_morph_result(
text,
FELANG_REQ_CONV,
FELANG_CMODE_HIRAGANAOUT
| FELANG_CMODE_ROMAN
| FELANG_CMODE_NOINVISIBLECHAR
| FELANG_CMODE_PRECONV,
);
match &result {
Ok(converted) => info!("Conversion successful: {} -> {}", text, converted),
Err(e) => debug!("Conversion failed: {}", e),
}
result
}

View File

@ -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());
@ -65,17 +68,18 @@ impl FElanguage {
error!("GetJMorphResult returned null pointer");
return Err(anyhow::anyhow!("GetJMorphResult returned null pointer"));
}
let result_struct = unsafe { &*result_ptr };
let output_bstr_ptr = result_struct.pwchOutput;
let output_len = result_struct.cchOutput as usize;
if output_bstr_ptr.is_null() {
error!("Output BSTR pointer is null");
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);

View File

@ -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,27 +120,34 @@ 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 {
time: datetime.format("%Y %m/%d %H:%M:%S").to_string(),
original: parsed_contents,
converted
}).is_err() {
error!("App handle add log failed");
}
let datetime = Local::now();
if self
.app_handle
.emit(
"addLog",
Log {
time: datetime.format("%Y %m/%d %H:%M:%S").to_string(),
original: parsed_contents,
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) => {

View File

@ -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;
@ -25,9 +25,9 @@ use tracing::Level;
#[derive(Serialize, Deserialize, Debug, Clone)]
struct Log {
pub time: String,
pub original: String,
pub converted: String,
pub time: String,
pub original: String,
pub converted: String,
}
struct AppState {
@ -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,15 +72,15 @@ 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();
let conversion_handler = ConversionHandler::new(app_handle).unwrap();
let mut master = Master::new(conversion_handler);
master.run().unwrap();
});

View File

@ -1,3 +1 @@
pub struct TransformRule {
}
pub struct TransformRule {}

View File

@ -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())

View File

@ -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,25 +33,37 @@ 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())
}
}
}
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())

View File

@ -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())

View File

@ -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)
@ -42,9 +50,12 @@ impl SearchCandidateProvider {
let input_utf16: Vec<u16> = "".encode_utf16().chain(Some(0)).collect();
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,15 +65,18 @@ impl SearchCandidateProvider {
candidates.resize(candidates_count as usize, None);
let candidates: Vec<String> = candidates.iter().map(|candidate| unsafe {
match candidate.as_ref().unwrap().GetString() {
Ok(s) => s.to_string(),
Err(e) => {
error!("Failed to get candidate string: {:?}", e);
String::new()
let candidates: Vec<String> = candidates
.iter()
.map(|candidate| unsafe {
match candidate.as_ref().unwrap().GetString() {
Ok(s) => s.to_string(),
Err(e) => {
error!("Failed to get candidate string: {:?}", e);
String::new()
}
}
}
}).collect();
})
.collect();
info!("Retrieved {} candidates", candidates.len());
Ok(candidates)
}

View File

@ -1,9 +1,9 @@
use anyhow::Result;
use tracing::{debug, error, info};
use windows::Win32::{
System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER},
UI::TextServices::{CLSID_TF_ThreadMgr, ITfFunctionProvider, ITfThreadMgr2},
};
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)
}

View File

@ -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();

View File

@ -2,38 +2,41 @@
"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"
"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"
},
"tauri": {
"productName": "vrclipboard-ime-gui",
"mainBinaryName": "vrclipboard-ime-gui",
"version": "1.9.0",
"identifier": "dev.mii.vrclipboard-ime",
"plugins": {
"updater": {
"active": true,
"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": [
{
@ -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"
}
}
}
]
}
}
}

View File

@ -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 {

View File

@ -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();