mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-01-13 11:40:27 +00:00
feat: downloader update
This commit is contained in:
parent
4315e36cbe
commit
289691896d
@ -6,12 +6,27 @@
|
||||
import '../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
// These functions are ignored because they are not marked as `pub`: `get_task_status`
|
||||
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`
|
||||
// These functions are ignored because they are not marked as `pub`: `get_session`, `get_task_status`
|
||||
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `eq`, `fmt`, `fmt`, `fmt`
|
||||
|
||||
/// Initialize the download manager session
|
||||
void downloaderInit({required String downloadDir}) => RustLib.instance.api
|
||||
.crateApiDownloaderApiDownloaderInit(downloadDir: downloadDir);
|
||||
/// Initialize the download manager session with persistence enabled
|
||||
///
|
||||
/// Parameters:
|
||||
/// - working_dir: The directory to store session data (persistence, DHT, etc.)
|
||||
/// - default_download_dir: The default directory to store downloads
|
||||
/// - upload_limit_bps: Upload speed limit in bytes per second (0 = unlimited)
|
||||
/// - download_limit_bps: Download speed limit in bytes per second (0 = unlimited)
|
||||
void downloaderInit({
|
||||
required String workingDir,
|
||||
required String defaultDownloadDir,
|
||||
int? uploadLimitBps,
|
||||
int? downloadLimitBps,
|
||||
}) => RustLib.instance.api.crateApiDownloaderApiDownloaderInit(
|
||||
workingDir: workingDir,
|
||||
defaultDownloadDir: defaultDownloadDir,
|
||||
uploadLimitBps: uploadLimitBps,
|
||||
downloadLimitBps: downloadLimitBps,
|
||||
);
|
||||
|
||||
/// Check if the downloader is initialized
|
||||
bool downloaderIsInitialized() =>
|
||||
@ -95,10 +110,34 @@ Future<void> downloaderPauseAll() =>
|
||||
Future<void> downloaderResumeAll() =>
|
||||
RustLib.instance.api.crateApiDownloaderApiDownloaderResumeAll();
|
||||
|
||||
/// Stop the downloader session
|
||||
/// Stop the downloader session (pauses all tasks but keeps session)
|
||||
Future<void> downloaderStop() =>
|
||||
RustLib.instance.api.crateApiDownloaderApiDownloaderStop();
|
||||
|
||||
/// Shutdown the downloader session completely (allows restart with new settings)
|
||||
Future<void> downloaderShutdown() =>
|
||||
RustLib.instance.api.crateApiDownloaderApiDownloaderShutdown();
|
||||
|
||||
/// Update global speed limits
|
||||
/// Note: rqbit Session doesn't support runtime limit changes,
|
||||
/// this function is a placeholder that returns an error.
|
||||
/// Speed limits should be set during downloader_init.
|
||||
Future<void> downloaderUpdateSpeedLimits({
|
||||
int? uploadLimitBps,
|
||||
int? downloadLimitBps,
|
||||
}) => RustLib.instance.api.crateApiDownloaderApiDownloaderUpdateSpeedLimits(
|
||||
uploadLimitBps: uploadLimitBps,
|
||||
downloadLimitBps: downloadLimitBps,
|
||||
);
|
||||
|
||||
/// Remove all completed tasks (equivalent to aria2's --seed-time=0 behavior)
|
||||
Future<int> downloaderRemoveCompletedTasks() =>
|
||||
RustLib.instance.api.crateApiDownloaderApiDownloaderRemoveCompletedTasks();
|
||||
|
||||
/// Check if there are any active (non-completed) tasks
|
||||
Future<bool> downloaderHasActiveTasks() =>
|
||||
RustLib.instance.api.crateApiDownloaderApiDownloaderHasActiveTasks();
|
||||
|
||||
/// Global statistics
|
||||
class DownloadGlobalStat {
|
||||
final BigInt downloadSpeed;
|
||||
|
||||
@ -72,7 +72,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
||||
String get codegenVersion => '2.11.1';
|
||||
|
||||
@override
|
||||
int get rustContentHash => -1465039096;
|
||||
int get rustContentHash => -641930410;
|
||||
|
||||
static const kDefaultExternalLibraryLoaderConfig =
|
||||
ExternalLibraryLoaderConfig(
|
||||
@ -126,7 +126,14 @@ abstract class RustLibApi extends BaseApi {
|
||||
required BigInt taskId,
|
||||
});
|
||||
|
||||
void crateApiDownloaderApiDownloaderInit({required String downloadDir});
|
||||
Future<bool> crateApiDownloaderApiDownloaderHasActiveTasks();
|
||||
|
||||
void crateApiDownloaderApiDownloaderInit({
|
||||
required String workingDir,
|
||||
required String defaultDownloadDir,
|
||||
int? uploadLimitBps,
|
||||
int? downloadLimitBps,
|
||||
});
|
||||
|
||||
bool crateApiDownloaderApiDownloaderIsInitialized();
|
||||
|
||||
@ -143,12 +150,21 @@ abstract class RustLibApi extends BaseApi {
|
||||
required bool deleteFiles,
|
||||
});
|
||||
|
||||
Future<int> crateApiDownloaderApiDownloaderRemoveCompletedTasks();
|
||||
|
||||
Future<void> crateApiDownloaderApiDownloaderResume({required BigInt taskId});
|
||||
|
||||
Future<void> crateApiDownloaderApiDownloaderResumeAll();
|
||||
|
||||
Future<void> crateApiDownloaderApiDownloaderShutdown();
|
||||
|
||||
Future<void> crateApiDownloaderApiDownloaderStop();
|
||||
|
||||
Future<void> crateApiDownloaderApiDownloaderUpdateSpeedLimits({
|
||||
int? uploadLimitBps,
|
||||
int? downloadLimitBps,
|
||||
});
|
||||
|
||||
Future<RustHttpResponse> crateApiHttpApiFetch({
|
||||
required MyMethod method,
|
||||
required String url,
|
||||
@ -700,19 +716,64 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
);
|
||||
|
||||
@override
|
||||
void crateApiDownloaderApiDownloaderInit({required String downloadDir}) {
|
||||
Future<bool> crateApiDownloaderApiDownloaderHasActiveTasks() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire
|
||||
.wire__crate__api__downloader_api__downloader_has_active_tasks(
|
||||
port_,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_bool,
|
||||
decodeErrorData: null,
|
||||
),
|
||||
constMeta: kCrateApiDownloaderApiDownloaderHasActiveTasksConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiDownloaderApiDownloaderHasActiveTasksConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "downloader_has_active_tasks",
|
||||
argNames: [],
|
||||
);
|
||||
|
||||
@override
|
||||
void crateApiDownloaderApiDownloaderInit({
|
||||
required String workingDir,
|
||||
required String defaultDownloadDir,
|
||||
int? uploadLimitBps,
|
||||
int? downloadLimitBps,
|
||||
}) {
|
||||
return handler.executeSync(
|
||||
SyncTask(
|
||||
callFfi: () {
|
||||
var arg0 = cst_encode_String(downloadDir);
|
||||
return wire.wire__crate__api__downloader_api__downloader_init(arg0);
|
||||
var arg0 = cst_encode_String(workingDir);
|
||||
var arg1 = cst_encode_String(defaultDownloadDir);
|
||||
var arg2 = cst_encode_opt_box_autoadd_u_32(uploadLimitBps);
|
||||
var arg3 = cst_encode_opt_box_autoadd_u_32(downloadLimitBps);
|
||||
return wire.wire__crate__api__downloader_api__downloader_init(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiDownloaderApiDownloaderInitConstMeta,
|
||||
argValues: [downloadDir],
|
||||
argValues: [
|
||||
workingDir,
|
||||
defaultDownloadDir,
|
||||
uploadLimitBps,
|
||||
downloadLimitBps,
|
||||
],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
@ -721,7 +782,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
TaskConstMeta get kCrateApiDownloaderApiDownloaderInitConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "downloader_init",
|
||||
argNames: ["downloadDir"],
|
||||
argNames: [
|
||||
"workingDir",
|
||||
"defaultDownloadDir",
|
||||
"uploadLimitBps",
|
||||
"downloadLimitBps",
|
||||
],
|
||||
);
|
||||
|
||||
@override
|
||||
@ -858,6 +924,35 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["taskId", "deleteFiles"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<int> crateApiDownloaderApiDownloaderRemoveCompletedTasks() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire
|
||||
.wire__crate__api__downloader_api__downloader_remove_completed_tasks(
|
||||
port_,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_u_32,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta:
|
||||
kCrateApiDownloaderApiDownloaderRemoveCompletedTasksConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta
|
||||
get kCrateApiDownloaderApiDownloaderRemoveCompletedTasksConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "downloader_remove_completed_tasks",
|
||||
argNames: [],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiDownloaderApiDownloaderResume({required BigInt taskId}) {
|
||||
return handler.executeNormal(
|
||||
@ -906,6 +1001,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
TaskConstMeta get kCrateApiDownloaderApiDownloaderResumeAllConstMeta =>
|
||||
const TaskConstMeta(debugName: "downloader_resume_all", argNames: []);
|
||||
|
||||
@override
|
||||
Future<void> crateApiDownloaderApiDownloaderShutdown() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__downloader_api__downloader_shutdown(
|
||||
port_,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiDownloaderApiDownloaderShutdownConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiDownloaderApiDownloaderShutdownConstMeta =>
|
||||
const TaskConstMeta(debugName: "downloader_shutdown", argNames: []);
|
||||
|
||||
@override
|
||||
Future<void> crateApiDownloaderApiDownloaderStop() {
|
||||
return handler.executeNormal(
|
||||
@ -927,6 +1045,41 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
TaskConstMeta get kCrateApiDownloaderApiDownloaderStopConstMeta =>
|
||||
const TaskConstMeta(debugName: "downloader_stop", argNames: []);
|
||||
|
||||
@override
|
||||
Future<void> crateApiDownloaderApiDownloaderUpdateSpeedLimits({
|
||||
int? uploadLimitBps,
|
||||
int? downloadLimitBps,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_opt_box_autoadd_u_32(uploadLimitBps);
|
||||
var arg1 = cst_encode_opt_box_autoadd_u_32(downloadLimitBps);
|
||||
return wire
|
||||
.wire__crate__api__downloader_api__downloader_update_speed_limits(
|
||||
port_,
|
||||
arg0,
|
||||
arg1,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiDownloaderApiDownloaderUpdateSpeedLimitsConstMeta,
|
||||
argValues: [uploadLimitBps, downloadLimitBps],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta
|
||||
get kCrateApiDownloaderApiDownloaderUpdateSpeedLimitsConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "downloader_update_speed_limits",
|
||||
argNames: ["uploadLimitBps", "downloadLimitBps"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<RustHttpResponse> crateApiHttpApiFetch({
|
||||
required MyMethod method,
|
||||
@ -2386,6 +2539,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return dco_decode_rsi_launcher_asar_data(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
int dco_decode_box_autoadd_u_32(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return raw as int;
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt dco_decode_box_autoadd_u_64(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@ -2537,6 +2696,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return raw == null ? null : dco_decode_box_autoadd_bool(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
int? dco_decode_opt_box_autoadd_u_32(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return raw == null ? null : dco_decode_box_autoadd_u_32(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt? dco_decode_opt_box_autoadd_u_64(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@ -2797,6 +2962,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return (sse_decode_rsi_launcher_asar_data(deserializer));
|
||||
}
|
||||
|
||||
@protected
|
||||
int sse_decode_box_autoadd_u_32(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
return (sse_decode_u_32(deserializer));
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt sse_decode_box_autoadd_u_64(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@ -3027,6 +3198,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
int? sse_decode_opt_box_autoadd_u_32(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
if (sse_decode_bool(deserializer)) {
|
||||
return (sse_decode_box_autoadd_u_32(deserializer));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt? sse_decode_opt_box_autoadd_u_64(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@ -3407,6 +3589,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
sse_encode_rsi_launcher_asar_data(self, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_u_32(self, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_u_64(BigInt self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@ -3619,6 +3807,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_u_32(int? self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
sse_encode_bool(self != null, serializer);
|
||||
if (self != null) {
|
||||
sse_encode_box_autoadd_u_32(self, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_u_64(BigInt? self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
@ -50,6 +50,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
dynamic raw,
|
||||
);
|
||||
|
||||
@protected
|
||||
int dco_decode_box_autoadd_u_32(dynamic raw);
|
||||
|
||||
@protected
|
||||
BigInt dco_decode_box_autoadd_u_64(dynamic raw);
|
||||
|
||||
@ -115,6 +118,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
bool? dco_decode_opt_box_autoadd_bool(dynamic raw);
|
||||
|
||||
@protected
|
||||
int? dco_decode_opt_box_autoadd_u_32(dynamic raw);
|
||||
|
||||
@protected
|
||||
BigInt? dco_decode_opt_box_autoadd_u_64(dynamic raw);
|
||||
|
||||
@ -203,6 +209,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
int sse_decode_box_autoadd_u_32(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BigInt sse_decode_box_autoadd_u_64(SseDeserializer deserializer);
|
||||
|
||||
@ -282,6 +291,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
bool? sse_decode_opt_box_autoadd_bool(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int? sse_decode_opt_box_autoadd_u_32(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BigInt? sse_decode_opt_box_autoadd_u_64(SseDeserializer deserializer);
|
||||
|
||||
@ -408,6 +420,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<ffi.Uint32> cst_encode_box_autoadd_u_32(int raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
return wire.cst_new_box_autoadd_u_32(cst_encode_u_32(raw));
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<ffi.Uint64> cst_encode_box_autoadd_u_64(BigInt raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
@ -538,6 +556,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
return raw == null ? ffi.nullptr : cst_encode_box_autoadd_bool(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<ffi.Uint32> cst_encode_opt_box_autoadd_u_32(int? raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
return raw == null ? ffi.nullptr : cst_encode_box_autoadd_u_32(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
ffi.Pointer<ffi.Uint64> cst_encode_opt_box_autoadd_u_64(BigInt? raw) {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
@ -829,6 +853,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_u_64(BigInt self, SseSerializer serializer);
|
||||
|
||||
@ -925,6 +952,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_bool(bool? self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_u_32(int? self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_u_64(BigInt? self, SseSerializer serializer);
|
||||
|
||||
@ -1337,10 +1367,34 @@ class RustLibWire implements BaseWire {
|
||||
_wire__crate__api__downloader_api__downloader_get_task_infoPtr
|
||||
.asFunction<void Function(int, int)>();
|
||||
|
||||
WireSyncRust2DartDco wire__crate__api__downloader_api__downloader_init(
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> download_dir,
|
||||
void wire__crate__api__downloader_api__downloader_has_active_tasks(
|
||||
int port_,
|
||||
) {
|
||||
return _wire__crate__api__downloader_api__downloader_init(download_dir);
|
||||
return _wire__crate__api__downloader_api__downloader_has_active_tasks(
|
||||
port_,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__downloader_api__downloader_has_active_tasksPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_has_active_tasks',
|
||||
);
|
||||
late final _wire__crate__api__downloader_api__downloader_has_active_tasks =
|
||||
_wire__crate__api__downloader_api__downloader_has_active_tasksPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
WireSyncRust2DartDco wire__crate__api__downloader_api__downloader_init(
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> working_dir,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> default_download_dir,
|
||||
ffi.Pointer<ffi.Uint32> upload_limit_bps,
|
||||
ffi.Pointer<ffi.Uint32> download_limit_bps,
|
||||
) {
|
||||
return _wire__crate__api__downloader_api__downloader_init(
|
||||
working_dir,
|
||||
default_download_dir,
|
||||
upload_limit_bps,
|
||||
download_limit_bps,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__downloader_api__downloader_initPtr =
|
||||
@ -1348,6 +1402,9 @@ class RustLibWire implements BaseWire {
|
||||
ffi.NativeFunction<
|
||||
WireSyncRust2DartDco Function(
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<ffi.Uint32>,
|
||||
ffi.Pointer<ffi.Uint32>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
@ -1358,6 +1415,9 @@ class RustLibWire implements BaseWire {
|
||||
.asFunction<
|
||||
WireSyncRust2DartDco Function(
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<ffi.Uint32>,
|
||||
ffi.Pointer<ffi.Uint32>,
|
||||
)
|
||||
>();
|
||||
|
||||
@ -1450,6 +1510,22 @@ class RustLibWire implements BaseWire {
|
||||
_wire__crate__api__downloader_api__downloader_removePtr
|
||||
.asFunction<void Function(int, int, bool)>();
|
||||
|
||||
void wire__crate__api__downloader_api__downloader_remove_completed_tasks(
|
||||
int port_,
|
||||
) {
|
||||
return _wire__crate__api__downloader_api__downloader_remove_completed_tasks(
|
||||
port_,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__downloader_api__downloader_remove_completed_tasksPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_remove_completed_tasks',
|
||||
);
|
||||
late final _wire__crate__api__downloader_api__downloader_remove_completed_tasks =
|
||||
_wire__crate__api__downloader_api__downloader_remove_completed_tasksPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__downloader_api__downloader_resume(
|
||||
int port_,
|
||||
int task_id,
|
||||
@ -1477,6 +1553,18 @@ class RustLibWire implements BaseWire {
|
||||
_wire__crate__api__downloader_api__downloader_resume_allPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__downloader_api__downloader_shutdown(int port_) {
|
||||
return _wire__crate__api__downloader_api__downloader_shutdown(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__downloader_api__downloader_shutdownPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_shutdown',
|
||||
);
|
||||
late final _wire__crate__api__downloader_api__downloader_shutdown =
|
||||
_wire__crate__api__downloader_api__downloader_shutdownPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__downloader_api__downloader_stop(int port_) {
|
||||
return _wire__crate__api__downloader_api__downloader_stop(port_);
|
||||
}
|
||||
@ -1489,6 +1577,36 @@ class RustLibWire implements BaseWire {
|
||||
_wire__crate__api__downloader_api__downloader_stopPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__downloader_api__downloader_update_speed_limits(
|
||||
int port_,
|
||||
ffi.Pointer<ffi.Uint32> _upload_limit_bps,
|
||||
ffi.Pointer<ffi.Uint32> _download_limit_bps,
|
||||
) {
|
||||
return _wire__crate__api__downloader_api__downloader_update_speed_limits(
|
||||
port_,
|
||||
_upload_limit_bps,
|
||||
_download_limit_bps,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__downloader_api__downloader_update_speed_limitsPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<ffi.Uint32>,
|
||||
ffi.Pointer<ffi.Uint32>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_update_speed_limits',
|
||||
);
|
||||
late final _wire__crate__api__downloader_api__downloader_update_speed_limits =
|
||||
_wire__crate__api__downloader_api__downloader_update_speed_limitsPtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<ffi.Uint32>, ffi.Pointer<ffi.Uint32>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__http_api__fetch(
|
||||
int port_,
|
||||
int method,
|
||||
@ -2755,6 +2873,17 @@ class RustLibWire implements BaseWire {
|
||||
ffi.Pointer<wire_cst_rsi_launcher_asar_data> Function()
|
||||
>();
|
||||
|
||||
ffi.Pointer<ffi.Uint32> cst_new_box_autoadd_u_32(int value) {
|
||||
return _cst_new_box_autoadd_u_32(value);
|
||||
}
|
||||
|
||||
late final _cst_new_box_autoadd_u_32Ptr =
|
||||
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Uint32> Function(ffi.Uint32)>>(
|
||||
'frbgen_starcitizen_doctor_cst_new_box_autoadd_u_32',
|
||||
);
|
||||
late final _cst_new_box_autoadd_u_32 = _cst_new_box_autoadd_u_32Ptr
|
||||
.asFunction<ffi.Pointer<ffi.Uint32> Function(int)>();
|
||||
|
||||
ffi.Pointer<ffi.Uint64> cst_new_box_autoadd_u_64(int value) {
|
||||
return _cst_new_box_autoadd_u_64(value);
|
||||
}
|
||||
|
||||
@ -614,6 +614,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloader_action_pause_download": MessageLookupByLibrary.simpleMessage(
|
||||
"Pause Download",
|
||||
),
|
||||
"downloader_action_restart_later": MessageLookupByLibrary.simpleMessage(
|
||||
"Apply Later",
|
||||
),
|
||||
"downloader_action_restart_now": MessageLookupByLibrary.simpleMessage(
|
||||
"Restart Now",
|
||||
),
|
||||
"downloader_action_resume_all": MessageLookupByLibrary.simpleMessage(
|
||||
"Resume All",
|
||||
),
|
||||
@ -645,6 +651,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"SCToolbox uses p2p network to accelerate file downloads. If you have limited bandwidth, you can set the upload bandwidth to 1(byte) here.",
|
||||
),
|
||||
"downloader_info_paused": MessageLookupByLibrary.simpleMessage("Paused"),
|
||||
"downloader_info_restart_manager_to_apply":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Speed limit settings saved. Restart the download manager now to apply new settings?",
|
||||
),
|
||||
"downloader_info_speed_limit_saved_restart_required":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Speed limit settings saved. Will apply on next downloader start.",
|
||||
),
|
||||
"downloader_info_status": m22,
|
||||
"downloader_info_total_size": m23,
|
||||
"downloader_info_uploaded": m24,
|
||||
|
||||
@ -551,6 +551,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloader_action_pause_download": MessageLookupByLibrary.simpleMessage(
|
||||
"ダウンロードを一時停止",
|
||||
),
|
||||
"downloader_action_restart_later": MessageLookupByLibrary.simpleMessage(
|
||||
"後で適用",
|
||||
),
|
||||
"downloader_action_restart_now": MessageLookupByLibrary.simpleMessage(
|
||||
"今すぐ再起動",
|
||||
),
|
||||
"downloader_action_resume_all": MessageLookupByLibrary.simpleMessage(
|
||||
"すべて再開",
|
||||
),
|
||||
@ -582,6 +588,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"SCToolboxはファイルダウンロードを高速化するためにP2Pネットワークを使用しています。通信量に制限がある場合は、アップロード帯域幅を1(byte)に設定できます。",
|
||||
),
|
||||
"downloader_info_paused": MessageLookupByLibrary.simpleMessage("一時停止中"),
|
||||
"downloader_info_restart_manager_to_apply":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"速度制限設定が保存されました。新しい設定を適用するためにダウンロードマネージャーを今すぐ再起動しますか?",
|
||||
),
|
||||
"downloader_info_speed_limit_saved_restart_required":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"速度制限設定が保存されました。次回のダウンローダー起動時に適用されます。",
|
||||
),
|
||||
"downloader_info_status": m22,
|
||||
"downloader_info_total_size": m23,
|
||||
"downloader_info_uploaded": m24,
|
||||
|
||||
@ -591,6 +591,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloader_action_pause_download": MessageLookupByLibrary.simpleMessage(
|
||||
"Приостановить загрузку",
|
||||
),
|
||||
"downloader_action_restart_later": MessageLookupByLibrary.simpleMessage(
|
||||
"Применить позже",
|
||||
),
|
||||
"downloader_action_restart_now": MessageLookupByLibrary.simpleMessage(
|
||||
"Перезапустить сейчас",
|
||||
),
|
||||
"downloader_action_resume_all": MessageLookupByLibrary.simpleMessage(
|
||||
"Возобновить все",
|
||||
),
|
||||
@ -624,6 +630,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloader_info_paused": MessageLookupByLibrary.simpleMessage(
|
||||
"Приостановлено",
|
||||
),
|
||||
"downloader_info_restart_manager_to_apply":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Настройки ограничения скорости сохранены. Перезапустить менеджер загрузок сейчас для применения новых настроек?",
|
||||
),
|
||||
"downloader_info_speed_limit_saved_restart_required":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Настройки ограничения скорости сохранены. Будут применены при следующем запуске загрузчика.",
|
||||
),
|
||||
"downloader_info_status": m22,
|
||||
"downloader_info_total_size": m23,
|
||||
"downloader_info_uploaded": m24,
|
||||
|
||||
@ -538,6 +538,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloader_action_pause_download": MessageLookupByLibrary.simpleMessage(
|
||||
"暂停下载",
|
||||
),
|
||||
"downloader_action_restart_later": MessageLookupByLibrary.simpleMessage(
|
||||
"下次启动时生效",
|
||||
),
|
||||
"downloader_action_restart_now": MessageLookupByLibrary.simpleMessage(
|
||||
"立即重启下载管理器",
|
||||
),
|
||||
"downloader_action_resume_all": MessageLookupByLibrary.simpleMessage(
|
||||
"恢复全部",
|
||||
),
|
||||
@ -565,6 +571,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"SC 汉化盒子使用 p2p 网络来加速文件下载,如果您流量有限,可在此处将上传带宽设置为 1(byte)。",
|
||||
),
|
||||
"downloader_info_paused": MessageLookupByLibrary.simpleMessage("已暂停"),
|
||||
"downloader_info_restart_manager_to_apply":
|
||||
MessageLookupByLibrary.simpleMessage("限速设置已保存。是否立即重启下载管理器以应用新设置?"),
|
||||
"downloader_info_speed_limit_saved_restart_required":
|
||||
MessageLookupByLibrary.simpleMessage("限速设置已保存,将在下次启动下载器时生效。"),
|
||||
"downloader_info_status": m22,
|
||||
"downloader_info_total_size": m23,
|
||||
"downloader_info_uploaded": m24,
|
||||
|
||||
@ -522,6 +522,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloader_action_pause_download": MessageLookupByLibrary.simpleMessage(
|
||||
"暫停下載",
|
||||
),
|
||||
"downloader_action_restart_later": MessageLookupByLibrary.simpleMessage(
|
||||
"稍後套用",
|
||||
),
|
||||
"downloader_action_restart_now": MessageLookupByLibrary.simpleMessage(
|
||||
"立即重新啟動",
|
||||
),
|
||||
"downloader_action_resume_all": MessageLookupByLibrary.simpleMessage(
|
||||
"全部繼續",
|
||||
),
|
||||
@ -549,6 +555,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"SC 工具箱使用 p2p 網路來加速文件下載,如果您流量有限,可在此處將上傳頻寬設定為 1(byte)。",
|
||||
),
|
||||
"downloader_info_paused": MessageLookupByLibrary.simpleMessage("已暫停"),
|
||||
"downloader_info_restart_manager_to_apply":
|
||||
MessageLookupByLibrary.simpleMessage("限速設定已儲存。是否立即重新啟動下載管理器以套用新設定?"),
|
||||
"downloader_info_speed_limit_saved_restart_required":
|
||||
MessageLookupByLibrary.simpleMessage("限速設定已儲存,將在下次啟動下載器時生效。"),
|
||||
"downloader_info_status": m22,
|
||||
"downloader_info_total_size": m23,
|
||||
"downloader_info_uploaded": m24,
|
||||
|
||||
@ -28,10 +28,9 @@ class S {
|
||||
static const AppLocalizationDelegate delegate = AppLocalizationDelegate();
|
||||
|
||||
static Future<S> load(Locale locale) {
|
||||
final name =
|
||||
(locale.countryCode?.isEmpty ?? false)
|
||||
? locale.languageCode
|
||||
: locale.toString();
|
||||
final name = (locale.countryCode?.isEmpty ?? false)
|
||||
? locale.languageCode
|
||||
: locale.toString();
|
||||
final localeName = Intl.canonicalizedLocale(name);
|
||||
return initializeMessages(localeName).then((_) {
|
||||
Intl.defaultLocale = localeName;
|
||||
@ -715,6 +714,46 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Speed limit settings saved. Will apply on next downloader start.`
|
||||
String get downloader_info_speed_limit_saved_restart_required {
|
||||
return Intl.message(
|
||||
'Speed limit settings saved. Will apply on next downloader start.',
|
||||
name: 'downloader_info_speed_limit_saved_restart_required',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Restart Now`
|
||||
String get downloader_action_restart_now {
|
||||
return Intl.message(
|
||||
'Restart Now',
|
||||
name: 'downloader_action_restart_now',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Apply Later`
|
||||
String get downloader_action_restart_later {
|
||||
return Intl.message(
|
||||
'Apply Later',
|
||||
name: 'downloader_action_restart_later',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Speed limit settings saved. Restart the download manager now to apply new settings?`
|
||||
String get downloader_info_restart_manager_to_apply {
|
||||
return Intl.message(
|
||||
'Speed limit settings saved. Restart the download manager now to apply new settings?',
|
||||
name: 'downloader_info_restart_manager_to_apply',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `One-Click Diagnosis -> {v0}`
|
||||
String doctor_title_one_click_diagnosis(Object v0) {
|
||||
return Intl.message(
|
||||
|
||||
@ -135,6 +135,14 @@
|
||||
"@downloader_input_download_speed_limit": {},
|
||||
"downloader_input_info_p2p_upload_note": "* P2P upload only occurs when downloading files and will close p2p connections after download completion. If you want to participate in seeding, please contact us through the About page.",
|
||||
"@downloader_input_info_p2p_upload_note": {},
|
||||
"downloader_info_speed_limit_saved_restart_required": "Speed limit settings saved. Will apply on next downloader start.",
|
||||
"@downloader_info_speed_limit_saved_restart_required": {},
|
||||
"downloader_action_restart_now": "Restart Now",
|
||||
"@downloader_action_restart_now": {},
|
||||
"downloader_action_restart_later": "Apply Later",
|
||||
"@downloader_action_restart_later": {},
|
||||
"downloader_info_restart_manager_to_apply": "Speed limit settings saved. Restart the download manager now to apply new settings?",
|
||||
"@downloader_info_restart_manager_to_apply": {},
|
||||
"doctor_title_one_click_diagnosis": "One-Click Diagnosis -> {v0}",
|
||||
"@doctor_title_one_click_diagnosis": {},
|
||||
"doctor_action_rsi_launcher_log": "RSI Launcher log",
|
||||
|
||||
@ -135,6 +135,14 @@
|
||||
"@downloader_input_download_speed_limit": {},
|
||||
"downloader_input_info_p2p_upload_note": "* P2Pアップロードはファイルのダウンロード中にのみ行われ、ダウンロードが完了するとP2P接続は閉じられます。シードに参加したい場合は、「アバウト」ページから私たちにご連絡ください。",
|
||||
"@downloader_input_info_p2p_upload_note": {},
|
||||
"downloader_info_speed_limit_saved_restart_required": "速度制限設定が保存されました。次回のダウンローダー起動時に適用されます。",
|
||||
"@downloader_info_speed_limit_saved_restart_required": {},
|
||||
"downloader_action_restart_now": "今すぐ再起動",
|
||||
"@downloader_action_restart_now": {},
|
||||
"downloader_action_restart_later": "後で適用",
|
||||
"@downloader_action_restart_later": {},
|
||||
"downloader_info_restart_manager_to_apply": "速度制限設定が保存されました。新しい設定を適用するためにダウンロードマネージャーを今すぐ再起動しますか?",
|
||||
"@downloader_info_restart_manager_to_apply": {},
|
||||
"doctor_title_one_click_diagnosis": "ワンクリック診断 -> {v0}",
|
||||
"@doctor_title_one_click_diagnosis": {},
|
||||
"doctor_action_rsi_launcher_log": "RSIランチャーログ",
|
||||
|
||||
@ -135,6 +135,14 @@
|
||||
"@downloader_input_download_speed_limit": {},
|
||||
"downloader_input_info_p2p_upload_note": "* P2P отдача происходит только во время загрузки файла и отключается после завершения. Если вы хотите участвовать в раздаче, пожалуйста, свяжитесь с нами через страницу 'О программе'.",
|
||||
"@downloader_input_info_p2p_upload_note": {},
|
||||
"downloader_info_speed_limit_saved_restart_required": "Настройки ограничения скорости сохранены. Будут применены при следующем запуске загрузчика.",
|
||||
"@downloader_info_speed_limit_saved_restart_required": {},
|
||||
"downloader_action_restart_now": "Перезапустить сейчас",
|
||||
"@downloader_action_restart_now": {},
|
||||
"downloader_action_restart_later": "Применить позже",
|
||||
"@downloader_action_restart_later": {},
|
||||
"downloader_info_restart_manager_to_apply": "Настройки ограничения скорости сохранены. Перезапустить менеджер загрузок сейчас для применения новых настроек?",
|
||||
"@downloader_info_restart_manager_to_apply": {},
|
||||
"doctor_title_one_click_diagnosis": "Быстрая диагностика -> {v0}",
|
||||
"@doctor_title_one_click_diagnosis": {},
|
||||
"doctor_action_rsi_launcher_log": "Лог RSI Launcher",
|
||||
|
||||
@ -134,6 +134,14 @@
|
||||
"@downloader_input_download_speed_limit": {},
|
||||
"downloader_input_info_p2p_upload_note": "* P2P 上传仅在下载文件时进行,下载完成后会关闭 p2p 连接。如您想参与做种,请通过关于页面联系我们。",
|
||||
"@downloader_input_info_p2p_upload_note": {},
|
||||
"downloader_info_speed_limit_saved_restart_required": "限速设置已保存,将在下次启动下载器时生效。",
|
||||
"@downloader_info_speed_limit_saved_restart_required": {},
|
||||
"downloader_action_restart_now": "立即重启下载管理器",
|
||||
"@downloader_action_restart_now": {},
|
||||
"downloader_action_restart_later": "下次启动时生效",
|
||||
"@downloader_action_restart_later": {},
|
||||
"downloader_info_restart_manager_to_apply": "限速设置已保存。是否立即重启下载管理器以应用新设置?",
|
||||
"@downloader_info_restart_manager_to_apply": {},
|
||||
"doctor_title_one_click_diagnosis": "一键诊断 -> {v0}",
|
||||
"@doctor_title_one_click_diagnosis": {},
|
||||
"doctor_action_rsi_launcher_log": "RSI启动器log",
|
||||
|
||||
@ -135,6 +135,14 @@
|
||||
"@downloader_input_download_speed_limit": {},
|
||||
"downloader_input_info_p2p_upload_note": "* P2P 上傳僅在下載文件時進行,下載完成後會關閉 p2p 連接。如您想參與製作種子文件,請透過關於頁面聯絡我們。",
|
||||
"@downloader_input_info_p2p_upload_note": {},
|
||||
"downloader_info_speed_limit_saved_restart_required": "限速設定已儲存,將在下次啟動下載器時生效。",
|
||||
"@downloader_info_speed_limit_saved_restart_required": {},
|
||||
"downloader_action_restart_now": "立即重新啟動",
|
||||
"@downloader_action_restart_now": {},
|
||||
"downloader_action_restart_later": "稍後套用",
|
||||
"@downloader_action_restart_later": {},
|
||||
"downloader_info_restart_manager_to_apply": "限速設定已儲存。是否立即重新啟動下載管理器以套用新設定?",
|
||||
"@downloader_info_restart_manager_to_apply": {},
|
||||
"doctor_title_one_click_diagnosis": "疑難排解 -> {v0}",
|
||||
"@doctor_title_one_click_diagnosis": {},
|
||||
"doctor_action_rsi_launcher_log": "RSI啟動器log",
|
||||
|
||||
@ -13,6 +13,7 @@ part 'download_manager.freezed.dart';
|
||||
@freezed
|
||||
abstract class DownloadManagerState with _$DownloadManagerState {
|
||||
const factory DownloadManagerState({
|
||||
required String workingDir,
|
||||
required String downloadDir,
|
||||
@Default(false) bool isInitialized,
|
||||
downloader_api.DownloadGlobalStat? globalStat,
|
||||
@ -36,18 +37,24 @@ class DownloadManager extends _$DownloadManager {
|
||||
if (appGlobalState.applicationBinaryModuleDir == null) {
|
||||
throw Exception("applicationBinaryModuleDir is null");
|
||||
}
|
||||
if (appGlobalState.applicationSupportDir == null) {
|
||||
throw Exception("applicationSupportDir is null");
|
||||
}
|
||||
ref.onDispose(() {
|
||||
_disposed = true;
|
||||
});
|
||||
ref.keepAlive();
|
||||
|
||||
// Working directory for session data (in appSupport)
|
||||
final workingDir = "${appGlobalState.applicationSupportDir}${Platform.pathSeparator}downloader";
|
||||
// Default download directory (can be customized)
|
||||
final downloadDir = "${appGlobalState.applicationBinaryModuleDir}${Platform.pathSeparator}downloads";
|
||||
|
||||
// Lazy load init
|
||||
() async {
|
||||
try {
|
||||
// Check if there are existing tasks
|
||||
final dir = Directory(downloadDir);
|
||||
// Check if there are existing tasks (check working dir for session data)
|
||||
final dir = Directory(workingDir);
|
||||
if (await dir.exists()) {
|
||||
dPrint("Launch download manager");
|
||||
await initDownloader();
|
||||
@ -59,21 +66,32 @@ class DownloadManager extends _$DownloadManager {
|
||||
}
|
||||
}();
|
||||
|
||||
return DownloadManagerState(downloadDir: downloadDir);
|
||||
return DownloadManagerState(workingDir: workingDir, downloadDir: downloadDir);
|
||||
}
|
||||
|
||||
Future<void> initDownloader() async {
|
||||
Future<void> initDownloader({int? uploadLimitBps, int? downloadLimitBps}) async {
|
||||
if (state.isInitialized) return;
|
||||
|
||||
try {
|
||||
// Create download directory if it doesn't exist
|
||||
final dir = Directory(state.downloadDir);
|
||||
if (!await dir.exists()) {
|
||||
await dir.create(recursive: true);
|
||||
// Create working directory if it doesn't exist
|
||||
final workingDir = Directory(state.workingDir);
|
||||
if (!await workingDir.exists()) {
|
||||
await workingDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// Initialize the Rust downloader
|
||||
downloader_api.downloaderInit(downloadDir: state.downloadDir);
|
||||
// Create download directory if it doesn't exist
|
||||
final downloadDir = Directory(state.downloadDir);
|
||||
if (!await downloadDir.exists()) {
|
||||
await downloadDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// Initialize the Rust downloader with optional speed limits
|
||||
downloader_api.downloaderInit(
|
||||
workingDir: state.workingDir,
|
||||
defaultDownloadDir: state.downloadDir,
|
||||
uploadLimitBps: uploadLimitBps,
|
||||
downloadLimitBps: downloadLimitBps,
|
||||
);
|
||||
|
||||
state = state.copyWith(isInitialized: true);
|
||||
|
||||
@ -97,6 +115,9 @@ class DownloadManager extends _$DownloadManager {
|
||||
try {
|
||||
final globalStat = await downloader_api.downloaderGetGlobalStats();
|
||||
state = state.copyWith(globalStat: globalStat);
|
||||
|
||||
// Auto-remove completed tasks (no seeding behavior)
|
||||
await removeCompletedTasks();
|
||||
} catch (e) {
|
||||
dPrint("globalStat update error:$e");
|
||||
}
|
||||
@ -177,6 +198,18 @@ class DownloadManager extends _$DownloadManager {
|
||||
state = state.copyWith(isInitialized: false, globalStat: null);
|
||||
}
|
||||
|
||||
/// Shutdown the downloader completely (allows restart with new settings)
|
||||
Future<void> shutdown() async {
|
||||
await downloader_api.downloaderShutdown();
|
||||
state = state.copyWith(isInitialized: false, globalStat: null);
|
||||
}
|
||||
|
||||
/// Restart the downloader with new speed limit settings
|
||||
Future<void> restart({int? uploadLimitBps, int? downloadLimitBps}) async {
|
||||
await shutdown();
|
||||
await initDownloader(uploadLimitBps: uploadLimitBps, downloadLimitBps: downloadLimitBps);
|
||||
}
|
||||
|
||||
/// Convert speed limit text to bytes per second
|
||||
/// Supports formats like: "1", "100k", "10m", "0"
|
||||
int textToByte(String text) {
|
||||
@ -195,4 +228,22 @@ class DownloadManager extends _$DownloadManager {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Remove all completed tasks (equivalent to aria2's --seed-time=0 behavior)
|
||||
/// Returns the number of tasks removed
|
||||
Future<int> removeCompletedTasks() async {
|
||||
if (!state.isInitialized) {
|
||||
return 0;
|
||||
}
|
||||
final removed = await downloader_api.downloaderRemoveCompletedTasks();
|
||||
return removed;
|
||||
}
|
||||
|
||||
/// Check if there are any active (non-completed) download tasks
|
||||
Future<bool> hasActiveTasks() async {
|
||||
if (!state.isInitialized) {
|
||||
return false;
|
||||
}
|
||||
return await downloader_api.downloaderHasActiveTasks();
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$DownloadManagerState {
|
||||
|
||||
String get downloadDir; bool get isInitialized; downloader_api.DownloadGlobalStat? get globalStat;
|
||||
String get workingDir; String get downloadDir; bool get isInitialized; downloader_api.DownloadGlobalStat? get globalStat;
|
||||
/// Create a copy of DownloadManagerState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@ -25,16 +25,16 @@ $DownloadManagerStateCopyWith<DownloadManagerState> get copyWith => _$DownloadMa
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is DownloadManagerState&&(identical(other.downloadDir, downloadDir) || other.downloadDir == downloadDir)&&(identical(other.isInitialized, isInitialized) || other.isInitialized == isInitialized)&&(identical(other.globalStat, globalStat) || other.globalStat == globalStat));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is DownloadManagerState&&(identical(other.workingDir, workingDir) || other.workingDir == workingDir)&&(identical(other.downloadDir, downloadDir) || other.downloadDir == downloadDir)&&(identical(other.isInitialized, isInitialized) || other.isInitialized == isInitialized)&&(identical(other.globalStat, globalStat) || other.globalStat == globalStat));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,downloadDir,isInitialized,globalStat);
|
||||
int get hashCode => Object.hash(runtimeType,workingDir,downloadDir,isInitialized,globalStat);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DownloadManagerState(downloadDir: $downloadDir, isInitialized: $isInitialized, globalStat: $globalStat)';
|
||||
return 'DownloadManagerState(workingDir: $workingDir, downloadDir: $downloadDir, isInitialized: $isInitialized, globalStat: $globalStat)';
|
||||
}
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ abstract mixin class $DownloadManagerStateCopyWith<$Res> {
|
||||
factory $DownloadManagerStateCopyWith(DownloadManagerState value, $Res Function(DownloadManagerState) _then) = _$DownloadManagerStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat
|
||||
String workingDir, String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat
|
||||
});
|
||||
|
||||
|
||||
@ -62,9 +62,10 @@ class _$DownloadManagerStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of DownloadManagerState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? downloadDir = null,Object? isInitialized = null,Object? globalStat = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? workingDir = null,Object? downloadDir = null,Object? isInitialized = null,Object? globalStat = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
downloadDir: null == downloadDir ? _self.downloadDir : downloadDir // ignore: cast_nullable_to_non_nullable
|
||||
workingDir: null == workingDir ? _self.workingDir : workingDir // ignore: cast_nullable_to_non_nullable
|
||||
as String,downloadDir: null == downloadDir ? _self.downloadDir : downloadDir // ignore: cast_nullable_to_non_nullable
|
||||
as String,isInitialized: null == isInitialized ? _self.isInitialized : isInitialized // ignore: cast_nullable_to_non_nullable
|
||||
as bool,globalStat: freezed == globalStat ? _self.globalStat : globalStat // ignore: cast_nullable_to_non_nullable
|
||||
as downloader_api.DownloadGlobalStat?,
|
||||
@ -152,10 +153,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String workingDir, String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _DownloadManagerState() when $default != null:
|
||||
return $default(_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
return $default(_that.workingDir,_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@ -173,10 +174,10 @@ return $default(_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String workingDir, String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _DownloadManagerState():
|
||||
return $default(_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
return $default(_that.workingDir,_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@ -193,10 +194,10 @@ return $default(_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String workingDir, String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _DownloadManagerState() when $default != null:
|
||||
return $default(_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
return $default(_that.workingDir,_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@ -208,9 +209,10 @@ return $default(_that.downloadDir,_that.isInitialized,_that.globalStat);case _:
|
||||
|
||||
|
||||
class _DownloadManagerState implements DownloadManagerState {
|
||||
const _DownloadManagerState({required this.downloadDir, this.isInitialized = false, this.globalStat});
|
||||
const _DownloadManagerState({required this.workingDir, required this.downloadDir, this.isInitialized = false, this.globalStat});
|
||||
|
||||
|
||||
@override final String workingDir;
|
||||
@override final String downloadDir;
|
||||
@override@JsonKey() final bool isInitialized;
|
||||
@override final downloader_api.DownloadGlobalStat? globalStat;
|
||||
@ -225,16 +227,16 @@ _$DownloadManagerStateCopyWith<_DownloadManagerState> get copyWith => __$Downloa
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DownloadManagerState&&(identical(other.downloadDir, downloadDir) || other.downloadDir == downloadDir)&&(identical(other.isInitialized, isInitialized) || other.isInitialized == isInitialized)&&(identical(other.globalStat, globalStat) || other.globalStat == globalStat));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DownloadManagerState&&(identical(other.workingDir, workingDir) || other.workingDir == workingDir)&&(identical(other.downloadDir, downloadDir) || other.downloadDir == downloadDir)&&(identical(other.isInitialized, isInitialized) || other.isInitialized == isInitialized)&&(identical(other.globalStat, globalStat) || other.globalStat == globalStat));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,downloadDir,isInitialized,globalStat);
|
||||
int get hashCode => Object.hash(runtimeType,workingDir,downloadDir,isInitialized,globalStat);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DownloadManagerState(downloadDir: $downloadDir, isInitialized: $isInitialized, globalStat: $globalStat)';
|
||||
return 'DownloadManagerState(workingDir: $workingDir, downloadDir: $downloadDir, isInitialized: $isInitialized, globalStat: $globalStat)';
|
||||
}
|
||||
|
||||
|
||||
@ -245,7 +247,7 @@ abstract mixin class _$DownloadManagerStateCopyWith<$Res> implements $DownloadMa
|
||||
factory _$DownloadManagerStateCopyWith(_DownloadManagerState value, $Res Function(_DownloadManagerState) _then) = __$DownloadManagerStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat
|
||||
String workingDir, String downloadDir, bool isInitialized, downloader_api.DownloadGlobalStat? globalStat
|
||||
});
|
||||
|
||||
|
||||
@ -262,9 +264,10 @@ class __$DownloadManagerStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of DownloadManagerState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? downloadDir = null,Object? isInitialized = null,Object? globalStat = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? workingDir = null,Object? downloadDir = null,Object? isInitialized = null,Object? globalStat = freezed,}) {
|
||||
return _then(_DownloadManagerState(
|
||||
downloadDir: null == downloadDir ? _self.downloadDir : downloadDir // ignore: cast_nullable_to_non_nullable
|
||||
workingDir: null == workingDir ? _self.workingDir : workingDir // ignore: cast_nullable_to_non_nullable
|
||||
as String,downloadDir: null == downloadDir ? _self.downloadDir : downloadDir // ignore: cast_nullable_to_non_nullable
|
||||
as String,isInitialized: null == isInitialized ? _self.isInitialized : isInitialized // ignore: cast_nullable_to_non_nullable
|
||||
as bool,globalStat: freezed == globalStat ? _self.globalStat : globalStat // ignore: cast_nullable_to_non_nullable
|
||||
as downloader_api.DownloadGlobalStat?,
|
||||
|
||||
@ -41,7 +41,7 @@ final class DownloadManagerProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$downloadManagerHash() => r'adc9a147522afbfcfc8a2e16310649220a75d6a3';
|
||||
String _$downloadManagerHash() => r'f0fd818851be0d1c9e6774803aae465c33843cde';
|
||||
|
||||
abstract class _$DownloadManager extends $Notifier<DownloadManagerState> {
|
||||
DownloadManagerState build();
|
||||
|
||||
@ -267,14 +267,51 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
),
|
||||
);
|
||||
if (ok == true) {
|
||||
// Note: rqbit doesn't support dynamic speed limit changes yet
|
||||
// Just save the settings for now
|
||||
// Save the settings
|
||||
await box.put('downloader_up_limit', upCtrl.text.trim());
|
||||
await box.put('downloader_down_limit', downCtrl.text.trim());
|
||||
|
||||
// Show info that speed limits will apply on next restart
|
||||
// Ask user if they want to restart the download manager now
|
||||
if (context.mounted) {
|
||||
showToast(context, "Speed limit settings saved. Will apply on next download.");
|
||||
final restartNow = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => ContentDialog(
|
||||
title: Text(S.current.downloader_speed_limit_settings),
|
||||
content: Text(S.current.downloader_info_restart_manager_to_apply),
|
||||
actions: [
|
||||
Button(
|
||||
child: Text(S.current.downloader_action_restart_later),
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
),
|
||||
FilledButton(
|
||||
child: Text(S.current.downloader_action_restart_now),
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (restartNow == true) {
|
||||
// Get the download manager and restart it with new settings
|
||||
final downloadManager = ref.read(downloadManagerProvider.notifier);
|
||||
final upLimit = downloadManager.textToByte(upCtrl.text.trim());
|
||||
final downLimit = downloadManager.textToByte(downCtrl.text.trim());
|
||||
|
||||
try {
|
||||
await downloadManager.restart(
|
||||
uploadLimitBps: upLimit > 0 ? upLimit : null,
|
||||
downloadLimitBps: downLimit > 0 ? downLimit : null,
|
||||
);
|
||||
if (context.mounted) {
|
||||
showToast(context, S.current.downloader_info_speed_limit_saved_restart_required);
|
||||
}
|
||||
} catch (e) {
|
||||
dPrint("Failed to restart download manager: $e");
|
||||
if (context.mounted) {
|
||||
showToast(context, "Failed to restart: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ final class HomeDownloaderUIModelProvider
|
||||
}
|
||||
|
||||
String _$homeDownloaderUIModelHash() =>
|
||||
r'27e2e4b7a5103eee9d489a347410131edef46be4';
|
||||
r'3dd2ca0b1c03113d577c322de81078faa378230b';
|
||||
|
||||
abstract class _$HomeDownloaderUIModel
|
||||
extends $Notifier<HomeDownloaderUIState> {
|
||||
|
||||
22
rust/Cargo.lock
generated
22
rust/Cargo.lock
generated
@ -2994,7 +2994,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit"
|
||||
version = "9.0.0-beta.1"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@ -3058,7 +3058,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-bencode"
|
||||
version = "3.1.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arrayvec",
|
||||
@ -3074,7 +3074,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-buffers"
|
||||
version = "4.2.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"librqbit-clone-to-owned",
|
||||
@ -3085,7 +3085,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-clone-to-owned"
|
||||
version = "3.0.1"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
]
|
||||
@ -3093,7 +3093,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-core"
|
||||
version = "5.0.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@ -3122,7 +3122,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-dht"
|
||||
version = "5.3.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"backon",
|
||||
@ -3169,7 +3169,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-lsd"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"atoi",
|
||||
@ -3189,7 +3189,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-peer-protocol"
|
||||
version = "4.3.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitvec",
|
||||
@ -3209,7 +3209,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-sha1-wrapper"
|
||||
version = "4.1.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"assert_cfg",
|
||||
"aws-lc-rs",
|
||||
@ -3218,7 +3218,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-tracker-comms"
|
||||
version = "3.0.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@ -3246,7 +3246,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "librqbit-upnp"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.1#e5ac0ac75cceffe017e247ea265dc7402c226638"
|
||||
source = "git+https://github.com/StarCitizenToolBox/rqbit?tag=webseed-v0.0.2#7a9b4d7db84b7b9cccc424e294610cc800a9baa4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bstr",
|
||||
|
||||
@ -35,7 +35,7 @@ unp4k_rs = { git = "https://github.com/StarCitizenToolBox/unp4k_rs", tag = "V0.0
|
||||
uuid = { version = "1.19.0", features = ["v4"] }
|
||||
parking_lot = "0.12.5"
|
||||
crossbeam-channel = "0.5.15"
|
||||
librqbit = { git = "https://github.com/StarCitizenToolBox/rqbit", tag = "webseed-v0.0.1" }
|
||||
librqbit = { git = "https://github.com/StarCitizenToolBox/rqbit", tag = "webseed-v0.0.2" }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
bytes = "1.10"
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::num::NonZeroU32;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -7,9 +8,11 @@ use bytes::Bytes;
|
||||
use flutter_rust_bridge::frb;
|
||||
use librqbit::{
|
||||
AddTorrent, AddTorrentOptions, AddTorrentResponse, Session, SessionOptions,
|
||||
TorrentStats, ManagedTorrent, TorrentStatsState,
|
||||
SessionPersistenceConfig, TorrentStats, ManagedTorrent, TorrentStatsState,
|
||||
api::TorrentIdOrHash,
|
||||
dht::PersistentDhtConfig,
|
||||
limits::LimitsConfig,
|
||||
};
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::RwLock;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::Mutex;
|
||||
@ -17,8 +20,9 @@ use tokio::sync::Mutex;
|
||||
// Type alias for ManagedTorrentHandle
|
||||
type ManagedTorrentHandle = Arc<ManagedTorrent>;
|
||||
|
||||
// Global session instance
|
||||
static SESSION: OnceCell<Arc<Session>> = OnceCell::new();
|
||||
// Global session instance - using RwLock to allow restart
|
||||
static SESSION: once_cell::sync::Lazy<RwLock<Option<Arc<Session>>>> =
|
||||
once_cell::sync::Lazy::new(|| RwLock::new(None));
|
||||
static SESSION_INIT_LOCK: once_cell::sync::Lazy<Mutex<()>> =
|
||||
once_cell::sync::Lazy::new(|| Mutex::new(()));
|
||||
|
||||
@ -31,7 +35,7 @@ static TASK_OUTPUT_FOLDERS: once_cell::sync::Lazy<RwLock<HashMap<usize, String>>
|
||||
once_cell::sync::Lazy::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
/// Download task status
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum DownloadTaskStatus {
|
||||
Initializing,
|
||||
Live,
|
||||
@ -65,11 +69,22 @@ pub struct DownloadGlobalStat {
|
||||
pub num_waiting: usize,
|
||||
}
|
||||
|
||||
/// Initialize the download manager session
|
||||
/// Initialize the download manager session with persistence enabled
|
||||
///
|
||||
/// Parameters:
|
||||
/// - working_dir: The directory to store session data (persistence, DHT, etc.)
|
||||
/// - default_download_dir: The default directory to store downloads
|
||||
/// - upload_limit_bps: Upload speed limit in bytes per second (0 = unlimited)
|
||||
/// - download_limit_bps: Download speed limit in bytes per second (0 = unlimited)
|
||||
#[frb(sync)]
|
||||
pub fn downloader_init(download_dir: String) -> Result<()> {
|
||||
pub fn downloader_init(
|
||||
working_dir: String,
|
||||
default_download_dir: String,
|
||||
upload_limit_bps: Option<u32>,
|
||||
download_limit_bps: Option<u32>,
|
||||
) -> Result<()> {
|
||||
// Already initialized
|
||||
if SESSION.get().is_some() {
|
||||
if SESSION.read().is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -78,28 +93,52 @@ pub fn downloader_init(download_dir: String) -> Result<()> {
|
||||
let _lock = SESSION_INIT_LOCK.lock().await;
|
||||
|
||||
// Double check after acquiring lock
|
||||
if SESSION.get().is_some() {
|
||||
if SESSION.read().is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let output_folder = PathBuf::from(&download_dir);
|
||||
// Working directory for persistence and session data
|
||||
let working_folder = PathBuf::from(&working_dir);
|
||||
std::fs::create_dir_all(&working_folder)?;
|
||||
|
||||
// Default download folder
|
||||
let output_folder = PathBuf::from(&default_download_dir);
|
||||
std::fs::create_dir_all(&output_folder)?;
|
||||
|
||||
// Create persistence folder for session state in working directory
|
||||
let persistence_folder = working_folder.join("rqbit-session");
|
||||
std::fs::create_dir_all(&persistence_folder)?;
|
||||
|
||||
// DHT persistence file in working directory
|
||||
let dht_persistence_file = working_folder.join("dht.json");
|
||||
|
||||
let session = Session::new_with_opts(
|
||||
output_folder,
|
||||
SessionOptions {
|
||||
disable_dht: false,
|
||||
disable_dht_persistence: true,
|
||||
persistence: None,
|
||||
disable_dht_persistence: false,
|
||||
// Configure DHT persistence to use working directory
|
||||
dht_config: Some(PersistentDhtConfig {
|
||||
config_filename: Some(dht_persistence_file),
|
||||
..Default::default()
|
||||
}),
|
||||
// Enable JSON-based session persistence for task recovery
|
||||
persistence: Some(SessionPersistenceConfig::Json {
|
||||
folder: Some(persistence_folder),
|
||||
}),
|
||||
fastresume: false,
|
||||
// Configure rate limits
|
||||
ratelimits: LimitsConfig {
|
||||
upload_bps: upload_limit_bps.and_then(NonZeroU32::new),
|
||||
download_bps: download_limit_bps.and_then(NonZeroU32::new),
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.context("Failed to create rqbit session")?;
|
||||
|
||||
SESSION
|
||||
.set(session)
|
||||
.map_err(|_| anyhow::anyhow!("Session already initialized"))?;
|
||||
*SESSION.write() = Some(session);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
@ -108,7 +147,14 @@ pub fn downloader_init(download_dir: String) -> Result<()> {
|
||||
/// Check if the downloader is initialized
|
||||
#[frb(sync)]
|
||||
pub fn downloader_is_initialized() -> bool {
|
||||
SESSION.get().is_some()
|
||||
SESSION.read().is_some()
|
||||
}
|
||||
|
||||
/// Helper function to get session
|
||||
fn get_session() -> Result<Arc<Session>> {
|
||||
SESSION.read()
|
||||
.clone()
|
||||
.context("Downloader not initialized. Call downloader_init first.")
|
||||
}
|
||||
|
||||
/// Add a torrent from bytes (e.g., .torrent file content)
|
||||
@ -117,9 +163,7 @@ pub async fn downloader_add_torrent(
|
||||
output_folder: Option<String>,
|
||||
trackers: Option<Vec<String>>,
|
||||
) -> Result<usize> {
|
||||
let session = SESSION
|
||||
.get()
|
||||
.context("Downloader not initialized. Call downloader_init first.")?;
|
||||
let session = get_session()?;
|
||||
|
||||
let bytes = Bytes::from(torrent_bytes);
|
||||
let add_torrent = AddTorrent::from_bytes(bytes);
|
||||
@ -171,9 +215,7 @@ pub async fn downloader_add_magnet(
|
||||
output_folder: Option<String>,
|
||||
trackers: Option<Vec<String>>,
|
||||
) -> Result<usize> {
|
||||
let session = SESSION
|
||||
.get()
|
||||
.context("Downloader not initialized. Call downloader_init first.")?;
|
||||
let session = get_session()?;
|
||||
|
||||
// Check if it's a magnet link
|
||||
if !magnet_link.starts_with("magnet:") {
|
||||
@ -260,9 +302,7 @@ pub async fn downloader_add_url(
|
||||
|
||||
/// Pause a download task
|
||||
pub async fn downloader_pause(task_id: usize) -> Result<()> {
|
||||
let session = SESSION
|
||||
.get()
|
||||
.context("Downloader not initialized")?;
|
||||
let session = get_session()?;
|
||||
|
||||
let handle = {
|
||||
let handles = TORRENT_HANDLES.read();
|
||||
@ -279,9 +319,7 @@ pub async fn downloader_pause(task_id: usize) -> Result<()> {
|
||||
|
||||
/// Resume a download task
|
||||
pub async fn downloader_resume(task_id: usize) -> Result<()> {
|
||||
let session = SESSION
|
||||
.get()
|
||||
.context("Downloader not initialized")?;
|
||||
let session = get_session()?;
|
||||
|
||||
let handle = {
|
||||
let handles = TORRENT_HANDLES.read();
|
||||
@ -298,9 +336,7 @@ pub async fn downloader_resume(task_id: usize) -> Result<()> {
|
||||
|
||||
/// Remove a download task
|
||||
pub async fn downloader_remove(task_id: usize, delete_files: bool) -> Result<()> {
|
||||
let session = SESSION
|
||||
.get()
|
||||
.context("Downloader not initialized")?;
|
||||
let session = get_session()?;
|
||||
|
||||
session
|
||||
.delete(librqbit::api::TorrentIdOrHash::Id(task_id), delete_files)
|
||||
@ -382,11 +418,12 @@ fn get_task_status(stats: &TorrentStats) -> DownloadTaskStatus {
|
||||
|
||||
/// Get all tasks
|
||||
pub async fn downloader_get_all_tasks() -> Result<Vec<DownloadTaskInfo>> {
|
||||
let session = SESSION.get();
|
||||
if session.is_none() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
let session = session.unwrap();
|
||||
let session_guard = SESSION.read();
|
||||
let session = match session_guard.as_ref() {
|
||||
Some(s) => s.clone(),
|
||||
None => return Ok(vec![]),
|
||||
};
|
||||
drop(session_guard);
|
||||
|
||||
// Use RwLock to collect tasks since with_torrents takes Fn (not FnMut)
|
||||
let tasks: RwLock<Vec<DownloadTaskInfo>> = RwLock::new(Vec::new());
|
||||
@ -474,9 +511,7 @@ pub async fn downloader_is_name_in_task(name: String) -> bool {
|
||||
|
||||
/// Pause all tasks
|
||||
pub async fn downloader_pause_all() -> Result<()> {
|
||||
let session = SESSION
|
||||
.get()
|
||||
.context("Downloader not initialized")?;
|
||||
let session = get_session()?;
|
||||
|
||||
let handles: Vec<_> = TORRENT_HANDLES.read().values().cloned().collect();
|
||||
|
||||
@ -489,9 +524,7 @@ pub async fn downloader_pause_all() -> Result<()> {
|
||||
|
||||
/// Resume all tasks
|
||||
pub async fn downloader_resume_all() -> Result<()> {
|
||||
let session = SESSION
|
||||
.get()
|
||||
.context("Downloader not initialized")?;
|
||||
let session = get_session()?;
|
||||
|
||||
let handles: Vec<_> = TORRENT_HANDLES.read().values().cloned().collect();
|
||||
|
||||
@ -502,12 +535,80 @@ pub async fn downloader_resume_all() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Stop the downloader session
|
||||
/// Stop the downloader session (pauses all tasks but keeps session)
|
||||
pub async fn downloader_stop() -> Result<()> {
|
||||
if let Some(session) = SESSION.get() {
|
||||
let session = SESSION.read().clone();
|
||||
if let Some(session) = session {
|
||||
session.stop().await;
|
||||
}
|
||||
TORRENT_HANDLES.write().clear();
|
||||
TASK_OUTPUT_FOLDERS.write().clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Shutdown the downloader session completely (allows restart with new settings)
|
||||
pub async fn downloader_shutdown() -> Result<()> {
|
||||
let session_opt = {
|
||||
let mut guard = SESSION.write();
|
||||
guard.take()
|
||||
};
|
||||
|
||||
if let Some(session) = session_opt {
|
||||
session.stop().await;
|
||||
}
|
||||
|
||||
TORRENT_HANDLES.write().clear();
|
||||
TASK_OUTPUT_FOLDERS.write().clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update global speed limits
|
||||
/// Note: rqbit Session doesn't support runtime limit changes,
|
||||
/// this function is a placeholder that returns an error.
|
||||
/// Speed limits should be set during downloader_init.
|
||||
pub async fn downloader_update_speed_limits(
|
||||
_upload_limit_bps: Option<u32>,
|
||||
_download_limit_bps: Option<u32>,
|
||||
) -> Result<()> {
|
||||
// rqbit Session is created with limits but doesn't support runtime updates
|
||||
// To change limits, the session needs to be recreated
|
||||
anyhow::bail!("Runtime speed limit changes not supported. Please restart the downloader.")
|
||||
}
|
||||
|
||||
/// Remove all completed tasks (equivalent to aria2's --seed-time=0 behavior)
|
||||
pub async fn downloader_remove_completed_tasks() -> Result<u32> {
|
||||
let session = get_session()?;
|
||||
|
||||
let tasks = downloader_get_all_tasks().await?;
|
||||
let mut removed_count = 0u32;
|
||||
|
||||
for task in tasks {
|
||||
if task.status == DownloadTaskStatus::Finished {
|
||||
// Check if handle exists (drop lock before await)
|
||||
let has_handle = TORRENT_HANDLES.read().contains_key(&task.id);
|
||||
if has_handle {
|
||||
// Use TorrentIdOrHash::Id for deletion (TorrentId is just usize)
|
||||
if session.delete(TorrentIdOrHash::Id(task.id), false).await.is_ok() {
|
||||
TORRENT_HANDLES.write().remove(&task.id);
|
||||
TASK_OUTPUT_FOLDERS.write().remove(&task.id);
|
||||
removed_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(removed_count)
|
||||
}
|
||||
|
||||
/// Check if there are any active (non-completed) tasks
|
||||
pub async fn downloader_has_active_tasks() -> bool {
|
||||
if let Ok(tasks) = downloader_get_all_tasks().await {
|
||||
for task in tasks {
|
||||
if task.status != DownloadTaskStatus::Finished
|
||||
&& task.status != DownloadTaskStatus::Error {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
|
||||
default_rust_auto_opaque = RustAutoOpaqueNom,
|
||||
);
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1";
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1465039096;
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -641930410;
|
||||
|
||||
// Section: executor
|
||||
|
||||
@ -376,8 +376,35 @@ fn wire__crate__api__downloader_api__downloader_get_task_info_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__downloader_api__downloader_has_active_tasks_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "downloader_has_active_tasks",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| async move {
|
||||
transform_result_dco::<_, _, ()>(
|
||||
(move || async move {
|
||||
let output_ok = Result::<_, ()>::Ok(
|
||||
crate::api::downloader_api::downloader_has_active_tasks().await,
|
||||
)?;
|
||||
Ok(output_ok)
|
||||
})()
|
||||
.await,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__downloader_api__downloader_init_impl(
|
||||
download_dir: impl CstDecode<String>,
|
||||
working_dir: impl CstDecode<String>,
|
||||
default_download_dir: impl CstDecode<String>,
|
||||
upload_limit_bps: impl CstDecode<Option<u32>>,
|
||||
download_limit_bps: impl CstDecode<Option<u32>>,
|
||||
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartDco {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::<flutter_rust_bridge::for_generated::DcoCodec, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
@ -386,10 +413,18 @@ fn wire__crate__api__downloader_api__downloader_init_impl(
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync,
|
||||
},
|
||||
move || {
|
||||
let api_download_dir = download_dir.cst_decode();
|
||||
let api_working_dir = working_dir.cst_decode();
|
||||
let api_default_download_dir = default_download_dir.cst_decode();
|
||||
let api_upload_limit_bps = upload_limit_bps.cst_decode();
|
||||
let api_download_limit_bps = download_limit_bps.cst_decode();
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::downloader_api::downloader_init(api_download_dir)?;
|
||||
let output_ok = crate::api::downloader_api::downloader_init(
|
||||
api_working_dir,
|
||||
api_default_download_dir,
|
||||
api_upload_limit_bps,
|
||||
api_download_limit_bps,
|
||||
)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
@ -516,6 +551,29 @@ fn wire__crate__api__downloader_api__downloader_remove_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__downloader_api__downloader_remove_completed_tasks_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "downloader_remove_completed_tasks",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| async move {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || async move {
|
||||
let output_ok =
|
||||
crate::api::downloader_api::downloader_remove_completed_tasks().await?;
|
||||
Ok(output_ok)
|
||||
})()
|
||||
.await,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__downloader_api__downloader_resume_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
task_id: impl CstDecode<usize>,
|
||||
@ -563,6 +621,28 @@ fn wire__crate__api__downloader_api__downloader_resume_all_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__downloader_api__downloader_shutdown_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "downloader_shutdown",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| async move {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || async move {
|
||||
let output_ok = crate::api::downloader_api::downloader_shutdown().await?;
|
||||
Ok(output_ok)
|
||||
})()
|
||||
.await,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__downloader_api__downloader_stop_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
@ -585,6 +665,36 @@ fn wire__crate__api__downloader_api__downloader_stop_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__downloader_api__downloader_update_speed_limits_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
_upload_limit_bps: impl CstDecode<Option<u32>>,
|
||||
_download_limit_bps: impl CstDecode<Option<u32>>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "downloader_update_speed_limits",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api__upload_limit_bps = _upload_limit_bps.cst_decode();
|
||||
let api__download_limit_bps = _download_limit_bps.cst_decode();
|
||||
move |context| async move {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || async move {
|
||||
let output_ok = crate::api::downloader_api::downloader_update_speed_limits(
|
||||
api__upload_limit_bps,
|
||||
api__download_limit_bps,
|
||||
)
|
||||
.await?;
|
||||
Ok(output_ok)
|
||||
})()
|
||||
.await,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__http_api__fetch_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
method: impl CstDecode<crate::api::http_api::MyMethod>,
|
||||
@ -2152,6 +2262,17 @@ impl SseDecode for Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for Option<u32> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
if (<bool>::sse_decode(deserializer)) {
|
||||
return Some(<u32>::sse_decode(deserializer));
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for Option<u64> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
@ -3081,6 +3202,16 @@ impl SseEncode for Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for Option<u32> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<bool>::sse_encode(self.is_some(), serializer);
|
||||
if let Some(value) = self {
|
||||
<u32>::sse_encode(value, serializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for Option<u64> {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
@ -3374,6 +3505,12 @@ mod io {
|
||||
CstDecode::<crate::api::asar_api::RsiLauncherAsarData>::cst_decode(*wrap).into()
|
||||
}
|
||||
}
|
||||
impl CstDecode<u32> for *mut u32 {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> u32 {
|
||||
unsafe { *flutter_rust_bridge::for_generated::box_from_leak_ptr(self) }
|
||||
}
|
||||
}
|
||||
impl CstDecode<u64> for *mut u64 {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> u64 {
|
||||
@ -3947,11 +4084,26 @@ mod io {
|
||||
wire__crate__api__downloader_api__downloader_get_task_info_impl(port_, task_id)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_has_active_tasks(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__downloader_api__downloader_has_active_tasks_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_init(
|
||||
download_dir: *mut wire_cst_list_prim_u_8_strict,
|
||||
working_dir: *mut wire_cst_list_prim_u_8_strict,
|
||||
default_download_dir: *mut wire_cst_list_prim_u_8_strict,
|
||||
upload_limit_bps: *mut u32,
|
||||
download_limit_bps: *mut u32,
|
||||
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartDco {
|
||||
wire__crate__api__downloader_api__downloader_init_impl(download_dir)
|
||||
wire__crate__api__downloader_api__downloader_init_impl(
|
||||
working_dir,
|
||||
default_download_dir,
|
||||
upload_limit_bps,
|
||||
download_limit_bps,
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@ -3992,6 +4144,13 @@ mod io {
|
||||
wire__crate__api__downloader_api__downloader_remove_impl(port_, task_id, delete_files)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_remove_completed_tasks(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__downloader_api__downloader_remove_completed_tasks_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_resume(
|
||||
port_: i64,
|
||||
@ -4007,6 +4166,13 @@ mod io {
|
||||
wire__crate__api__downloader_api__downloader_resume_all_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_shutdown(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__downloader_api__downloader_shutdown_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_stop(
|
||||
port_: i64,
|
||||
@ -4014,6 +4180,19 @@ mod io {
|
||||
wire__crate__api__downloader_api__downloader_stop_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_update_speed_limits(
|
||||
port_: i64,
|
||||
_upload_limit_bps: *mut u32,
|
||||
_download_limit_bps: *mut u32,
|
||||
) {
|
||||
wire__crate__api__downloader_api__downloader_update_speed_limits_impl(
|
||||
port_,
|
||||
_upload_limit_bps,
|
||||
_download_limit_bps,
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__http_api__fetch(
|
||||
port_: i64,
|
||||
@ -4441,6 +4620,11 @@ mod io {
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_cst_new_box_autoadd_u_32(value: u32) -> *mut u32 {
|
||||
flutter_rust_bridge::for_generated::new_leak_box_ptr(value)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_cst_new_box_autoadd_u_64(value: u64) -> *mut u64 {
|
||||
flutter_rust_bridge::for_generated::new_leak_box_ptr(value)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user