forked from NG-SD-Plugins/PowerTools
Add minimal store UI functionality
This commit is contained in:
parent
2986c05170
commit
622f161560
13 changed files with 297 additions and 44 deletions
|
@ -28,6 +28,7 @@ pub enum ApiMessage {
|
||||||
LoadSystemSettings,
|
LoadSystemSettings,
|
||||||
GetLimits(Callback<super::SettingsLimits>),
|
GetLimits(Callback<super::SettingsLimits>),
|
||||||
GetProvider(String, Callback<crate::persist::DriverJson>),
|
GetProvider(String, Callback<crate::persist::DriverJson>),
|
||||||
|
UploadCurrentVariant(String, String), // SteamID, Steam username
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum BatteryMessage {
|
pub enum BatteryMessage {
|
||||||
|
@ -251,7 +252,7 @@ impl GeneralMessage {
|
||||||
cb(Vec::with_capacity(0))
|
cb(Vec::with_capacity(0))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Self::ApplyNow => {}
|
Self::ApplyNow => {},
|
||||||
}
|
}
|
||||||
dirty
|
dirty
|
||||||
}
|
}
|
||||||
|
@ -304,7 +305,7 @@ impl ApiMessageHandler {
|
||||||
if is_persistent {
|
if is_persistent {
|
||||||
let settings_clone = settings.json();
|
let settings_clone = settings.json();
|
||||||
let save_json: SettingsJson = settings_clone.into();
|
let save_json: SettingsJson = settings_clone.into();
|
||||||
if let Err(e) = crate::persist::FileJson::update_variant_or_create(&save_path, save_json, settings.general.get_name().to_owned()) {
|
if let Err(e) = crate::persist::FileJson::update_variant_or_create(&save_path, settings.general.get_app_id(), save_json, settings.general.get_name().to_owned()) {
|
||||||
log::error!("Failed to create/update settings file {}: {}", save_path.display(), e);
|
log::error!("Failed to create/update settings file {}: {}", save_path.display(), e);
|
||||||
}
|
}
|
||||||
//unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings");
|
//unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings");
|
||||||
|
@ -383,7 +384,7 @@ impl ApiMessageHandler {
|
||||||
}
|
}
|
||||||
ApiMessage::LoadSettings(id, name, variant_id, variant_name) => {
|
ApiMessage::LoadSettings(id, name, variant_id, variant_name) => {
|
||||||
let path = format!("{}.ron", id);
|
let path = format!("{}.ron", id);
|
||||||
match settings.load_file(path.into(), name, variant_id, variant_name, false) {
|
match settings.load_file(path.into(), id, name, variant_id, variant_name, false) {
|
||||||
Ok(success) => log::info!("Loaded settings file? {}", success),
|
Ok(success) => log::info!("Loaded settings file? {}", success),
|
||||||
Err(e) => log::warn!("Load file err: {}", e),
|
Err(e) => log::warn!("Load file err: {}", e),
|
||||||
}
|
}
|
||||||
|
@ -391,7 +392,8 @@ impl ApiMessageHandler {
|
||||||
}
|
}
|
||||||
ApiMessage::LoadVariant(variant_id, variant_name) => {
|
ApiMessage::LoadVariant(variant_id, variant_name) => {
|
||||||
let path = settings.general.get_path();
|
let path = settings.general.get_path();
|
||||||
match settings.load_file(path.into(), settings.general.get_name().to_owned(), variant_id, variant_name, false) {
|
let app_id = settings.general.get_app_id();
|
||||||
|
match settings.load_file(path.into(), app_id, settings.general.get_name().to_owned(), variant_id, variant_name, false) {
|
||||||
Ok(success) => log::info!("Loaded settings file? {}", success),
|
Ok(success) => log::info!("Loaded settings file? {}", success),
|
||||||
Err(e) => log::warn!("Load file err: {}", e),
|
Err(e) => log::warn!("Load file err: {}", e),
|
||||||
}
|
}
|
||||||
|
@ -400,6 +402,7 @@ impl ApiMessageHandler {
|
||||||
ApiMessage::LoadMainSettings => {
|
ApiMessage::LoadMainSettings => {
|
||||||
match settings.load_file(
|
match settings.load_file(
|
||||||
crate::consts::DEFAULT_SETTINGS_FILE.into(),
|
crate::consts::DEFAULT_SETTINGS_FILE.into(),
|
||||||
|
0,
|
||||||
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
||||||
0,
|
0,
|
||||||
crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(),
|
crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(),
|
||||||
|
@ -431,7 +434,13 @@ impl ApiMessageHandler {
|
||||||
_ => settings.general.provider(),
|
_ => settings.general.provider(),
|
||||||
});
|
});
|
||||||
false
|
false
|
||||||
}
|
},
|
||||||
|
ApiMessage::UploadCurrentVariant(steam_id, steam_username) => {
|
||||||
|
//TODO
|
||||||
|
let steam_app_id = settings.general.get_app_id();
|
||||||
|
super::web::upload_settings(steam_app_id, steam_id, steam_username, settings.json());
|
||||||
|
false
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,34 +87,104 @@ fn web_config_to_settings_json(meta: community_settings_core::v1::Metadata) -> c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn download_config(id: u128) -> std::io::Result<community_settings_core::v1::Metadata> {
|
||||||
|
let req_url = format!("{}/api/setting/by_id/{}", BASE_URL, id);
|
||||||
|
let response = ureq::get(&req_url).call()
|
||||||
|
.map_err(|e| {
|
||||||
|
log::warn!("GET to {} failed: {}", req_url, e);
|
||||||
|
std::io::Error::new(std::io::ErrorKind::ConnectionAborted, e)
|
||||||
|
})?;
|
||||||
|
response.into_json()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn upload_settings(id: u64, user_id: String, username: String, settings: crate::persist::SettingsJson) {
|
||||||
|
log::info!("Uploading settings {} by {} ({})", settings.name, username, user_id);
|
||||||
|
let user_id: u64 = match user_id.parse() {
|
||||||
|
Ok(id) => id,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Failed to parse `{}` as u64: {} (aborted upload_settings very early)", user_id, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let meta = settings_to_web_config(id as _, user_id, username, settings);
|
||||||
|
if let Err(e) = upload_config(meta) {
|
||||||
|
log::error!("Failed to upload settings: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn settings_to_web_config(app_id: u32, user_id: u64, username: String, settings: crate::persist::SettingsJson) -> community_settings_core::v1::Metadata {
|
||||||
|
community_settings_core::v1::Metadata {
|
||||||
|
name: settings.name,
|
||||||
|
steam_app_id: app_id,
|
||||||
|
steam_user_id: user_id,
|
||||||
|
steam_username: username,
|
||||||
|
tags: vec!["wip".to_owned()],
|
||||||
|
id: "".to_owned(),
|
||||||
|
config: community_settings_core::v1::Config {
|
||||||
|
cpus: settings.cpus.into_iter().map(|cpu| community_settings_core::v1::Cpu {
|
||||||
|
online: cpu.online,
|
||||||
|
clock_limits: cpu.clock_limits.map(|lim| community_settings_core::v1::MinMax {
|
||||||
|
min: lim.min,
|
||||||
|
max: lim.max,
|
||||||
|
}),
|
||||||
|
governor: cpu.governor,
|
||||||
|
}).collect(),
|
||||||
|
gpu: community_settings_core::v1::Gpu {
|
||||||
|
fast_ppt: settings.gpu.fast_ppt,
|
||||||
|
slow_ppt: settings.gpu.slow_ppt,
|
||||||
|
tdp: settings.gpu.tdp,
|
||||||
|
tdp_boost: settings.gpu.tdp_boost,
|
||||||
|
clock_limits: settings.gpu.clock_limits.map(|lim| community_settings_core::v1::MinMax {
|
||||||
|
min: lim.min,
|
||||||
|
max: lim.max,
|
||||||
|
}),
|
||||||
|
slow_memory: settings.gpu.slow_memory,
|
||||||
|
},
|
||||||
|
battery: community_settings_core::v1::Battery {
|
||||||
|
charge_rate: settings.battery.charge_rate,
|
||||||
|
charge_mode: settings.battery.charge_mode,
|
||||||
|
events: settings.battery.events.into_iter().map(|batt_ev| community_settings_core::v1::BatteryEvent {
|
||||||
|
trigger: batt_ev.trigger,
|
||||||
|
charge_rate: batt_ev.charge_rate,
|
||||||
|
charge_mode: batt_ev.charge_mode,
|
||||||
|
}).collect(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn upload_config(config: community_settings_core::v1::Metadata) -> std::io::Result<()> {
|
||||||
|
let req_url = format!("{}/api/setting", BASE_URL);
|
||||||
|
ureq::post(&req_url)
|
||||||
|
.send_json(&config)
|
||||||
|
.map_err(|e| {
|
||||||
|
log::warn!("POST to {} failed: {}", req_url, e);
|
||||||
|
std::io::Error::new(std::io::ErrorKind::ConnectionAborted, e)
|
||||||
|
})
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
/// Download config web method
|
/// Download config web method
|
||||||
pub fn download_new_config(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
pub fn download_new_config(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
|
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
|
||||||
let getter = move || {
|
let getter = move || {
|
||||||
let sender2 = sender.clone();
|
let sender2 = sender.clone();
|
||||||
move |id: u128| {
|
move |id: u128| {
|
||||||
let req_url = format!("{}/api/setting/by_id/{}", BASE_URL, id);
|
match download_config(id) {
|
||||||
match ureq::get(&req_url).call() {
|
Ok(meta) => {
|
||||||
Ok(response) => {
|
let (tx, rx) = mpsc::channel();
|
||||||
let json_res: std::io::Result<community_settings_core::v1::Metadata> = response.into_json();
|
let callback =
|
||||||
match json_res {
|
move |values: Vec<super::VariantInfo>| tx.send(values).expect("download_new_config callback send failed");
|
||||||
Ok(meta) => {
|
sender2
|
||||||
let (tx, rx) = mpsc::channel();
|
.lock()
|
||||||
let callback =
|
.unwrap()
|
||||||
move |values: Vec<super::VariantInfo>| tx.send(values).expect("download_new_config callback send failed");
|
.send(ApiMessage::General(GeneralMessage::AddVariant(web_config_to_settings_json(meta), Box::new(callback))))
|
||||||
sender2
|
.expect("download_new_config send failed");
|
||||||
.lock()
|
return rx.recv().expect("download_new_config callback recv failed");
|
||||||
.unwrap()
|
},
|
||||||
.send(ApiMessage::General(GeneralMessage::AddVariant(web_config_to_settings_json(meta), Box::new(callback))))
|
Err(e) => {
|
||||||
.expect("download_new_config send failed");
|
log::error!("Invalid response from download: {}", e);
|
||||||
return rx.recv().expect("download_new_config callback recv failed");
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Cannot parse response from `{}`: {}", req_url, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(e) => log::warn!("Cannot get setting result from `{}`: {}", req_url, e),
|
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
@ -140,3 +210,36 @@ pub fn download_new_config(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Upload currently-loaded variant
|
||||||
|
pub fn upload_current_variant(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
|
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
|
||||||
|
let getter = move || {
|
||||||
|
let sender2 = sender.clone();
|
||||||
|
move |(steam_id, steam_username): (String, String)| {
|
||||||
|
sender2
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.send(ApiMessage::UploadCurrentVariant(steam_id, steam_username))
|
||||||
|
.expect("upload_current_variant send failed");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
super::async_utils::AsyncIsh {
|
||||||
|
trans_setter: |params| {
|
||||||
|
if let Some(Primitive::String(steam_id)) = params.get(0) {
|
||||||
|
if let Some(Primitive::String(steam_username)) = params.get(1) {
|
||||||
|
Ok((steam_id.to_owned(), steam_username.to_owned()))
|
||||||
|
} else {
|
||||||
|
Err("upload_current_variant missing/invalid parameter 1".to_owned())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err("upload_current_variant missing/invalid parameter 0".to_owned())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set_get: getter,
|
||||||
|
trans_getter: |result| {
|
||||||
|
vec![result.into()]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -77,15 +77,17 @@ fn main() -> Result<(), ()> {
|
||||||
let mut loaded_settings =
|
let mut loaded_settings =
|
||||||
persist::FileJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
|
persist::FileJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
|
||||||
.map(|mut file| file.variants.remove(&0)
|
.map(|mut file| file.variants.remove(&0)
|
||||||
.map(|settings| settings::Settings::from_json(DEFAULT_SETTINGS_NAME.into(), settings, DEFAULT_SETTINGS_FILE.into()))
|
.map(|settings| settings::Settings::from_json(DEFAULT_SETTINGS_NAME.into(), settings, DEFAULT_SETTINGS_FILE.into(), 0))
|
||||||
.unwrap_or_else(|| settings::Settings::system_default(
|
.unwrap_or_else(|| settings::Settings::system_default(
|
||||||
DEFAULT_SETTINGS_FILE.into(),
|
DEFAULT_SETTINGS_FILE.into(),
|
||||||
|
0,
|
||||||
DEFAULT_SETTINGS_NAME.into(),
|
DEFAULT_SETTINGS_NAME.into(),
|
||||||
0,
|
0,
|
||||||
DEFAULT_SETTINGS_VARIANT_NAME.into())))
|
DEFAULT_SETTINGS_VARIANT_NAME.into())))
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
settings::Settings::system_default(
|
settings::Settings::system_default(
|
||||||
DEFAULT_SETTINGS_FILE.into(),
|
DEFAULT_SETTINGS_FILE.into(),
|
||||||
|
0,
|
||||||
DEFAULT_SETTINGS_NAME.into(),
|
DEFAULT_SETTINGS_NAME.into(),
|
||||||
0,
|
0,
|
||||||
DEFAULT_SETTINGS_VARIANT_NAME.into(),
|
DEFAULT_SETTINGS_VARIANT_NAME.into(),
|
||||||
|
@ -320,6 +322,10 @@ fn main() -> Result<(), ()> {
|
||||||
.register_async(
|
.register_async(
|
||||||
"WEB_download_new",
|
"WEB_download_new",
|
||||||
api::web::download_new_config(api_sender.clone())
|
api::web::download_new_config(api_sender.clone())
|
||||||
|
)
|
||||||
|
.register_async(
|
||||||
|
"WEB_upload_new",
|
||||||
|
api::web::upload_current_variant(api_sender.clone())
|
||||||
);
|
);
|
||||||
|
|
||||||
utility::ioperm_power_ec();
|
utility::ioperm_power_ec();
|
||||||
|
|
|
@ -9,6 +9,7 @@ use super::SettingsJson;
|
||||||
pub struct FileJson {
|
pub struct FileJson {
|
||||||
pub version: u64,
|
pub version: u64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub app_id: u64,
|
||||||
pub variants: HashMap<u64, SettingsJson>,
|
pub variants: HashMap<u64, SettingsJson>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ impl FileJson {
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_variant_or_create<P: AsRef<std::path::Path>>(path: P, mut setting: SettingsJson, given_name: String) -> Result<Self, SerdeError> {
|
pub fn update_variant_or_create<P: AsRef<std::path::Path>>(path: P, app_id: u64, mut setting: SettingsJson, given_name: String) -> Result<Self, SerdeError> {
|
||||||
if !setting.persistent {
|
if !setting.persistent {
|
||||||
return Self::open(path)
|
return Self::open(path)
|
||||||
}
|
}
|
||||||
|
@ -62,6 +63,7 @@ impl FileJson {
|
||||||
setting_variants.insert(setting.variant, setting);
|
setting_variants.insert(setting.variant, setting);
|
||||||
Self {
|
Self {
|
||||||
version: 0,
|
version: 0,
|
||||||
|
app_id: app_id,
|
||||||
name: given_name,
|
name: given_name,
|
||||||
variants: setting_variants,
|
variants: setting_variants,
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ pub fn auto_detect_provider() -> DriverJson {
|
||||||
let provider = auto_detect0(
|
let provider = auto_detect0(
|
||||||
None,
|
None,
|
||||||
crate::utility::settings_dir().join("autodetect.json"),
|
crate::utility::settings_dir().join("autodetect.json"),
|
||||||
|
0,
|
||||||
"".to_owned(),
|
"".to_owned(),
|
||||||
0,
|
0,
|
||||||
crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(),
|
crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(),
|
||||||
|
@ -76,6 +77,7 @@ pub fn auto_detect_provider() -> DriverJson {
|
||||||
pub fn auto_detect0(
|
pub fn auto_detect0(
|
||||||
settings_opt: Option<&SettingsJson>,
|
settings_opt: Option<&SettingsJson>,
|
||||||
json_path: std::path::PathBuf,
|
json_path: std::path::PathBuf,
|
||||||
|
app_id: u64,
|
||||||
name: String,
|
name: String,
|
||||||
variant_id: u64,
|
variant_id: u64,
|
||||||
variant_name: String,
|
variant_name: String,
|
||||||
|
@ -83,6 +85,7 @@ pub fn auto_detect0(
|
||||||
let mut general_driver = Box::new(General {
|
let mut general_driver = Box::new(General {
|
||||||
persistent: false,
|
persistent: false,
|
||||||
path: json_path,
|
path: json_path,
|
||||||
|
app_id,
|
||||||
name,
|
name,
|
||||||
variant_id,
|
variant_id,
|
||||||
variant_name,
|
variant_name,
|
||||||
|
|
|
@ -13,14 +13,15 @@ impl Driver {
|
||||||
name: String,
|
name: String,
|
||||||
settings: &SettingsJson,
|
settings: &SettingsJson,
|
||||||
json_path: std::path::PathBuf,
|
json_path: std::path::PathBuf,
|
||||||
|
app_id: u64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let name_bup = settings.name.clone();
|
let name_bup = settings.name.clone();
|
||||||
let id_bup = settings.variant;
|
let id_bup = settings.variant;
|
||||||
auto_detect0(Some(settings), json_path, name, id_bup, name_bup)
|
auto_detect0(Some(settings), json_path, app_id, name, id_bup, name_bup)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn system_default(json_path: std::path::PathBuf, name: String, variant_id: u64, variant_name: String) -> Self {
|
pub fn system_default(json_path: std::path::PathBuf, app_id: u64, name: String, variant_id: u64, variant_name: String) -> Self {
|
||||||
auto_detect0(None, json_path, name, variant_id, variant_name)
|
auto_detect0(None, json_path, app_id, name, variant_id, variant_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ impl std::fmt::Display for SettingVariant {
|
||||||
pub struct General {
|
pub struct General {
|
||||||
pub persistent: bool,
|
pub persistent: bool,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
|
pub app_id: u64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub variant_id: u64,
|
pub variant_id: u64,
|
||||||
pub variant_name: String,
|
pub variant_name: String,
|
||||||
|
@ -73,6 +74,14 @@ impl TGeneral for General {
|
||||||
self.path = path;
|
self.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn app_id(&mut self) -> &'_ mut u64 {
|
||||||
|
&mut self.app_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_app_id(&self) -> u64 {
|
||||||
|
self.app_id
|
||||||
|
}
|
||||||
|
|
||||||
fn get_name(&self) -> &'_ str {
|
fn get_name(&self) -> &'_ str {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
@ -108,7 +117,7 @@ impl TGeneral for General {
|
||||||
|
|
||||||
fn add_variant(&self, variant: crate::persist::SettingsJson) -> Result<Vec<crate::api::VariantInfo>, SettingError> {
|
fn add_variant(&self, variant: crate::persist::SettingsJson) -> Result<Vec<crate::api::VariantInfo>, SettingError> {
|
||||||
let variant_name = variant.name.clone();
|
let variant_name = variant.name.clone();
|
||||||
crate::persist::FileJson::update_variant_or_create(self.get_path(), variant, variant_name)
|
crate::persist::FileJson::update_variant_or_create(self.get_path(), self.get_app_id(), variant, variant_name)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!("failed to add variant: {}", e),
|
msg: format!("failed to add variant: {}", e),
|
||||||
setting: SettingVariant::General,
|
setting: SettingVariant::General,
|
||||||
|
@ -173,8 +182,8 @@ impl OnSet for Settings {
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_json(name: String, other: SettingsJson, json_path: PathBuf) -> Self {
|
pub fn from_json(name: String, other: SettingsJson, json_path: PathBuf, app_id: u64) -> Self {
|
||||||
let x = super::Driver::init(name, &other, json_path.clone());
|
let x = super::Driver::init(name, &other, json_path.clone(), app_id);
|
||||||
log::info!(
|
log::info!(
|
||||||
"Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}",
|
"Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}",
|
||||||
x.general.provider(),
|
x.general.provider(),
|
||||||
|
@ -190,8 +199,8 @@ impl Settings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn system_default(json_path: PathBuf, name: String, variant_id: u64, variant_name: String) -> Self {
|
pub fn system_default(json_path: PathBuf, app_id: u64, name: String, variant_id: u64, variant_name: String) -> Self {
|
||||||
let driver = super::Driver::system_default(json_path, name, variant_id, variant_name);
|
let driver = super::Driver::system_default(json_path, app_id, name, variant_id, variant_name);
|
||||||
Self {
|
Self {
|
||||||
general: driver.general,
|
general: driver.general,
|
||||||
cpus: driver.cpus,
|
cpus: driver.cpus,
|
||||||
|
@ -201,7 +210,7 @@ impl Settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_system_default(&mut self, name: String, variant_id: u64, variant_name: String) {
|
pub fn load_system_default(&mut self, name: String, variant_id: u64, variant_name: String) {
|
||||||
let driver = super::Driver::system_default(self.general.get_path().to_owned(), name, variant_id, variant_name);
|
let driver = super::Driver::system_default(self.general.get_path().to_owned(), self.general.get_app_id(), name, variant_id, variant_name);
|
||||||
self.cpus = driver.cpus;
|
self.cpus = driver.cpus;
|
||||||
self.gpu = driver.gpu;
|
self.gpu = driver.gpu;
|
||||||
self.battery = driver.battery;
|
self.battery = driver.battery;
|
||||||
|
@ -222,6 +231,7 @@ impl Settings {
|
||||||
pub fn load_file(
|
pub fn load_file(
|
||||||
&mut self,
|
&mut self,
|
||||||
filename: PathBuf,
|
filename: PathBuf,
|
||||||
|
app_id: u64,
|
||||||
name: String,
|
name: String,
|
||||||
variant: u64,
|
variant: u64,
|
||||||
variant_name: String,
|
variant_name: String,
|
||||||
|
@ -231,7 +241,7 @@ impl Settings {
|
||||||
if json_path.exists() {
|
if json_path.exists() {
|
||||||
if variant == u64::MAX {
|
if variant == u64::MAX {
|
||||||
*self.general.persistent() = true;
|
*self.general.persistent() = true;
|
||||||
let file_json = FileJson::update_variant_or_create(&json_path, self.json(), variant_name.clone()).map_err(|e| SettingError {
|
let file_json = FileJson::update_variant_or_create(&json_path, app_id, self.json(), variant_name.clone()).map_err(|e| SettingError {
|
||||||
msg: format!("Failed to open settings {}: {}", json_path.display(), e),
|
msg: format!("Failed to open settings {}: {}", json_path.display(), e),
|
||||||
setting: SettingVariant::General,
|
setting: SettingVariant::General,
|
||||||
})?;
|
})?;
|
||||||
|
@ -252,7 +262,7 @@ impl Settings {
|
||||||
*self.general.persistent() = false;
|
*self.general.persistent() = false;
|
||||||
self.general.name(name);
|
self.general.name(name);
|
||||||
} else {
|
} else {
|
||||||
let x = super::Driver::init(name, settings_json, json_path.clone());
|
let x = super::Driver::init(name, settings_json, json_path.clone(), app_id);
|
||||||
log::info!("Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}", x.general.provider(), x.cpus.provider(), x.gpu.provider(), x.battery.provider());
|
log::info!("Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}", x.general.provider(), x.cpus.provider(), x.gpu.provider(), x.battery.provider());
|
||||||
self.general = x.general;
|
self.general = x.general;
|
||||||
self.cpus = x.cpus;
|
self.cpus = x.cpus;
|
||||||
|
@ -270,6 +280,7 @@ impl Settings {
|
||||||
}
|
}
|
||||||
*self.general.persistent() = false;
|
*self.general.persistent() = false;
|
||||||
}
|
}
|
||||||
|
*self.general.app_id() = app_id;
|
||||||
self.general.path(filename);
|
self.general.path(filename);
|
||||||
self.general.variant_id(variant);
|
self.general.variant_id(variant);
|
||||||
Ok(*self.general.persistent())
|
Ok(*self.general.persistent())
|
||||||
|
|
|
@ -105,6 +105,10 @@ pub trait TGeneral: OnSet + OnResume + OnPowerEvent + Debug + Send {
|
||||||
|
|
||||||
fn path(&mut self, path: std::path::PathBuf);
|
fn path(&mut self, path: std::path::PathBuf);
|
||||||
|
|
||||||
|
fn app_id(&mut self) -> &'_ mut u64;
|
||||||
|
|
||||||
|
fn get_app_id(&self) -> u64;
|
||||||
|
|
||||||
fn get_name(&self) -> &'_ str;
|
fn get_name(&self) -> &'_ str;
|
||||||
|
|
||||||
fn name(&mut self, name: String);
|
fn name(&mut self, name: String);
|
||||||
|
|
|
@ -383,6 +383,10 @@ export async function storeDownloadById(id: string): Promise<VariantInfo[]> {
|
||||||
return (await call_backend("WEB_download_new", [id]));
|
return (await call_backend("WEB_download_new", [id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function storeUpload(steam_id: string, steam_username: string): Promise<VariantInfo[]> {
|
||||||
|
return (await call_backend("WEB_upload_new", [steam_id, steam_username]));
|
||||||
|
}
|
||||||
|
|
||||||
export async function getAllSettingVariants(): Promise<VariantInfo[]> {
|
export async function getAllSettingVariants(): Promise<VariantInfo[]> {
|
||||||
console.log("GENERAL_get_all_variants");
|
console.log("GENERAL_get_all_variants");
|
||||||
return (await call_backend("GENERAL_get_all_variants", []));
|
return (await call_backend("GENERAL_get_all_variants", []));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
import {Component} from "react";
|
import { Component } from "react";
|
||||||
import {
|
import {
|
||||||
ToggleField,
|
ToggleField,
|
||||||
SliderField,
|
SliderField,
|
||||||
|
|
|
@ -35,6 +35,13 @@ export const CURRENT_VARIANT_GEN = "GENERAL_current_variant";
|
||||||
|
|
||||||
export const MESSAGE_LIST = "MESSAGE_messages";
|
export const MESSAGE_LIST = "MESSAGE_messages";
|
||||||
|
|
||||||
|
export const INTERNAL_STEAM_ID = "INTERNAL_steam_id";
|
||||||
|
export const INTERNAL_STEAM_USERNAME = "INTERNAL_stream_username";
|
||||||
|
|
||||||
|
export const STORE_RESULTS = "INTERNAL_store_results";
|
||||||
|
|
||||||
export const PERIODICAL_BACKEND_PERIOD = 5000; // milliseconds
|
export const PERIODICAL_BACKEND_PERIOD = 5000; // milliseconds
|
||||||
export const AUTOMATIC_REAPPLY_WAIT = 2000; // milliseconds
|
export const AUTOMATIC_REAPPLY_WAIT = 2000; // milliseconds
|
||||||
|
|
||||||
|
export const STORE_RESULTS_URI = "/plugins/PowerTools/settings_store";
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
Field,
|
Field,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
SingleDropdownOption,
|
SingleDropdownOption,
|
||||||
|
Navigation,
|
||||||
//NotchLabel
|
//NotchLabel
|
||||||
//gamepadDialogClasses,
|
//gamepadDialogClasses,
|
||||||
//joinClassNames,
|
//joinClassNames,
|
||||||
|
@ -22,6 +23,7 @@ import {
|
||||||
import { VFC, useState } from "react";
|
import { VFC, useState } from "react";
|
||||||
import { GiDrill, GiTimeBomb, GiTimeTrap, GiDynamite } from "react-icons/gi";
|
import { GiDrill, GiTimeBomb, GiTimeTrap, GiDynamite } from "react-icons/gi";
|
||||||
import { HiRefresh, HiTrash, HiPlus, HiUpload } from "react-icons/hi";
|
import { HiRefresh, HiTrash, HiPlus, HiUpload } from "react-icons/hi";
|
||||||
|
import { TbWorldPlus } from "react-icons/tb";
|
||||||
|
|
||||||
//import * as python from "./python";
|
//import * as python from "./python";
|
||||||
import * as backend from "./backend";
|
import * as backend from "./backend";
|
||||||
|
@ -63,6 +65,12 @@ import {
|
||||||
|
|
||||||
MESSAGE_LIST,
|
MESSAGE_LIST,
|
||||||
|
|
||||||
|
INTERNAL_STEAM_ID,
|
||||||
|
INTERNAL_STEAM_USERNAME,
|
||||||
|
|
||||||
|
STORE_RESULTS,
|
||||||
|
STORE_RESULTS_URI,
|
||||||
|
|
||||||
PERIODICAL_BACKEND_PERIOD,
|
PERIODICAL_BACKEND_PERIOD,
|
||||||
AUTOMATIC_REAPPLY_WAIT,
|
AUTOMATIC_REAPPLY_WAIT,
|
||||||
} from "./consts";
|
} from "./consts";
|
||||||
|
@ -73,10 +81,13 @@ import { Battery } from "./components/battery";
|
||||||
import { Cpus } from "./components/cpus";
|
import { Cpus } from "./components/cpus";
|
||||||
import { DevMessages } from "./components/message";
|
import { DevMessages } from "./components/message";
|
||||||
|
|
||||||
|
import { StoreResultsPage } from "./store/page";
|
||||||
|
|
||||||
var periodicHook: NodeJS.Timeout | null = null;
|
var periodicHook: NodeJS.Timeout | null = null;
|
||||||
var lifetimeHook: any = null;
|
var lifetimeHook: any = null;
|
||||||
var startHook: any = null;
|
var startHook: any = null;
|
||||||
var endHook: any = null;
|
var endHook: any = null;
|
||||||
|
var userHook: any = null;
|
||||||
var usdplReady = false;
|
var usdplReady = false;
|
||||||
|
|
||||||
var tryNotifyProfileChange = function() {};
|
var tryNotifyProfileChange = function() {};
|
||||||
|
@ -118,6 +129,10 @@ const reload = function() {
|
||||||
console.debug("POWERTOOLS: got limits ", limits);
|
console.debug("POWERTOOLS: got limits ", limits);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!get_value(STORE_RESULTS)) {
|
||||||
|
backend.resolve(backend.searchStoreByAppId(0), (results) => set_value(STORE_RESULTS, results));
|
||||||
|
}
|
||||||
|
|
||||||
backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) });
|
backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) });
|
||||||
backend.resolve_nullable(backend.getBatteryChargeRate(), (rate: number | null) => { set_value(CHARGE_RATE_BATT, rate) });
|
backend.resolve_nullable(backend.getBatteryChargeRate(), (rate: number | null) => { set_value(CHARGE_RATE_BATT, rate) });
|
||||||
backend.resolve_nullable(backend.getBatteryChargeMode(), (mode: string | null) => { set_value(CHARGE_MODE_BATT, mode) });
|
backend.resolve_nullable(backend.getBatteryChargeMode(), (mode: string | null) => { set_value(CHARGE_MODE_BATT, mode) });
|
||||||
|
@ -175,6 +190,7 @@ const clearHooks = function() {
|
||||||
lifetimeHook?.unregister();
|
lifetimeHook?.unregister();
|
||||||
startHook?.unregister();
|
startHook?.unregister();
|
||||||
endHook?.unregister();
|
endHook?.unregister();
|
||||||
|
userHook?.unregister();
|
||||||
|
|
||||||
backend.log(backend.LogLevel.Info, "Unregistered PowerTools callbacks, so long and thanks for all the fish.");
|
backend.log(backend.LogLevel.Info, "Unregistered PowerTools callbacks, so long and thanks for all the fish.");
|
||||||
};
|
};
|
||||||
|
@ -209,7 +225,6 @@ const registerCallbacks = function(autoclear: boolean) {
|
||||||
let appId = gameInfo.appid.toString();
|
let appId = gameInfo.appid.toString();
|
||||||
|
|
||||||
backend.log(backend.LogLevel.Info, "RegisterForGameActionStart callback(" + actionType + ", " + id + ")");
|
backend.log(backend.LogLevel.Info, "RegisterForGameActionStart callback(" + actionType + ", " + id + ")");
|
||||||
// don't use gameInfo.appid, haha
|
|
||||||
backend.resolve(
|
backend.resolve(
|
||||||
backend.loadGeneralSettings(appId, gameInfo.display_name, "0", undefined),
|
backend.loadGeneralSettings(appId, gameInfo.display_name, "0", undefined),
|
||||||
(ok: boolean) => {
|
(ok: boolean) => {
|
||||||
|
@ -221,6 +236,12 @@ const registerCallbacks = function(autoclear: boolean) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
backend.resolve(
|
||||||
|
backend.searchStoreByAppId(appId),
|
||||||
|
(results: backend.StoreMetadata[]) => {
|
||||||
|
set_value(STORE_RESULTS, results);
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// this fires immediately, so let's ignore that callback
|
// this fires immediately, so let's ignore that callback
|
||||||
|
@ -236,6 +257,20 @@ const registerCallbacks = function(autoclear: boolean) {
|
||||||
setTimeout(() => backend.forceApplySettings(), AUTOMATIC_REAPPLY_WAIT);
|
setTimeout(() => backend.forceApplySettings(), AUTOMATIC_REAPPLY_WAIT);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
userHook = SteamClient.User.RegisterForCurrentUserChanges((data) => {
|
||||||
|
const accountName = data.strAccountName;
|
||||||
|
const steamId = data.strSteamID;
|
||||||
|
SteamClient.User.GetLoginUsers().then((users: any) => {
|
||||||
|
users.forEach((user: any) => {
|
||||||
|
if (user && user.accountName == accountName) {
|
||||||
|
set_value(INTERNAL_STEAM_ID, steamId);
|
||||||
|
set_value(INTERNAL_STEAM_USERNAME, user.personaName ? user.personaName : accountName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
backend.log(backend.LogLevel.Debug, "Registered PowerTools callbacks, hello!");
|
backend.log(backend.LogLevel.Debug, "Registered PowerTools callbacks, hello!");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -373,7 +408,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
}}>
|
}}>
|
||||||
<DialogButton
|
<DialogButton
|
||||||
style={{
|
style={{
|
||||||
maxWidth: "45%",
|
maxWidth: "30%",
|
||||||
minWidth: "auto",
|
minWidth: "auto",
|
||||||
}}
|
}}
|
||||||
//layout="below"
|
//layout="below"
|
||||||
|
@ -396,16 +431,35 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
</DialogButton>
|
</DialogButton>
|
||||||
<DialogButton
|
<DialogButton
|
||||||
style={{
|
style={{
|
||||||
maxWidth: "45%",
|
maxWidth: "30%",
|
||||||
minWidth: "auto",
|
minWidth: "auto",
|
||||||
}}
|
}}
|
||||||
//layout="below"
|
//layout="below"
|
||||||
onClick={(_: MouseEvent) => {
|
onClick={(_: MouseEvent) => {
|
||||||
backend.log(backend.LogLevel.Debug, "Clicked on unimplemented upload button");
|
const steamId = get_value(INTERNAL_STEAM_ID);
|
||||||
|
const steamName = get_value(INTERNAL_STEAM_USERNAME);
|
||||||
|
if (steamId && steamName) {
|
||||||
|
backend.storeUpload(steamId, steamName);
|
||||||
|
} else {
|
||||||
|
backend.log(backend.LogLevel.Warn, "Cannot upload with null steamID (is null: " + !steamId + ") and/or username (is null: " + !steamName + ")");
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<HiUpload/>
|
<HiUpload/>
|
||||||
</DialogButton>
|
</DialogButton>
|
||||||
|
<DialogButton
|
||||||
|
style={{
|
||||||
|
maxWidth: "30%",
|
||||||
|
minWidth: "auto",
|
||||||
|
}}
|
||||||
|
//layout="below"
|
||||||
|
onClick={(_: MouseEvent) => {
|
||||||
|
Navigation.Navigate(STORE_RESULTS_URI);
|
||||||
|
Navigation.CloseSideMenus();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TbWorldPlus />
|
||||||
|
</DialogButton>
|
||||||
</PanelSectionRow>
|
</PanelSectionRow>
|
||||||
|
|
||||||
<Debug idc={idc}/>
|
<Debug idc={idc}/>
|
||||||
|
@ -453,6 +507,7 @@ export default definePlugin((serverApi: ServerAPI) => {
|
||||||
ico = <span><GiDynamite /><GiTimeTrap /><GiTimeBomb /></span>;
|
ico = <span><GiDynamite /><GiTimeTrap /><GiTimeBomb /></span>;
|
||||||
}
|
}
|
||||||
//registerCallbacks(false);
|
//registerCallbacks(false);
|
||||||
|
serverApi.routerHook.addRoute(STORE_RESULTS_URI, StoreResultsPage);
|
||||||
return {
|
return {
|
||||||
title: <div className={staticClasses.Title}>PowerTools</div>,
|
title: <div className={staticClasses.Title}>PowerTools</div>,
|
||||||
content: <Content serverAPI={serverApi} />,
|
content: <Content serverAPI={serverApi} />,
|
||||||
|
|
48
src/store/page.tsx
Normal file
48
src/store/page.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { Component, Fragment } from "react";
|
||||||
|
|
||||||
|
import * as backend from "../backend";
|
||||||
|
import { tr } from "usdpl-front";
|
||||||
|
import { get_value} from "usdpl-front";
|
||||||
|
|
||||||
|
import {
|
||||||
|
STORE_RESULTS,
|
||||||
|
} from "../consts";
|
||||||
|
|
||||||
|
export class StoreResultsPage extends Component {
|
||||||
|
constructor() {
|
||||||
|
super({});
|
||||||
|
this.state = {
|
||||||
|
reloadThingy: "/shrug",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const storeItems = get_value(STORE_RESULTS) as backend.StoreMetadata[] | undefined;
|
||||||
|
console.log("POWERTOOLS: Rendering store results", storeItems);
|
||||||
|
if (storeItems) {
|
||||||
|
if (storeItems.length == 0) {
|
||||||
|
backend.log(backend.LogLevel.Warn, "No store results; got array with length 0 from cache");
|
||||||
|
return (<div>
|
||||||
|
{ tr("No results") /* TODO translate */ }
|
||||||
|
</div>);
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
return storeItems.map((meta: backend.StoreMetadata) => {
|
||||||
|
<div>
|
||||||
|
<div> { meta.name } </div>
|
||||||
|
<div> { tr("Created by") /* TODO translate */} { meta.steam_username } </div>
|
||||||
|
<div> { meta.tags.map((tag: string) => <span>{tag}</span>) } </div>
|
||||||
|
Hey NG you should finish this page
|
||||||
|
</div>
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
backend.log(backend.LogLevel.Warn, "Store failed to load; got null from cache");
|
||||||
|
// store did not pre-load when the game started
|
||||||
|
return (<Fragment>
|
||||||
|
{ tr("Store failed to load") /* TODO translate */ }
|
||||||
|
</Fragment>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue