mirror of
https://github.com/ALEZ-DEV/Babylonia-terminal.git
synced 2026-03-21 21:58:52 +00:00
can now download and install proton from GUI
This commit is contained in:
parent
c6eacbfeaa
commit
4d07600ea6
51
babylonia_terminal_launcher/lib/models/proton.dart
Normal file
51
babylonia_terminal_launcher/lib/models/proton.dart
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import './../messages/steps/proton.pb.dart';
|
||||||
|
import './../providers/providers.dart';
|
||||||
|
|
||||||
|
enum ProtonInstallationState {
|
||||||
|
idle,
|
||||||
|
downloading,
|
||||||
|
decompressing,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Proton with ChangeNotifier {
|
||||||
|
ProtonInstallationState protonState = ProtonInstallationState.idle;
|
||||||
|
|
||||||
|
Int64 currentProgress = Int64(0);
|
||||||
|
Int64 maxProgress = Int64(0);
|
||||||
|
|
||||||
|
Future startInstallation(BuildContext context, String protonVersion) async {
|
||||||
|
protonState = ProtonInstallationState.downloading;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
StartProtonInstallation(protonVersion: protonVersion).sendSignalToRust();
|
||||||
|
final progressStream = ProtonDownloadProgress.rustSignalStream;
|
||||||
|
await for (final rustSignal in progressStream) {
|
||||||
|
currentProgress = rustSignal.message.current;
|
||||||
|
maxProgress = rustSignal.message.max;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
if (currentProgress >= maxProgress) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final notificationDecompressingStream =
|
||||||
|
NotifyProtonStartDecompressing.rustSignalStream;
|
||||||
|
await for (final _ in notificationDecompressingStream) {
|
||||||
|
protonState = ProtonInstallationState.decompressing;
|
||||||
|
notifyListeners();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
final notificationInstalledStream =
|
||||||
|
NotifiyProtonSuccessfullyInstalled.rustSignalStream;
|
||||||
|
await for (final _ in notificationInstalledStream) {
|
||||||
|
Provider.of<GameStateProvider>(context, listen: false).updateGameState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:yaru/theme.dart';
|
|
||||||
|
|
||||||
class SimpleButton extends StatelessWidget {
|
class SimpleButton extends StatelessWidget {
|
||||||
const SimpleButton({super.key, required this.child, required this.onPressed});
|
const SimpleButton({super.key, required this.child, required this.onPressed});
|
||||||
|
|||||||
@ -3,7 +3,8 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:yaru/widgets.dart';
|
import 'package:yaru/widgets.dart';
|
||||||
|
|
||||||
import './../../models/github.dart';
|
import './../../models/github.dart';
|
||||||
import './../../providers/providers.dart';
|
import './../../models/proton.dart';
|
||||||
|
import './../../widgets/simple_button.dart';
|
||||||
|
|
||||||
class ProtonSteps extends StatefulWidget {
|
class ProtonSteps extends StatefulWidget {
|
||||||
const ProtonSteps({super.key});
|
const ProtonSteps({super.key});
|
||||||
@ -13,6 +14,40 @@ class ProtonSteps extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ProtonStepsState extends State<ProtonSteps> {
|
class _ProtonStepsState extends State<ProtonSteps> {
|
||||||
|
final Proton proton = Proton();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (_) => proton,
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
switch (Provider.of<Proton>(context).protonState) {
|
||||||
|
case ProtonInstallationState.idle:
|
||||||
|
return const InstallProton();
|
||||||
|
case ProtonInstallationState.downloading:
|
||||||
|
return const Center(
|
||||||
|
child: Text('downloading...'),
|
||||||
|
);
|
||||||
|
case ProtonInstallationState.decompressing:
|
||||||
|
return const Center(
|
||||||
|
child: Text('decompressing...'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InstallProton extends StatefulWidget {
|
||||||
|
const InstallProton({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InstallProton> createState() => _InstallProtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InstallProtonState extends State<InstallProton> {
|
||||||
bool hasLoaded = false;
|
bool hasLoaded = false;
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
late List<String> protonVersions;
|
late List<String> protonVersions;
|
||||||
@ -39,7 +74,7 @@ class _ProtonStepsState extends State<ProtonSteps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
child: isLoading
|
child: isLoading
|
||||||
? const Row(
|
? const Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -51,20 +86,33 @@ class _ProtonStepsState extends State<ProtonSteps> {
|
|||||||
Text('Fetching versions...'),
|
Text('Fetching versions...'),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: YaruPopupMenuButton(
|
: Row(
|
||||||
initialValue: selectedValue,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
itemBuilder: (_) => protonVersions
|
children: [
|
||||||
.map(
|
YaruPopupMenuButton(
|
||||||
(e) => PopupMenuItem(
|
initialValue: selectedValue,
|
||||||
value: e,
|
itemBuilder: (_) => protonVersions
|
||||||
child: Text(e),
|
.map(
|
||||||
),
|
(e) => PopupMenuItem(
|
||||||
)
|
value: e,
|
||||||
.toList(),
|
child: Text(e),
|
||||||
onSelected: (v) => setState(() {
|
),
|
||||||
selectedValue = v!;
|
)
|
||||||
}),
|
.toList(),
|
||||||
child: Text(selectedValue!),
|
onSelected: (v) => setState(() {
|
||||||
|
selectedValue = v;
|
||||||
|
}),
|
||||||
|
child: Text(selectedValue!),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
|
child: SimpleButton(
|
||||||
|
onPressed: () => Provider.of<Proton>(context, listen: false)
|
||||||
|
.startInstallation(context, selectedValue!),
|
||||||
|
child: const Text("Install"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
19
babylonia_terminal_launcher/messages/steps/proton.proto
Normal file
19
babylonia_terminal_launcher/messages/steps/proton.proto
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package proton;
|
||||||
|
|
||||||
|
// [RINF:RUST-SIGNAL]
|
||||||
|
message ProtonDownloadProgress {
|
||||||
|
uint64 current = 1;
|
||||||
|
uint64 max = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [RINF:DART-SIGNAL]
|
||||||
|
message StartProtonInstallation {
|
||||||
|
string protonVersion = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// [RINF:RUST-SIGNAL]
|
||||||
|
message NotifyProtonStartDecompressing {}
|
||||||
|
|
||||||
|
// [RINF:RUST-SIGNAL]
|
||||||
|
message NotifiyProtonSuccessfullyInstalled {}
|
||||||
2
babylonia_terminal_launcher/native/hub/Cargo.toml
Executable file → Normal file
2
babylonia_terminal_launcher/native/hub/Cargo.toml
Executable file → Normal file
@ -17,3 +17,5 @@ prost = "0.12.3"
|
|||||||
wasm-bindgen = "0.2.91"
|
wasm-bindgen = "0.2.91"
|
||||||
tokio_with_wasm = "0.4.3"
|
tokio_with_wasm = "0.4.3"
|
||||||
babylonia-terminal-sdk = { path = "./../../../babylonia-terminal-sdk" }
|
babylonia-terminal-sdk = { path = "./../../../babylonia-terminal-sdk" }
|
||||||
|
downloader = { git = "https://github.com/ALEZ-DEV/downloader" } # version = "0.2.7",
|
||||||
|
once_cell = "1.19.0"
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use crate::messages::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[warn(dead_code)]
|
#[warn(dead_code)]
|
||||||
struct GithubInfo;
|
pub struct GithubInfo;
|
||||||
|
|
||||||
impl GithubRequester for GithubInfo {
|
impl GithubRequester for GithubInfo {
|
||||||
fn set_github_release_index(&mut self, _: usize) {
|
fn set_github_release_index(&mut self, _: usize) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
//! This `hub` crate is the
|
//! This `hub` crate is the
|
||||||
//! entry point of the Rust logic.
|
//! entry point of the Rust logic.
|
||||||
|
|
||||||
|
use proton::listen_proton_installation;
|
||||||
// This `tokio` will be used by Rinf.
|
// This `tokio` will be used by Rinf.
|
||||||
// You can replace it with the original `tokio`
|
// You can replace it with the original `tokio`
|
||||||
// if you're not targeting the web.
|
// if you're not targeting the web.
|
||||||
@ -10,6 +11,7 @@ mod config;
|
|||||||
mod game_state;
|
mod game_state;
|
||||||
mod github;
|
mod github;
|
||||||
mod messages;
|
mod messages;
|
||||||
|
mod proton;
|
||||||
|
|
||||||
rinf::write_interface!();
|
rinf::write_interface!();
|
||||||
|
|
||||||
@ -27,4 +29,5 @@ async fn main() {
|
|||||||
tokio::spawn(config::listen_config());
|
tokio::spawn(config::listen_config());
|
||||||
tokio::spawn(config::listen_config());
|
tokio::spawn(config::listen_config());
|
||||||
tokio::spawn(github::listen_proton_version());
|
tokio::spawn(github::listen_proton_version());
|
||||||
|
tokio::spawn(proton::listen_proton_installation());
|
||||||
}
|
}
|
||||||
|
|||||||
129
babylonia_terminal_launcher/native/hub/src/proton.rs
Normal file
129
babylonia_terminal_launcher/native/hub/src/proton.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
use std::{future::Future, thread};
|
||||||
|
|
||||||
|
use babylonia_terminal_sdk::{
|
||||||
|
components::{
|
||||||
|
self,
|
||||||
|
component_downloader::ComponentDownloader,
|
||||||
|
proton_component::{self, ProtonComponent, PROTON_DEV, PROTON_REPO},
|
||||||
|
},
|
||||||
|
game_state::GameState,
|
||||||
|
utils::github_requester::{GithubRelease, GithubRequester},
|
||||||
|
};
|
||||||
|
use rinf::debug_print;
|
||||||
|
use tokio_with_wasm::tokio::{
|
||||||
|
self,
|
||||||
|
task::{spawn_blocking, spawn_local},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
github::GithubInfo,
|
||||||
|
messages::{
|
||||||
|
error::ReportError,
|
||||||
|
steps::proton::{
|
||||||
|
NotifiyProtonSuccessfullyInstalled, NotifyProtonStartDecompressing,
|
||||||
|
ProtonDownloadProgress, StartProtonInstallation,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn listen_proton_installation() {
|
||||||
|
let mut receiver = StartProtonInstallation::get_dart_signal_receiver();
|
||||||
|
while let Some(info) = receiver.recv().await {
|
||||||
|
let releases: Result<Vec<GithubRelease>, _> =
|
||||||
|
GithubInfo::get_github_releases(PROTON_DEV, PROTON_REPO).await;
|
||||||
|
if releases.is_err() {
|
||||||
|
ReportError {
|
||||||
|
error_message: format!("When fetching proton versions : {}", releases.unwrap_err()),
|
||||||
|
}
|
||||||
|
.send_signal_to_dart();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let checked_releases = releases.unwrap();
|
||||||
|
let release_index = checked_releases
|
||||||
|
.iter()
|
||||||
|
.position(|v| v.tag_name == info.message.proton_version);
|
||||||
|
|
||||||
|
if release_index.is_none() {
|
||||||
|
ReportError {
|
||||||
|
error_message: "Failed to find Proton version".to_string(),
|
||||||
|
}
|
||||||
|
.send_signal_to_dart();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut proton_component = ProtonComponent::new(GameState::get_config().await.config_dir);
|
||||||
|
|
||||||
|
proton_component.set_github_release_index(release_index.unwrap());
|
||||||
|
|
||||||
|
thread::spawn(|| {
|
||||||
|
tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.block_on(async {
|
||||||
|
install_proton(proton_component).await;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn install_proton(component: ProtonComponent) {
|
||||||
|
debug_print!("starting !!!!");
|
||||||
|
match component.install(Some(DownloadReporter::create())).await {
|
||||||
|
Err(e) => ReportError {
|
||||||
|
error_message: format!("Failed to install Proton : {}", e),
|
||||||
|
}
|
||||||
|
.send_signal_to_dart(),
|
||||||
|
Ok(_) => NotifiyProtonSuccessfullyInstalled {}.send_signal_to_dart(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DownloadReporterPrivate {
|
||||||
|
max_progress: Option<u64>,
|
||||||
|
last_current: u64,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DownloadReporter {
|
||||||
|
private: std::sync::Mutex<Option<DownloadReporterPrivate>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DownloadReporter {
|
||||||
|
pub fn create() -> std::sync::Arc<Self> {
|
||||||
|
std::sync::Arc::new(Self {
|
||||||
|
private: std::sync::Mutex::new(None),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl downloader::progress::Reporter for DownloadReporter {
|
||||||
|
fn setup(&self, max_progress: Option<u64>, message: &str) {
|
||||||
|
let private = DownloadReporterPrivate {
|
||||||
|
max_progress,
|
||||||
|
last_current: 0,
|
||||||
|
message: message.to_owned(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut guard = self.private.lock().unwrap();
|
||||||
|
*guard = Some(private);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn progress(&self, current: u64) {
|
||||||
|
if let Some(p) = self.private.lock().unwrap().as_mut() {
|
||||||
|
ProtonDownloadProgress {
|
||||||
|
current: current,
|
||||||
|
max: p.max_progress.unwrap(),
|
||||||
|
}
|
||||||
|
.send_signal_to_dart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_message(&self, _: &str) {}
|
||||||
|
|
||||||
|
fn done(&self) {
|
||||||
|
NotifyProtonStartDecompressing {}.send_signal_to_dart();
|
||||||
|
let mut guard = self.private.lock().unwrap();
|
||||||
|
*guard = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -49,6 +49,7 @@ dependencies:
|
|||||||
shared_preferences: ^2.2.3
|
shared_preferences: ^2.2.3
|
||||||
http: ^1.2.1
|
http: ^1.2.1
|
||||||
flutter_highlight: ^0.7.0
|
flutter_highlight: ^0.7.0
|
||||||
|
fixnum: ^1.1.0
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
media_kit:
|
media_kit:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user