Skip to content

Commit 1321f69

Browse files
committed
feat(launcher): ✨ Support copying session file from other installations
1 parent 1f0ba24 commit 1321f69

File tree

3 files changed

+176
-76
lines changed

3 files changed

+176
-76
lines changed

alvr/launcher/src/actions.rs

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ pub fn worker(
2727
tokio::runtime::Runtime::new()
2828
.expect("Failed to create tokio runtime")
2929
.block_on(async {
30-
let client = reqwest::Client::builder()
30+
let req_client = reqwest::Client::builder()
3131
.user_agent("ALVR-Launcher")
3232
.build()
3333
.unwrap();
34-
let version_data = match fetch_all_releases(&client).await {
34+
let version_data = match fetch_all_releases(&req_client).await {
3535
Ok(data) => data,
3636
Err(e) => {
3737
eprintln!("Error fetching version data: {e}");
@@ -49,8 +49,17 @@ pub fn worker(
4949
};
5050
let res = match message {
5151
UiMessage::Quit => return,
52-
UiMessage::InstallServer(release) => {
53-
install_server(&worker_message_sender, release, &client).await
52+
UiMessage::InstallServer {
53+
release_info,
54+
session_version,
55+
} => {
56+
install_server(
57+
&worker_message_sender,
58+
release_info,
59+
session_version,
60+
&req_client,
61+
)
62+
.await
5463
}
5564
UiMessage::InstallClient(release_info) => {
5665
install_and_launch_apk(&worker_message_sender, release_info)
@@ -125,7 +134,7 @@ pub fn get_release(
125134
fn install_and_launch_apk(
126135
worker_message_sender: &Sender<WorkerMessage>,
127136
release: ReleaseInfo,
128-
) -> anyhow::Result<()> {
137+
) -> Result<()> {
129138
worker_message_sender.send(WorkerMessage::ProgressUpdate(Progress {
130139
message: "Starting install".into(),
131140
progress: 0.0,
@@ -205,7 +214,7 @@ async fn download(
205214
message: &str,
206215
url: &str,
207216
client: &reqwest::Client,
208-
) -> anyhow::Result<Vec<u8>> {
217+
) -> Result<Vec<u8>> {
209218
let res = client.get(url).send().await?;
210219
let total_size = res.content_length();
211220
let mut stream = res.bytes_stream();
@@ -232,9 +241,10 @@ async fn download(
232241

233242
async fn install_server(
234243
worker_message_sender: &Sender<WorkerMessage>,
235-
release: ReleaseInfo,
236-
client: &reqwest::Client,
237-
) -> anyhow::Result<()> {
244+
release_info: ReleaseInfo,
245+
session_version: Option<String>,
246+
req_client: &reqwest::Client,
247+
) -> Result<()> {
238248
worker_message_sender.send(WorkerMessage::ProgressUpdate(Progress {
239249
message: "Starting install".into(),
240250
progress: 0.0,
@@ -246,14 +256,20 @@ async fn install_server(
246256
"alvr_streamer_linux.tar.gz"
247257
};
248258

249-
let url = release
259+
let url = release_info
250260
.assets
251261
.get(file_name)
252262
.ok_or(anyhow::anyhow!("Unable to determine download link"))?;
253263

254-
let buffer = download(worker_message_sender, "Downloading Streamer", url, client).await?;
264+
let buffer = download(
265+
worker_message_sender,
266+
"Downloading Streamer",
267+
url,
268+
req_client,
269+
)
270+
.await?;
255271

256-
let installation_dir = installations_dir().join(&release.version);
272+
let installation_dir = installations_dir().join(&release_info.version);
257273

258274
fs::create_dir_all(&installation_dir)?;
259275

@@ -264,6 +280,31 @@ async fn install_server(
264280
tar::Archive::new(&mut GzDecoder::new(&mut buffer)).unpack(&installation_dir)?;
265281
}
266282

283+
if let Some(session_version) = session_version {
284+
assert!(cfg!(windows));
285+
286+
let installations = get_installations();
287+
for inst in installations {
288+
if inst.version == session_version {
289+
let source = alvr_filesystem::filesystem_layout_from_openvr_driver_root_dir(
290+
&installations_dir().join(session_version),
291+
)
292+
.unwrap()
293+
.session();
294+
295+
let destination = alvr_filesystem::filesystem_layout_from_openvr_driver_root_dir(
296+
&installation_dir,
297+
)
298+
.unwrap()
299+
.session();
300+
301+
fs::copy(source, destination)?;
302+
303+
break;
304+
}
305+
}
306+
}
307+
267308
Ok(())
268309
}
269310

@@ -295,11 +336,21 @@ pub fn get_installations() -> Vec<InstallationInfo> {
295336
}
296337
})
297338
.map(|entry| {
298-
let mut apk_path = entry.path();
299-
apk_path.push(APK_NAME);
339+
let has_session_json = if cfg!(windows) {
340+
alvr_filesystem::filesystem_layout_from_openvr_driver_root_dir(
341+
&entry.path(),
342+
)
343+
.map(|layout| layout.session().exists())
344+
.unwrap_or(false)
345+
} else {
346+
// On linux, the launcher does not need to manage the session files
347+
false
348+
};
349+
300350
InstallationInfo {
301351
version: entry.file_name().to_string_lossy().into(),
302-
is_apk_downloaded: apk_path.exists(),
352+
is_apk_downloaded: entry.path().join(APK_NAME).exists(),
353+
has_session_json,
303354
}
304355
})
305356
})

alvr/launcher/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ pub struct ReleaseInfo {
3030
}
3131

3232
pub enum UiMessage {
33-
InstallServer(ReleaseInfo),
33+
InstallServer {
34+
release_info: ReleaseInfo,
35+
session_version: Option<String>,
36+
},
3437
InstallClient(ReleaseInfo),
3538
Quit,
3639
}
3740

3841
pub struct InstallationInfo {
39-
pub version: String,
42+
version: String,
4043
is_apk_downloaded: bool,
44+
has_session_json: bool, // Only relevent on Windows
4145
}
4246

4347
fn main() {

alvr/launcher/src/ui.rs

Lines changed: 104 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ enum PopupType {
2525
None,
2626
DeleteInstallation(String),
2727
EditVersion(String),
28-
Version(Version),
28+
AddVersion {
29+
version_selection: Version,
30+
session_version_selection: Option<String>,
31+
},
2932
}
3033

3134
#[derive(Clone, PartialEq, Eq)]
@@ -67,47 +70,56 @@ impl Launcher {
6770
}
6871
}
6972

70-
fn version_popup(&self, ctx: &Context, mut version: Version) -> PopupType {
73+
fn version_popup(
74+
&self,
75+
ctx: &Context,
76+
mut version: Version,
77+
mut session_version: Option<String>,
78+
) -> PopupType {
7179
let response = alvr_gui_common::modal(
7280
ctx,
7381
"Add version",
7482
{
7583
// Safety: unwrap is safe because the "Add release" button is available after populating the release_channels_info.
7684
let release_channels_info = self.release_channels_info.as_ref().unwrap();
7785
Some(|ui: &mut Ui| {
78-
let (channel, version_str, versions): (&str, String, Vec<Version>) =
79-
match &version.release_channel {
80-
ReleaseChannelType::Stable => (
81-
"Stable",
82-
version.string.clone(),
83-
release_channels_info
84-
.stable
85-
.iter()
86-
.map(|release| Version {
87-
string: release.version.clone(),
88-
release_channel: ReleaseChannelType::Stable,
89-
})
90-
.collect(),
91-
),
92-
ReleaseChannelType::Nightly => (
93-
"Nightly",
94-
version.string.clone(),
95-
release_channels_info
96-
.nightly
97-
.iter()
98-
.map(|release| Version {
99-
string: release.version.clone(),
100-
release_channel: ReleaseChannelType::Nightly,
101-
})
102-
.collect(),
103-
),
104-
};
86+
let version_str = version.string.clone();
87+
let versions: Vec<_> = match &version.release_channel {
88+
ReleaseChannelType::Stable => release_channels_info
89+
.stable
90+
.iter()
91+
.map(|release| Version {
92+
string: release.version.clone(),
93+
release_channel: ReleaseChannelType::Stable,
94+
})
95+
.collect(),
96+
97+
ReleaseChannelType::Nightly => release_channels_info
98+
.nightly
99+
.iter()
100+
.map(|release| Version {
101+
string: release.version.clone(),
102+
release_channel: ReleaseChannelType::Nightly,
103+
})
104+
.collect(),
105+
};
106+
let installations_with_session: Vec<_> = self
107+
.installations
108+
.iter()
109+
.filter(|installation| installation.has_session_json)
110+
.map(|installation| installation.version.clone())
111+
.collect();
112+
105113
Grid::new("add-version-grid").num_columns(2).show(ui, |ui| {
106114
ui.label("Channel");
107-
108115
ui.with_layout(Layout::right_to_left(Align::Min), |ui| {
116+
let channel_str = match version.release_channel {
117+
ReleaseChannelType::Stable => "Stable",
118+
ReleaseChannelType::Nightly => "Nightly",
119+
};
120+
109121
ComboBox::from_id_salt("channel")
110-
.selected_text(channel)
122+
.selected_text(channel_str)
111123
.show_ui(ui, |ui| {
112124
ui.selectable_value(
113125
&mut version,
@@ -142,6 +154,25 @@ impl Launcher {
142154
})
143155
});
144156
ui.end_row();
157+
158+
if cfg!(windows) {
159+
ui.label("Copy session from:");
160+
ui.with_layout(Layout::right_to_left(Align::Min), |ui| {
161+
ComboBox::from_id_salt("session")
162+
.selected_text(session_version.clone().unwrap_or("None".into()))
163+
.show_ui(ui, |ui| {
164+
ui.selectable_value(&mut session_version, None, "None");
165+
for ver_str in installations_with_session {
166+
ui.selectable_value(
167+
&mut session_version,
168+
Some(ver_str.clone()),
169+
ver_str,
170+
);
171+
}
172+
})
173+
});
174+
ui.end_row();
175+
}
145176
});
146177
})
147178
},
@@ -151,32 +182,40 @@ impl Launcher {
151182
match response {
152183
Some(ModalButton::Cancel) => PopupType::None,
153184
Some(ModalButton::Custom(_)) => {
185+
let release_info = match &version.release_channel {
186+
ReleaseChannelType::Stable => self
187+
.release_channels_info
188+
.as_ref()
189+
.unwrap()
190+
.stable
191+
.iter()
192+
.find(|release| release.version == version.string)
193+
.unwrap()
194+
.clone(),
195+
ReleaseChannelType::Nightly => self
196+
.release_channels_info
197+
.as_ref()
198+
.unwrap()
199+
.nightly
200+
.iter()
201+
.find(|release| release.version == version.string)
202+
.unwrap()
203+
.clone(),
204+
};
205+
154206
self.ui_message_sender
155-
.send(UiMessage::InstallServer(match &version.release_channel {
156-
ReleaseChannelType::Stable => self
157-
.release_channels_info
158-
.as_ref()
159-
.unwrap()
160-
.stable
161-
.iter()
162-
.find(|release| release.version == version.string)
163-
.unwrap()
164-
.clone(),
165-
ReleaseChannelType::Nightly => self
166-
.release_channels_info
167-
.as_ref()
168-
.unwrap()
169-
.nightly
170-
.iter()
171-
.find(|release| release.version == version.string)
172-
.unwrap()
173-
.clone(),
174-
}))
207+
.send(UiMessage::InstallServer {
208+
release_info,
209+
session_version,
210+
})
175211
.ok();
176212

177213
PopupType::None
178214
}
179-
_ => PopupType::Version(version),
215+
_ => PopupType::AddVersion {
216+
version_selection: version,
217+
session_version_selection: session_version,
218+
},
180219
}
181220
}
182221

@@ -343,16 +382,22 @@ impl eframe::App for Launcher {
343382
)
344383
.clicked()
345384
{
346-
self.popup = PopupType::Version(Version {
347-
string: self.release_channels_info.as_ref().unwrap().stable[0]
348-
.version
349-
.clone(),
350-
release_channel: ReleaseChannelType::Stable,
351-
});
385+
self.popup = PopupType::AddVersion {
386+
version_selection: Version {
387+
string: self.release_channels_info.as_ref().unwrap().stable[0]
388+
.version
389+
.clone(),
390+
release_channel: ReleaseChannelType::Stable,
391+
},
392+
session_version_selection: None,
393+
};
352394
}
353395

354396
let popup = match mem::take(&mut self.popup) {
355-
PopupType::Version(version) => self.version_popup(ctx, version),
397+
PopupType::AddVersion {
398+
version_selection,
399+
session_version_selection,
400+
} => self.version_popup(ctx, version_selection, session_version_selection),
356401
PopupType::EditVersion(version) => self.edit_popup(ctx, version),
357402
PopupType::DeleteInstallation(version) => self.delete_popup(ctx, version),
358403
PopupType::None => PopupType::None,

0 commit comments

Comments
 (0)