mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Steam collections (#60)
This commit is contained in:
Generated
+139
-7
@@ -87,6 +87,7 @@ dependencies = [
|
|||||||
name = "boilr"
|
name = "boilr"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64",
|
||||||
"config",
|
"config",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"failure",
|
"failure",
|
||||||
@@ -99,6 +100,7 @@ dependencies = [
|
|||||||
"nom 7.0.0",
|
"nom 7.0.0",
|
||||||
"nom_locate",
|
"nom_locate",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"rusty-leveldb",
|
||||||
"serde 1.0.130",
|
"serde 1.0.130",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"steam_shortcuts_util",
|
"steam_shortcuts_util",
|
||||||
@@ -108,6 +110,12 @@ dependencies = [
|
|||||||
"winreg 0.10.1",
|
"winreg 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "build_const"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.7.1"
|
version = "3.7.1"
|
||||||
@@ -197,6 +205,15 @@ version = "0.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||||
|
dependencies = [
|
||||||
|
"build_const",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@@ -246,6 +263,27 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||||
|
dependencies = [
|
||||||
|
"errno-dragonfly",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno-dragonfly"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "failure"
|
name = "failure"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
@@ -351,6 +389,16 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs2"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -451,6 +499,17 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.1.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@@ -594,6 +653,12 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "integer-encoding"
|
||||||
|
version = "1.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48dc51180a9b377fd75814d0cc02199c20f8e99433d6762f650d39cdbbd3b56f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.3.1"
|
version = "2.3.1"
|
||||||
@@ -970,6 +1035,19 @@ version = "0.5.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.1.16",
|
||||||
|
"libc",
|
||||||
|
"rand_chacha 0.2.2",
|
||||||
|
"rand_core 0.5.1",
|
||||||
|
"rand_hc 0.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@@ -977,9 +1055,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha 0.3.1",
|
||||||
"rand_core",
|
"rand_core 0.6.3",
|
||||||
"rand_hc",
|
"rand_hc 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -989,7 +1077,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core",
|
"rand_core 0.6.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.1.16",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -998,7 +1095,16 @@ version = "0.6.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1007,7 +1113,7 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_core",
|
"rand_core 0.6.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1092,6 +1198,20 @@ version = "0.1.21"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusty-leveldb"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19365c4619fa0892aef573e6ee1b569b1161ac1ac3da765f550a17645192615e"
|
||||||
|
dependencies = [
|
||||||
|
"crc",
|
||||||
|
"errno",
|
||||||
|
"fs2",
|
||||||
|
"integer-encoding",
|
||||||
|
"rand 0.7.3",
|
||||||
|
"snap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
@@ -1219,6 +1339,12 @@ version = "1.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
|
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snap"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@@ -1296,7 +1422,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"rand",
|
"rand 0.8.4",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"remove_dir_all",
|
"remove_dir_all",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -1480,6 +1606,12 @@ dependencies = [
|
|||||||
"try-lock",
|
"try-lock",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.2+wasi-snapshot-preview1"
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ futures = { version = "^0.3.17" }
|
|||||||
dashmap = { version = "^4.0.2", features = ["serde"] }
|
dashmap = { version = "^4.0.2", features = ["serde"] }
|
||||||
fltk-theme = {version ="0.4" , optional = true }
|
fltk-theme = {version ="0.4" , optional = true }
|
||||||
is_executable = "1.0.1"
|
is_executable = "1.0.1"
|
||||||
|
rusty-leveldb = "0.3.6"
|
||||||
|
base64="0.13.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
fl2rust = { version = "0.4", optional = true }
|
fl2rust = { version = "0.4", optional = true }
|
||||||
|
|||||||
+8
-3
@@ -12,11 +12,16 @@ class UserInterface {open
|
|||||||
} {
|
} {
|
||||||
|
|
||||||
# ----- Steam -----
|
# ----- Steam -----
|
||||||
Fl_Input steam_location_input {
|
Fl_Check_Button steam_create_collections {
|
||||||
label {Steam Location}
|
label {Create Collections}
|
||||||
xywh {25 25 450 25} align 5
|
tooltip {Create Collections for each platform}
|
||||||
|
xywh {25 25 155 25} down_box DOWN_BOX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fl_Input steam_location_input {
|
||||||
|
label {Steam Location}
|
||||||
|
xywh {175 25 300 25} align 5
|
||||||
|
}
|
||||||
|
|
||||||
# ----- Art download -----
|
# ----- Art download -----
|
||||||
Fl_Check_Button enable_steamgrid_db_checkbox {
|
Fl_Check_Button enable_steamgrid_db_checkbox {
|
||||||
|
|||||||
@@ -33,3 +33,4 @@ enabled = true
|
|||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
[steam]
|
[steam]
|
||||||
|
create_collections = false
|
||||||
@@ -0,0 +1,422 @@
|
|||||||
|
use nom::FindSubstring;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
use rusty_leveldb::{LdbIterator, Options, WriteBatch, DB};
|
||||||
|
|
||||||
|
const BOILR_TAG: &'static str = "boilr";
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum SteamCollection {
|
||||||
|
Actual(ActualSteamCollection),
|
||||||
|
Deleted(DeletedCollection),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SteamCollection {
|
||||||
|
pub fn is_boilr_collection(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
SteamCollection::Actual(actual) => actual.is_boilr_collection(),
|
||||||
|
SteamCollection::Deleted(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
struct ActualSteamCollection {
|
||||||
|
key: String,
|
||||||
|
timestamp: u64,
|
||||||
|
value: String, //For custom collections, this value is a ValueCollection json serialized
|
||||||
|
#[serde(
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
rename = "conflictResolutionMethod"
|
||||||
|
)]
|
||||||
|
conflict_resolution_method: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", rename = "strMethodId")]
|
||||||
|
str_method_id: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
version: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActualSteamCollection {
|
||||||
|
fn new<B: AsRef<str>>(name: B, ids: &Vec<usize>) -> Self {
|
||||||
|
let name = name.as_ref();
|
||||||
|
let key = format!("user-collections.{}", name_to_key(name));
|
||||||
|
let value = serialize_collection_value(name, ids);
|
||||||
|
let start = SystemTime::now();
|
||||||
|
let since_the_epoch = start
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.expect("Time went backwards");
|
||||||
|
let timestamp = since_the_epoch.as_secs();
|
||||||
|
|
||||||
|
ActualSteamCollection {
|
||||||
|
key,
|
||||||
|
timestamp,
|
||||||
|
value,
|
||||||
|
conflict_resolution_method: Some("custom".to_string()),
|
||||||
|
str_method_id: Some("union-collections".to_string()),
|
||||||
|
version: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_boilr_collection(&self) -> bool {
|
||||||
|
self.key
|
||||||
|
.contains(&format!("user-collections.{}", BOILR_TAG))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
struct ValueCollection {
|
||||||
|
id: String,
|
||||||
|
name: String,
|
||||||
|
added: Vec<usize>,
|
||||||
|
removed: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValueCollection {
|
||||||
|
fn new<S: AsRef<str>>(name: S, game_ids: &Vec<usize>) -> Self {
|
||||||
|
let name = name.as_ref();
|
||||||
|
let id = name_to_key(name);
|
||||||
|
let value = ValueCollection {
|
||||||
|
id,
|
||||||
|
name: name.to_string(),
|
||||||
|
added: game_ids.clone(),
|
||||||
|
removed: vec![],
|
||||||
|
};
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
|
||||||
|
struct DeletedCollection {
|
||||||
|
key: String,
|
||||||
|
timestamp: usize,
|
||||||
|
is_deleted: bool,
|
||||||
|
version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Collection {
|
||||||
|
pub name: String,
|
||||||
|
pub game_ids: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_collections<S: AsRef<str>>(
|
||||||
|
steam_user_id: S,
|
||||||
|
collections_to_add: &Vec<Collection>,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
let steam_user_id = steam_user_id.as_ref();
|
||||||
|
let new_collections: Vec<(String, SteamCollection)> = collections_to_add
|
||||||
|
.iter()
|
||||||
|
.map(|c| {
|
||||||
|
let collection = ActualSteamCollection::new(&c.name, &c.game_ids);
|
||||||
|
(collection.key.clone(), SteamCollection::Actual(collection))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut db = open_db()?;
|
||||||
|
|
||||||
|
let current_categories = get_categories(steam_user_id, &mut db)?;
|
||||||
|
//this is a collection of collections, known as a category
|
||||||
|
let mut write_batch = WriteBatch::new();
|
||||||
|
|
||||||
|
for (category_key, mut collections) in current_categories {
|
||||||
|
collections.retain(|(_key, collection)| !collection.is_boilr_collection());
|
||||||
|
collections.extend(new_collections.clone());
|
||||||
|
save_category(category_key, collections, &mut write_batch)?;
|
||||||
|
|
||||||
|
if let Some(path) = get_vdf_path(steam_user_id) {
|
||||||
|
let content = std::fs::read_to_string(&path).expect("Should be able to read this file");
|
||||||
|
if let Some(mut vdf_collections) = parse_vdf_collection(content) {
|
||||||
|
let boilr_keys: Vec<String> = vdf_collections
|
||||||
|
.keys()
|
||||||
|
.filter(|k| k.contains(BOILR_TAG))
|
||||||
|
.map(|k| k.clone())
|
||||||
|
.collect();
|
||||||
|
for key in boilr_keys {
|
||||||
|
vdf_collections.remove(&key);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_vdfs = collections_to_add.iter().map(|collection| {
|
||||||
|
let key = name_to_key(&collection.name);
|
||||||
|
let vd_collection = VdfCollection {
|
||||||
|
id: key,
|
||||||
|
added: collection.game_ids.clone(),
|
||||||
|
removed: vec![],
|
||||||
|
};
|
||||||
|
vd_collection
|
||||||
|
});
|
||||||
|
for new_vdf in new_vdfs {
|
||||||
|
vdf_collections.insert(new_vdf.id.clone(), new_vdf.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_string = write_vdf_collection_to_string(
|
||||||
|
&path.clone().to_string_lossy(),
|
||||||
|
&vdf_collections,
|
||||||
|
);
|
||||||
|
if let Some(new_string) = new_string {
|
||||||
|
std::fs::write(path, new_string).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db.write(write_batch, true)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
fn get_vdf_path<S: AsRef<str>>(steamid: S) -> Option<PathBuf> {
|
||||||
|
match std::env::var("HOME") {
|
||||||
|
Ok(home) => {
|
||||||
|
let path = Path::new(&home)
|
||||||
|
.join(".steam")
|
||||||
|
.join("steam")
|
||||||
|
.join("userdata")
|
||||||
|
.join(steamid.as_ref())
|
||||||
|
.join("config")
|
||||||
|
.join("localconfig.vdf");
|
||||||
|
if path.exists() {
|
||||||
|
return Some(path.to_path_buf());
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Err(e) => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn get_vdf_path<S: AsRef<str>>(steamid: S) -> Option<PathBuf> {
|
||||||
|
match std::env::var("PROGRAMFILES(X86)") {
|
||||||
|
Ok(program_files) => {
|
||||||
|
let path = Path::new(&program_files)
|
||||||
|
.join("Steam")
|
||||||
|
.join("userdata")
|
||||||
|
.join(steamid.as_ref())
|
||||||
|
.join("config")
|
||||||
|
.join("localconfig.vdf");
|
||||||
|
if path.exists() {
|
||||||
|
Some(path.to_path_buf())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_e) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_category<S: AsRef<str>>(
|
||||||
|
category_key: S,
|
||||||
|
category: Vec<(String, SteamCollection)>,
|
||||||
|
batch: &mut WriteBatch,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
let json = serde_json::to_string(&category)?;
|
||||||
|
let prefixed = format!("\u{1}{}", json);
|
||||||
|
batch.put(category_key.as_ref().as_bytes(), prefixed.as_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_categories<S: AsRef<str>>(
|
||||||
|
steamid: S,
|
||||||
|
db: &mut DB,
|
||||||
|
) -> Result<HashMap<String, Vec<(String, SteamCollection)>>, Box<dyn Error>> {
|
||||||
|
let namespace_keys = get_namespace_keys(steamid, db);
|
||||||
|
let mut db_iter = db.new_iter()?;
|
||||||
|
let mut res = HashMap::new();
|
||||||
|
while let Some((key_bytes, data_bytes)) = db_iter.next() {
|
||||||
|
let key = String::from_utf8_lossy(&key_bytes).to_string();
|
||||||
|
//make sure that what we are looking at is a collection
|
||||||
|
//there are other things in this db as well
|
||||||
|
if namespace_keys.contains(&key) {
|
||||||
|
let data = String::from_utf8_lossy(&data_bytes);
|
||||||
|
let collections = parse_steam_collections(&data)?;
|
||||||
|
res.insert(key, collections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_db() -> Result<DB, Box<dyn Error>> {
|
||||||
|
let location = get_level_db_location();
|
||||||
|
let options = Options::default();
|
||||||
|
let open_res = DB::open(location.unwrap(), options);
|
||||||
|
if let Err(e) = &open_res {
|
||||||
|
match &e.code {
|
||||||
|
rusty_leveldb::StatusCode::LockError => {
|
||||||
|
println!("Could not lock the steam level database, make sure steam is turned off when running synchronizations");
|
||||||
|
}
|
||||||
|
rusty_leveldb::StatusCode::NotFound => {
|
||||||
|
println!("Could not find the steam level database, try to open and close steam once and synchronize again");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(open_res?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_namespace_keys<S: AsRef<str>>(steamid: S, db: &mut DB) -> HashSet<String> {
|
||||||
|
let keyprefix = get_steam_user_prefix(steamid);
|
||||||
|
|
||||||
|
let namespaces_key = format!("{}s", keyprefix);
|
||||||
|
let key_bytes = namespaces_key.as_bytes();
|
||||||
|
let namespaces = get_namespaces(db, key_bytes).unwrap_or_default();
|
||||||
|
let namespace_keys = namespaces
|
||||||
|
.iter()
|
||||||
|
.map(|c| format!("{}-{}", keyprefix, c.0))
|
||||||
|
.collect();
|
||||||
|
namespace_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_namespaces(db: &mut DB, key_bytes: &[u8]) -> Option<Vec<(i32, String)>> {
|
||||||
|
match db.get(key_bytes) {
|
||||||
|
Some(got) => {
|
||||||
|
let collection_bytes = got.as_slice();
|
||||||
|
let collectin_str = String::from_utf8_lossy(&collection_bytes)[1..].to_string();
|
||||||
|
let collection = serde_json::from_str(&collectin_str).unwrap_or_default();
|
||||||
|
Some(collection)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
fn get_level_db_location() -> Option<PathBuf> {
|
||||||
|
match std::env::var("HOME") {
|
||||||
|
Ok(home) => {
|
||||||
|
let path = Path::new(&home)
|
||||||
|
.join(".steam")
|
||||||
|
.join("steam")
|
||||||
|
.join("config")
|
||||||
|
.join("htmlcache")
|
||||||
|
.join("Local Storage")
|
||||||
|
.join("leveldb");
|
||||||
|
if path.exists() {
|
||||||
|
return Some(path.to_path_buf());
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Err(e) => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn get_level_db_location() -> Option<PathBuf> {
|
||||||
|
match std::env::var("LOCALAPPDATA") {
|
||||||
|
Ok(localdata) => {
|
||||||
|
let path = Path::new(&localdata)
|
||||||
|
.join("Steam")
|
||||||
|
.join("htmlcache")
|
||||||
|
.join("Local Storage")
|
||||||
|
.join("leveldb");
|
||||||
|
if path.exists() {
|
||||||
|
return Some(path.to_path_buf());
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Err(_e) => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_collection_value<S: AsRef<str>>(name: S, game_ids: &Vec<usize>) -> String {
|
||||||
|
let value = ValueCollection::new(name, game_ids);
|
||||||
|
let value_json = serde_json::to_string(&value).expect("Should be able to serialize known type");
|
||||||
|
value_json
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name_to_key<S: AsRef<str>>(name: S) -> String {
|
||||||
|
let config = base64::Config::new(base64::CharacterSet::Standard, false);
|
||||||
|
let base64 = base64::encode_config(name.as_ref(), config);
|
||||||
|
let key = format!("{}-{}", BOILR_TAG, base64);
|
||||||
|
key
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_steam_collections<S: AsRef<str>>(
|
||||||
|
input: S,
|
||||||
|
) -> Result<Vec<(String, SteamCollection)>, Box<dyn Error>> {
|
||||||
|
let input = input.as_ref();
|
||||||
|
let input = if input.starts_with("\u{1}") {
|
||||||
|
input[1..].to_string()
|
||||||
|
} else {
|
||||||
|
input.to_string()
|
||||||
|
};
|
||||||
|
let res = serde_json::from_str::<Vec<(String, SteamCollection)>>(&input)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_steam_user_prefix<S: AsRef<str>>(steamid: S) -> String {
|
||||||
|
let keyprefix = format!(
|
||||||
|
"_https://steamloopback.host\u{0000}\u{0001}U{}-cloud-storage-namespace",
|
||||||
|
steamid.as_ref()
|
||||||
|
);
|
||||||
|
keyprefix
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_vdf_collection<S: AsRef<str>>(input: S) -> Option<HashMap<String, VdfCollection>> {
|
||||||
|
let input = input.as_ref();
|
||||||
|
serde_json::from_str(input).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_vdf_collection_to_string<S: AsRef<str>>(
|
||||||
|
input: S,
|
||||||
|
vdf: &HashMap<String, VdfCollection>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let input = input.as_ref();
|
||||||
|
let str = serde_json::to_string(vdf).expect("Should be able to serialize known type");
|
||||||
|
let encoded_json = format!("\"{}\"", str.replace("\"", "\\\""));
|
||||||
|
let key = "\t\"user-collections\"\t\t";
|
||||||
|
if let Some(start_index) = input.find_substring(key) {
|
||||||
|
let start_index_plus_key = start_index + key.len();
|
||||||
|
if let Some(line_index) = input[start_index_plus_key..].find("\n") {
|
||||||
|
let end_index_in_full = line_index + start_index_plus_key;
|
||||||
|
let result = format!(
|
||||||
|
"{}{}{}",
|
||||||
|
input[..start_index_plus_key].to_string(),
|
||||||
|
encoded_json,
|
||||||
|
input[end_index_in_full..].to_string()
|
||||||
|
);
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct VdfCollection {
|
||||||
|
id: String,
|
||||||
|
added: Vec<usize>,
|
||||||
|
removed: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_serialize_collection() {
|
||||||
|
let games = vec![312200];
|
||||||
|
let mut collection = ActualSteamCollection::new("Itch", &games);
|
||||||
|
collection.timestamp = 1647763452;
|
||||||
|
let json = serde_json::to_string(&collection).unwrap();
|
||||||
|
let expected = include_str!("../testdata/leveldb/test_collection.json");
|
||||||
|
assert_eq!(json, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_serialize_collection_inner() {
|
||||||
|
let games = vec![312200];
|
||||||
|
let res = serialize_collection_value("Itch", &games);
|
||||||
|
let expected = include_str!("../testdata/leveldb/test_collection_value.json");
|
||||||
|
assert_eq!(res, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_categories() {
|
||||||
|
let input = include_str!("../testdata/leveldb/testcollections.json");
|
||||||
|
let collection = parse_steam_collections(input).unwrap();
|
||||||
|
assert_eq!(28, collection.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
mod settings;
|
mod settings;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod collections;
|
||||||
|
|
||||||
pub use settings::SteamSettings;
|
pub use settings::SteamSettings;
|
||||||
pub use utils::*;
|
pub use utils::*;
|
||||||
|
pub use collections::*;
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct SteamSettings {
|
pub struct SteamSettings {
|
||||||
pub location: Option<String>,
|
pub location: Option<String>,
|
||||||
|
pub create_collections: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ pub struct ShortcutInfo {
|
|||||||
pub struct SteamUsersInfo {
|
pub struct SteamUsersInfo {
|
||||||
pub steam_user_data_folder: String,
|
pub steam_user_data_folder: String,
|
||||||
pub shortcut_path: Option<String>,
|
pub shortcut_path: Option<String>,
|
||||||
|
pub user_id : String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the paths to the steam users shortcuts (one for each user)
|
/// Get the paths to the steam users shortcuts (one for each user)
|
||||||
@@ -80,6 +81,7 @@ pub fn get_shortcuts_paths(
|
|||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
.map(|folder| {
|
.map(|folder| {
|
||||||
|
let user_id = folder.file_name().to_string_lossy().to_string();
|
||||||
let folder_path = folder.path();
|
let folder_path = folder.path();
|
||||||
let folder_str = folder_path
|
let folder_str = folder_path
|
||||||
.to_str()
|
.to_str()
|
||||||
@@ -91,11 +93,13 @@ pub fn get_shortcuts_paths(
|
|||||||
return SteamUsersInfo {
|
return SteamUsersInfo {
|
||||||
steam_user_data_folder: folder_string,
|
steam_user_data_folder: folder_string,
|
||||||
shortcut_path: Some(shortcuts_path.to_str().unwrap().to_string()),
|
shortcut_path: Some(shortcuts_path.to_str().unwrap().to_string()),
|
||||||
|
user_id
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return SteamUsersInfo {
|
return SteamUsersInfo {
|
||||||
steam_user_data_folder: folder_string,
|
steam_user_data_folder: folder_string,
|
||||||
shortcut_path: None,
|
shortcut_path: None,
|
||||||
|
user_id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+71
-52
@@ -2,13 +2,17 @@ use steam_shortcuts_util::{shortcut::ShortcutOwned, shortcuts_to_bytes};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
egs::EpicPlatform,
|
egs::EpicPlatform,
|
||||||
|
heroic::HeroicPlatform,
|
||||||
legendary::LegendaryPlatform,
|
legendary::LegendaryPlatform,
|
||||||
lutris::lutris_platform::LutrisPlatform,
|
lutris::lutris_platform::LutrisPlatform,
|
||||||
platform::Platform,
|
platform::Platform,
|
||||||
settings::Settings,
|
settings::Settings,
|
||||||
steam::{get_shortcuts_for_user, get_shortcuts_paths, ShortcutInfo, SteamUsersInfo},
|
steam::{
|
||||||
|
get_shortcuts_for_user, get_shortcuts_paths, write_collections, Collection, ShortcutInfo,
|
||||||
|
SteamUsersInfo,
|
||||||
|
},
|
||||||
steamgriddb::download_images_for_users,
|
steamgriddb::download_images_for_users,
|
||||||
uplay::Uplay, heroic::HeroicPlatform,
|
uplay::Uplay,
|
||||||
};
|
};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
@@ -19,6 +23,12 @@ const BOILR_TAG: &str = "boilr";
|
|||||||
|
|
||||||
pub async fn run_sync(settings: &Settings) -> Result<(), Box<dyn Error>> {
|
pub async fn run_sync(settings: &Settings) -> Result<(), Box<dyn Error>> {
|
||||||
let mut userinfo_shortcuts = get_shortcuts_paths(&settings.steam)?;
|
let mut userinfo_shortcuts = get_shortcuts_paths(&settings.steam)?;
|
||||||
|
|
||||||
|
let platform_shortcuts = get_platform_shortcuts(settings);
|
||||||
|
let all_shortcuts: Vec<ShortcutOwned> = platform_shortcuts
|
||||||
|
.iter()
|
||||||
|
.flat_map(|s| s.1.clone())
|
||||||
|
.collect();
|
||||||
println!("Found {} user(s)", userinfo_shortcuts.len());
|
println!("Found {} user(s)", userinfo_shortcuts.len());
|
||||||
for user in userinfo_shortcuts.iter_mut() {
|
for user in userinfo_shortcuts.iter_mut() {
|
||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
@@ -27,14 +37,22 @@ pub async fn run_sync(settings: &Settings) -> Result<(), Box<dyn Error>> {
|
|||||||
println!(
|
println!(
|
||||||
"Found {} shortcuts for user: {}",
|
"Found {} shortcuts for user: {}",
|
||||||
shortcut_info.shortcuts.len(),
|
shortcut_info.shortcuts.len(),
|
||||||
user.steam_user_data_folder
|
user.user_id
|
||||||
);
|
);
|
||||||
|
|
||||||
remove_old_shortcuts(&mut shortcut_info);
|
remove_old_shortcuts(&mut shortcut_info);
|
||||||
update_platforms(settings, &mut shortcut_info.shortcuts);
|
|
||||||
|
shortcut_info.shortcuts.extend(all_shortcuts.clone());
|
||||||
|
|
||||||
fix_shortcut_icons(user, &mut shortcut_info.shortcuts);
|
fix_shortcut_icons(user, &mut shortcut_info.shortcuts);
|
||||||
save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path));
|
save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path));
|
||||||
user.shortcut_path = Some(shortcut_info.path.to_string_lossy().to_string());
|
|
||||||
|
if settings.steam.create_collections {
|
||||||
|
match write_shortcut_collections(&user.user_id, &platform_shortcuts) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(_e) => eprintln!("Could not write collections, make sure steam is shut down"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let duration = start_time.elapsed();
|
let duration = start_time.elapsed();
|
||||||
println!("Finished synchronizing games in: {:?}", duration);
|
println!("Finished synchronizing games in: {:?}", duration);
|
||||||
@@ -84,50 +102,46 @@ fn fix_shortcut_icons(user: &SteamUsersInfo, shortcuts: &mut Vec<ShortcutOwned>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec<ShortcutOwned>) {
|
fn write_shortcut_collections<S: AsRef<str>>(
|
||||||
update_platform_shortcuts(
|
steam_id: S,
|
||||||
&EpicPlatform::new(settings.epic_games.clone()),
|
platform_results: &Vec<(String, Vec<ShortcutOwned>)>,
|
||||||
new_user_shortcuts,
|
) -> Result<(), Box<dyn Error>> {
|
||||||
);
|
let mut collections = vec![];
|
||||||
update_platform_shortcuts(
|
|
||||||
&LegendaryPlatform::new(settings.legendary.clone()),
|
|
||||||
new_user_shortcuts,
|
|
||||||
);
|
|
||||||
update_platform_shortcuts(
|
|
||||||
&ItchPlatform::new(settings.itch.clone()),
|
|
||||||
new_user_shortcuts,
|
|
||||||
);
|
|
||||||
update_platform_shortcuts(
|
|
||||||
&OriginPlatform {
|
|
||||||
settings: settings.origin.clone(),
|
|
||||||
},
|
|
||||||
new_user_shortcuts,
|
|
||||||
);
|
|
||||||
update_platform_shortcuts(
|
|
||||||
&GogPlatform {
|
|
||||||
settings: settings.gog.clone(),
|
|
||||||
},
|
|
||||||
new_user_shortcuts,
|
|
||||||
);
|
|
||||||
update_platform_shortcuts(
|
|
||||||
&Uplay {
|
|
||||||
settings: settings.uplay.clone(),
|
|
||||||
},
|
|
||||||
new_user_shortcuts,
|
|
||||||
);
|
|
||||||
|
|
||||||
update_platform_shortcuts(
|
for (name, shortcuts) in platform_results {
|
||||||
&LutrisPlatform {
|
let game_ids = shortcuts.iter().map(|s| (s.app_id as usize)).collect();
|
||||||
|
collections.push(Collection {
|
||||||
|
name: name.clone(),
|
||||||
|
game_ids,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
println!("Writing {} collections ", collections.len());
|
||||||
|
write_collections(steam_id.as_ref(), &collections)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_platform_shortcuts(settings: &Settings) -> Vec<(String, Vec<ShortcutOwned>)> {
|
||||||
|
let platform_results = vec![
|
||||||
|
update_platform_shortcuts(&EpicPlatform::new(settings.epic_games.clone())),
|
||||||
|
update_platform_shortcuts(&LegendaryPlatform::new(settings.legendary.clone())),
|
||||||
|
update_platform_shortcuts(&ItchPlatform::new(settings.itch.clone())),
|
||||||
|
update_platform_shortcuts(&OriginPlatform {
|
||||||
|
settings: settings.origin.clone(),
|
||||||
|
}),
|
||||||
|
update_platform_shortcuts(&GogPlatform {
|
||||||
|
settings: settings.gog.clone(),
|
||||||
|
}),
|
||||||
|
update_platform_shortcuts(&Uplay {
|
||||||
|
settings: settings.uplay.clone(),
|
||||||
|
}),
|
||||||
|
update_platform_shortcuts(&LutrisPlatform {
|
||||||
settings: settings.lutris.clone(),
|
settings: settings.lutris.clone(),
|
||||||
},
|
}),
|
||||||
new_user_shortcuts,
|
update_platform_shortcuts(&HeroicPlatform {
|
||||||
);
|
|
||||||
update_platform_shortcuts(
|
|
||||||
&HeroicPlatform {
|
|
||||||
settings: settings.heroic.clone(),
|
settings: settings.heroic.clone(),
|
||||||
},
|
}),
|
||||||
new_user_shortcuts,
|
];
|
||||||
);
|
platform_results.iter().filter_map(|p| p.clone()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) {
|
fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) {
|
||||||
@@ -157,7 +171,7 @@ fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_platform_shortcuts<P, T, E>(platform: &P, current_shortcuts: &mut Vec<ShortcutOwned>)
|
fn update_platform_shortcuts<P, T, E>(platform: &P) -> Option<(String, Vec<ShortcutOwned>)>
|
||||||
where
|
where
|
||||||
P: Platform<T, E>,
|
P: Platform<T, E>,
|
||||||
E: std::fmt::Debug + std::fmt::Display,
|
E: std::fmt::Debug + std::fmt::Display,
|
||||||
@@ -170,9 +184,11 @@ where
|
|||||||
platform.name(),
|
platform.name(),
|
||||||
reason
|
reason
|
||||||
);
|
);
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut current_shortcuts = vec![];
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
if platform.create_symlinks() {
|
if platform.create_symlinks() {
|
||||||
let name = platform.name();
|
let name = platform.name();
|
||||||
@@ -181,13 +197,13 @@ where
|
|||||||
|
|
||||||
let shortcuts_to_add_result = platform.get_shortcuts();
|
let shortcuts_to_add_result = platform.get_shortcuts();
|
||||||
|
|
||||||
|
|
||||||
match shortcuts_to_add_result {
|
match shortcuts_to_add_result {
|
||||||
Ok(shortcuts_to_add) => {
|
Ok(shortcuts_to_add) => {
|
||||||
let mut shortcuts_to_add_transformed = vec![];
|
let mut shortcuts_to_add_transformed = vec![];
|
||||||
for shortcut in shortcuts_to_add{
|
for shortcut in shortcuts_to_add {
|
||||||
let mut shortcut_owned: ShortcutOwned = shortcut.into();
|
let mut shortcut_owned: ShortcutOwned = shortcut.into();
|
||||||
shortcut_owned.dev_kit_game_id = format!("{}-{}",BOILR_TAG,shortcut_owned.app_id);
|
shortcut_owned.dev_kit_game_id =
|
||||||
|
format!("{}-{}", BOILR_TAG, shortcut_owned.app_id);
|
||||||
shortcuts_to_add_transformed.push(shortcut_owned);
|
shortcuts_to_add_transformed.push(shortcut_owned);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,8 +222,10 @@ where
|
|||||||
} else {
|
} else {
|
||||||
shortcut_owned
|
shortcut_owned
|
||||||
};
|
};
|
||||||
current_shortcuts.push(shortcut_owned);
|
current_shortcuts.push(shortcut_owned.clone());
|
||||||
}
|
}
|
||||||
|
let name = platform.name();
|
||||||
|
return Some((name.to_string(), current_shortcuts));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("Error getting shortcuts from platform: {}", platform.name());
|
eprintln!("Error getting shortcuts from platform: {}", platform.name());
|
||||||
@@ -215,4 +233,5 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"key":"user-collections.boilr-SXRjaA","timestamp":1647763452,"value":"{\"id\":\"boilr-SXRjaA\",\"name\":\"Itch\",\"added\":[312200],\"removed\":[]}","conflictResolutionMethod":"custom","strMethodId":"union-collections"}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"id":"boilr-SXRjaA","name":"Itch","added":[312200],"removed":[]}
|
||||||
+1
File diff suppressed because one or more lines are too long
+271
@@ -0,0 +1,271 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
"showcases.2",
|
||||||
|
{
|
||||||
|
"key": "showcases.2",
|
||||||
|
"timestamp": 1627185068,
|
||||||
|
"value": "{\"nShowcaseId\":2,\"strCollectionId\":\"type-games\",\"eSortBy\":11,\"bExpanded\":true,\"nOrder\":1572675717433,\"nLastChangedMS\":1627185068325}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"showcases.-1",
|
||||||
|
{
|
||||||
|
"key": "showcases.-1",
|
||||||
|
"timestamp": 1572551831,
|
||||||
|
"value": "{\"nShowcaseId\":-1,\"strCollectionId\":\"\",\"eSortBy\":1,\"bExpanded\":false}",
|
||||||
|
"conflictResolutionMethod": "initial"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.favorite",
|
||||||
|
{
|
||||||
|
"key": "user-collections.favorite",
|
||||||
|
"timestamp": 1646915179,
|
||||||
|
"value": "{\"id\":\"favorite\",\"name\":\"Favorites\",\"added\":[265930,751780,433340,361420,337340,1055540,960990,240720,1364100,398850,233290,1245620],\"removed\":[]}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "766"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.hidden",
|
||||||
|
{
|
||||||
|
"key": "user-collections.hidden",
|
||||||
|
"timestamp": 1583777127,
|
||||||
|
"value": "{\"id\":\"hidden\",\"name\":\"Hidden\",\"added\":[622590,813000],\"removed\":[]}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"collection-bootstrap-complete",
|
||||||
|
{
|
||||||
|
"key": "collection-bootstrap-complete",
|
||||||
|
"timestamp": 1572551831,
|
||||||
|
"value": "true",
|
||||||
|
"conflictResolutionMethod": "initial"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"sc-version",
|
||||||
|
{
|
||||||
|
"key": "sc-version",
|
||||||
|
"timestamp": 1627720308,
|
||||||
|
"value": "6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-tyBrO3av85Yt",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-tyBrO3av85Yt",
|
||||||
|
"timestamp": 1647172018,
|
||||||
|
"value": "{\"id\":\"uc-tyBrO3av85Yt\",\"name\":\"Installed\",\"added\":[],\"removed\":[],\"filterSpec\":{\"nFormatVersion\":2,\"strSearchText\":\"\",\"filterGroups\":[{\"rgOptions\":[],\"bAcceptUnion\":true},{\"rgOptions\":[2,1],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false}]}}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "767"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-m1aOnX+0j8hd",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-m1aOnX+0j8hd",
|
||||||
|
"timestamp": 1647172018,
|
||||||
|
"value": "{\"id\":\"uc-m1aOnX+0j8hd\",\"name\":\"Ready TO Play\",\"added\":[],\"removed\":[],\"filterSpec\":{\"nFormatVersion\":2,\"strSearchText\":\"\",\"filterGroups\":[{\"rgOptions\":[],\"bAcceptUnion\":true},{\"rgOptions\":[2],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false}]}}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "767"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"showcases.3",
|
||||||
|
{
|
||||||
|
"key": "showcases.3",
|
||||||
|
"timestamp": 1589544934,
|
||||||
|
"value": "{\"nShowcaseId\":3,\"strCollectionId\":\"play-next\",\"eSortBy\":1,\"bExpanded\":false,\"nOrder\":1589544935035}",
|
||||||
|
"conflictResolutionMethod": "initial"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"whatsnew_lastseen",
|
||||||
|
{
|
||||||
|
"key": "whatsnew_lastseen",
|
||||||
|
"timestamp": 1589544939,
|
||||||
|
"value": "3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-Y33SC/drzUUE",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-Y33SC/drzUUE",
|
||||||
|
"timestamp": 1607528488,
|
||||||
|
"value": "{\"id\":\"uc-Y33SC/drzUUE\",\"name\":\"AllGames\",\"added\":[],\"removed\":[],\"filterSpec\":{\"nFormatVersion\":2,\"strSearchText\":\"\",\"filterGroups\":[{\"rgOptions\":[],\"bAcceptUnion\":true},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false}]}}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-in3wyYtlPtji",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-in3wyYtlPtji",
|
||||||
|
"timestamp": 1640761113,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "359"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"showcases.1616699857157",
|
||||||
|
{
|
||||||
|
"key": "showcases.1616699857157",
|
||||||
|
"timestamp": 1647376978,
|
||||||
|
"value": "{\"nShowcaseId\":1616699857157,\"strCollectionId\":\"recent-games\",\"eSortBy\":1,\"nLastChangedMS\":1647376978744}",
|
||||||
|
"version": "768"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-viSLEvPBQo8y",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-viSLEvPBQo8y",
|
||||||
|
"timestamp": 1640761088,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "354"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-v49SJCW8hvGt",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-v49SJCW8hvGt",
|
||||||
|
"timestamp": 1640761084,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "353"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-qOFB6+htBEw+",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-qOFB6+htBEw+",
|
||||||
|
"timestamp": 1640761104,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "357"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-eK5FEQBVV/f4",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-eK5FEQBVV/f4",
|
||||||
|
"timestamp": 1640761102,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "356"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-WY8/sP0+o0mi",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-WY8/sP0+o0mi",
|
||||||
|
"timestamp": 1640761091,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "355"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-tuuA/xdtEaPL",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-tuuA/xdtEaPL",
|
||||||
|
"timestamp": 1640761110,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "358"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-JxLU0W6+VB99",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-JxLU0W6+VB99",
|
||||||
|
"timestamp": 1640778296,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "513"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-x7kKBnx8rlm1",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-x7kKBnx8rlm1",
|
||||||
|
"timestamp": 1645356629,
|
||||||
|
"value": "{\"id\":\"uc-x7kKBnx8rlm1\",\"name\":\"Next\",\"added\":[1252330,403640,582160,337340,780290,236870,1182620,214560,105000,514900,480490,900270,384190,473690,34010,934780,536270,484900,984800,208650,250680,960990,692850,774361,1092430,399810,717610,893180,870780,718670,262060,214340,373650,452570,65930,330020,312200,1091500,548430,356650,17470,47780,337000,435150,373420,379720,47810,239140,761030,245280,716500,396750,470260,716490,1047220,330840,792100,368360,255070,331870,882100,268500,857980,427290,391540,499520,297130,205910,1150950,464920,2400,750920,418240,814380,302510,312520,9200,474960,741820,485030,633060,788100,760060,846470,1449560,529660,305620,1405790,414340,394510,863550,323190,233290,1349230,371140,214490,611760,1172450,206190,460950,739630,683320,304430,319630,264710,207690,1147550,601840,362890,200260,843260,557340,238320,1018850,1181400,874390,351920,274500,504210,322190,996580,813630,393190,597760,242760,470780,530320,965680,268130,424840,587430,582560,207170,960690,764790,220780,257850,234270,48000,200900,523780,1054490,428550,224480,547480,963000,613100,388880,230230,356400,475150,890720,701160,1168880,712730,493340,690640,699170,250700,522470,1127610,300550,1063490,233740,412020,291650,20900,223830,581270,281990,584980,209830,605450,1011190,555880,110800,582010,994220,115800,532210,304650,535480,443810,240760,431940,356040,231200,231910,437630],\"removed\":[]}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "765"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-BfHgIPPLf03m",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-BfHgIPPLf03m",
|
||||||
|
"timestamp": 1640778301,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "514"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-rlBhYJWJVfT7",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-rlBhYJWJVfT7",
|
||||||
|
"timestamp": 1644677712,
|
||||||
|
"value": "{\"id\":\"uc-rlBhYJWJVfT7\",\"name\":\"Completed\",\"added\":[80310,269050,250320,20920,258520,237930,98100,203160,205650,257510,343860,252410,221910,646570,31220,391220,212050,227000,632470,617290,1349230,873940,294100,1102190,1092790,874260,383870,409160,861540,1222140,894020,3830,1145360,546560,28050,205100,1070710,367520,219150,220,434170,213670,420,242680,102600,1057090,221640,286160,8930,35140,246420,341800,550,261570,40700,450390,380,8870,113200,620980,107100,207610,261030,436820,4580,219890,500,204360,212910,240,35700,80350,80360,29720,49400,225080,72850,57300,26800,55230,374320,405820,858260,80340,251470,1079800,201790,248820,50300,688420,211420,283160,266510,320,448280,368230,287700,113020,1172380,462770,80330,236430,12140,322500,244160,26500,40930,400430,17410,335300,238370,631570,1151640,1055540],\"removed\":[]}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "752"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-2mg3hoGsWUvy",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-2mg3hoGsWUvy",
|
||||||
|
"timestamp": 1640778308,
|
||||||
|
"is_deleted": true,
|
||||||
|
"version": "515"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-UGQi/7wUEotn",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-UGQi/7wUEotn",
|
||||||
|
"timestamp": 1644590139,
|
||||||
|
"value": "{\"id\":\"uc-UGQi/7wUEotn\",\"name\":\"Single player and Story Rich\",\"added\":[],\"removed\":[],\"filterSpec\":{\"nFormatVersion\":2,\"strSearchText\":\"\",\"filterGroups\":[{\"rgOptions\":[],\"bAcceptUnion\":true},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[7],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[1742],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false}]}}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "749"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-kiAlA*+Nothpn",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-kiAlA*+Nothpn",
|
||||||
|
"timestamp": 1645030805,
|
||||||
|
"value": "{\"id\":\"uc-kiAlA*+Nothpn\",\"name\":\"Co-op\",\"added\":[],\"removed\":[],\"filterSpec\":{\"nFormatVersion\":2,\"strSearchText\":\"\",\"filterGroups\":[{\"rgOptions\":[],\"bAcceptUnion\":true},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false},{\"rgOptions\":[3841,1685],\"bAcceptUnion\":false},{\"rgOptions\":[],\"bAcceptUnion\":false}]}}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "755"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-VLUd605CHPd+",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-VLUd605CHPd+",
|
||||||
|
"timestamp": 1647763452,
|
||||||
|
"value": "{\"id\":\"uc-VLUd605CHPd+\",\"name\":\"Itch\",\"added\":[312200],\"removed\":[]}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "771"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"user-collections.uc-DU8F01868yMa",
|
||||||
|
{
|
||||||
|
"key": "user-collections.uc-DU8F01868yMa",
|
||||||
|
"timestamp": 1647763461,
|
||||||
|
"value": "{\"id\":\"uc-DU8F01868yMa\",\"name\":\"TestTag\",\"added\":[],\"removed\":[]}",
|
||||||
|
"conflictResolutionMethod": "custom",
|
||||||
|
"strMethodId": "union-collections",
|
||||||
|
"version": "772"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"from-tag-Installed": {
|
||||||
|
"id": "from-tag-Installed",
|
||||||
|
"added": [
|
||||||
|
3601140154,
|
||||||
|
2719403116
|
||||||
|
],
|
||||||
|
"removed": []
|
||||||
|
},
|
||||||
|
"from-tag-Itch": {
|
||||||
|
"id": "from-tag-Itch",
|
||||||
|
"added": [
|
||||||
|
3601140154
|
||||||
|
],
|
||||||
|
"removed": []
|
||||||
|
},
|
||||||
|
"from-tag-Ready TO Play": {
|
||||||
|
"id": "from-tag-Ready TO Play",
|
||||||
|
"added": [
|
||||||
|
3601140154,
|
||||||
|
2719403116
|
||||||
|
],
|
||||||
|
"removed": []
|
||||||
|
},
|
||||||
|
"from-tag-Heroic": {
|
||||||
|
"id": "from-tag-Heroic",
|
||||||
|
"added": [
|
||||||
|
2719403116
|
||||||
|
],
|
||||||
|
"removed": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,6 +61,7 @@ fn empty_or_whitespace(input: String) -> Option<String> {
|
|||||||
fn update_settings_with_ui_values(settings: &mut Settings, ui: &UserInterface) {
|
fn update_settings_with_ui_values(settings: &mut Settings, ui: &UserInterface) {
|
||||||
// Steam location
|
// Steam location
|
||||||
settings.steam.location = empty_or_whitespace(ui.steam_location_input.value());
|
settings.steam.location = empty_or_whitespace(ui.steam_location_input.value());
|
||||||
|
settings.steam.create_collections = ui.steam_create_collections.value();
|
||||||
|
|
||||||
// Steamgrid db
|
// Steamgrid db
|
||||||
settings.steamgrid_db.enabled = ui.enable_steamgrid_db_checkbox.value();
|
settings.steamgrid_db.enabled = ui.enable_steamgrid_db_checkbox.value();
|
||||||
@@ -116,6 +117,9 @@ fn update_ui_with_settings(ui: &mut UserInterface, settings: &Settings) {
|
|||||||
.unwrap_or(steam::get_default_location().unwrap_or(String::from(""))),
|
.unwrap_or(steam::get_default_location().unwrap_or(String::from(""))),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ui.steam_create_collections
|
||||||
|
.set_value(settings.steam.create_collections);
|
||||||
|
|
||||||
ui.enable_steamgrid_db_checkbox
|
ui.enable_steamgrid_db_checkbox
|
||||||
.set_value(settings.steamgrid_db.enabled);
|
.set_value(settings.steamgrid_db.enabled);
|
||||||
ui.steamgrid_db_auth_key_input.set_value(
|
ui.steamgrid_db_auth_key_input.set_value(
|
||||||
|
|||||||
Reference in New Issue
Block a user