feat: update

This commit is contained in:
xkeyC 2025-12-20 17:31:36 +08:00
parent 6d2bb89c64
commit 79cc157e04
10 changed files with 95 additions and 38 deletions

View File

@ -16,9 +16,6 @@ import 'package:starcitizen_doctor/ui/guide/guide_ui.dart';
import 'package:starcitizen_doctor/ui/home/performance/performance_ui.dart';
import 'package:starcitizen_doctor/ui/splash_ui.dart';
import 'package:starcitizen_doctor/widgets/widgets.dart';
import 'package:uuid/uuid.dart';
import 'api/analytics.dart';
import 'api/api.dart';
import 'common/conf/url_conf.dart';
import 'common/helper/system_helper.dart';

View File

@ -1883,7 +1883,7 @@ class MessageLookup extends MessageLookupByLibrary {
),
"yearly_report_play_time_value": m89,
"yearly_report_powered_by": MessageLookupByLibrary.simpleMessage(
"Presented by SCToolbox",
"Presented by SCToolbox | github.com/StarCitizenToolBox/app",
),
"yearly_report_session_average": MessageLookupByLibrary.simpleMessage(
"Average",

View File

@ -1693,7 +1693,7 @@ class MessageLookup extends MessageLookupByLibrary {
"yearly_report_play_time_unit": MessageLookupByLibrary.simpleMessage("時間"),
"yearly_report_play_time_value": m89,
"yearly_report_powered_by": MessageLookupByLibrary.simpleMessage(
"SCToolbox 提供",
"SCToolbox 提供 | github.com/StarCitizenToolBox/app",
),
"yearly_report_session_average": MessageLookupByLibrary.simpleMessage("平均"),
"yearly_report_session_date": m90,

View File

@ -1897,7 +1897,7 @@ class MessageLookup extends MessageLookupByLibrary {
),
"yearly_report_play_time_value": m89,
"yearly_report_powered_by": MessageLookupByLibrary.simpleMessage(
"Представлено SCToolbox",
"Представлено SCToolbox | github.com/StarCitizenToolBox/app",
),
"yearly_report_session_average": MessageLookupByLibrary.simpleMessage(
"Среднее",

View File

@ -1621,7 +1621,7 @@ class MessageLookup extends MessageLookupByLibrary {
"yearly_report_play_time_unit": MessageLookupByLibrary.simpleMessage("小时"),
"yearly_report_play_time_value": m89,
"yearly_report_powered_by": MessageLookupByLibrary.simpleMessage(
"由 SC 汉化盒子为您呈现",
"由 SC 汉化盒子为您呈现 | github.com/StarCitizenToolBox/app",
),
"yearly_report_session_average": MessageLookupByLibrary.simpleMessage("平均"),
"yearly_report_session_date": m90,

View File

@ -1624,7 +1624,7 @@ class MessageLookup extends MessageLookupByLibrary {
"yearly_report_play_time_unit": MessageLookupByLibrary.simpleMessage("小時"),
"yearly_report_play_time_value": m89,
"yearly_report_powered_by": MessageLookupByLibrary.simpleMessage(
"由 SC工具箱為您呈現",
"由 SC工具箱為您呈現 | github.com/StarCitizenToolBox/app",
),
"yearly_report_session_average": MessageLookupByLibrary.simpleMessage("平均"),
"yearly_report_session_date": m90,

View File

@ -6812,10 +6812,10 @@ class S {
);
}
/// `Presented by SCToolbox`
/// `Presented by SCToolbox | github.com/StarCitizenToolBox/app`
String get yearly_report_powered_by {
return Intl.message(
'Presented by SCToolbox',
'Presented by SCToolbox | github.com/StarCitizenToolBox/app',
name: 'yearly_report_powered_by',
desc: '',
args: [],

View File

@ -7,6 +7,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:starcitizen_doctor/app.dart';
import 'package:starcitizen_doctor/common/utils/log.dart';
import 'package:starcitizen_doctor/widgets/widgets.dart';
import 'package:web/web.dart' as web;
@ -65,6 +66,12 @@ class YearlyReportEntryUIRoute extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final globalState = ref.watch(appGlobalModelProvider);
// initApp
useEffect(() {
ref.read(appGlobalModelProvider.notifier).initApp();
return null;
}, const []);
// 使 index_ui.dart
return Container(
color: const Color(0xFF0a0a12), //
@ -94,25 +101,16 @@ class YearlyReportEntryUIRoute extends HookConsumerWidget {
},
),
),
//
Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.black.withValues(alpha: .6), Colors.black.withValues(alpha: .75)],
),
),
),
//
Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 1440, maxHeight: 920),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(12)),
child: BlurOvalWidget(child: const YearlyReportEntryUI()),
child: BlurOvalWidget(
blurColor: Colors.black.withValues(alpha: .65),
child: const YearlyReportEntryUI(),
),
),
),
),
@ -304,27 +302,31 @@ class YearlyReportEntryUI extends HookConsumerWidget {
loadingProgress.value = 0;
errorMessage.value = null;
dPrint('[YearlyReport] Starting to read log files from directory...');
final contents = await _readLogFilesFromDirectory(loadingMessage, loadingProgress);
if (contents.isEmpty) {
dPrint('[YearlyReport] No log files found');
errorMessage.value = S.current.yearly_report_web_no_logs_found;
isLoading.value = false;
return;
}
dPrint('[YearlyReport] Successfully read ${contents.length} log files');
logContents.value = contents;
} catch (e) {
errorMessage.value = e.toString();
} catch (e, stackTrace) {
dPrint('[YearlyReport] Error reading directory: $e');
dPrint('[YearlyReport] Stack trace: $stackTrace');
errorMessage.value = 'Error: $e\n\nStack trace:\n$stackTrace';
isLoading.value = false;
}
}
bool _isDirectoryPickerSupported() {
try {
return true;
} catch (_) {
return false;
}
// WASM/Web true
// js_interop @JS 使
dPrint('[YearlyReport] Assuming showDirectoryPicker API is available (will handle error if not)');
return true;
}
Future<List<String>> _readLogFilesFromDirectory(
@ -334,18 +336,26 @@ class YearlyReportEntryUI extends HookConsumerWidget {
final logContents = <String>[];
try {
dPrint('[YearlyReport] Calling showDirectoryPicker...');
final dirHandle = await _showDirectoryPickerWrapper();
if (dirHandle == null) return [];
if (dirHandle == null) {
dPrint('[YearlyReport] User cancelled directory picker');
return [];
}
dPrint('[YearlyReport] Got directory handle');
final dirHandleJS = FileSystemDirectoryHandleJS(dirHandle);
// LIVE
FileSystemDirectoryHandleJS? liveHandle;
try {
dPrint('[YearlyReport] Trying to get LIVE directory...');
final livePromise = dirHandleJS.getDirectoryHandle('LIVE'.toJS);
final liveResult = await livePromise.toDart;
liveHandle = FileSystemDirectoryHandleJS(liveResult);
} catch (_) {
dPrint('[YearlyReport] Found LIVE directory');
} catch (e) {
dPrint('[YearlyReport] LIVE directory not found, using selected directory: $e');
liveHandle = dirHandleJS;
}
@ -354,18 +364,29 @@ class YearlyReportEntryUI extends HookConsumerWidget {
// Game.log
try {
dPrint('[YearlyReport] Trying to get Game.log...');
final gameLogPromise = liveHandle.getFileHandle('Game.log'.toJS);
final gameLogResult = await gameLogPromise.toDart;
filesToRead.add(FileSystemFileHandleJS(gameLogResult));
} catch (_) {}
dPrint('[YearlyReport] Found Game.log');
} catch (e) {
dPrint('[YearlyReport] Game.log not found: $e');
}
// logbackups
try {
dPrint('[YearlyReport] Trying to get logbackups directory...');
final logbackupsPromise = liveHandle.getDirectoryHandle('logbackups'.toJS);
final logbackupsResult = await logbackupsPromise.toDart;
final logbackupsHandle = FileSystemDirectoryHandleJS(logbackupsResult);
dPrint('[YearlyReport] Found logbackups directory');
await _collectLogbackupsFiles(logbackupsHandle, filesToRead);
} catch (_) {}
dPrint('[YearlyReport] Collected ${filesToRead.length} files from logbackups');
} catch (e) {
dPrint('[YearlyReport] logbackups directory not found: $e');
}
dPrint('[YearlyReport] Total files to read: ${filesToRead.length}');
//
for (var i = 0; i < filesToRead.length; i++) {
@ -380,12 +401,18 @@ class YearlyReportEntryUI extends HookConsumerWidget {
final content = await _readFileContent(fileHandle);
if (content.isNotEmpty) {
logContents.add(content);
dPrint('[YearlyReport] Read file: $fileName (${content.length} chars)');
}
} catch (_) {}
} catch (e) {
dPrint('[YearlyReport] Error reading file $fileName: $e');
}
}
loadingProgress.value = 1.0;
} catch (e) {
dPrint('[YearlyReport] Finished reading files, total: ${logContents.length}');
} catch (e, stackTrace) {
dPrint('[YearlyReport] Error in _readLogFilesFromDirectory: $e');
dPrint('[YearlyReport] Stack trace: $stackTrace');
rethrow;
}
@ -416,18 +443,30 @@ class YearlyReportEntryUI extends HookConsumerWidget {
filesToRead.add(handleJS);
}
}
} catch (e) {}
} catch (e) {
dPrint('[YearlyReport] Error collecting logbackups files: $e');
}
}
Future<JSObject?> _showDirectoryPickerWrapper() async {
try {
dPrint('[YearlyReport] Calling _showDirectoryPicker JS function...');
final promise = _showDirectoryPicker();
dPrint('[YearlyReport] Got promise, awaiting result...');
final result = await promise.toDart;
dPrint('[YearlyReport] Got result from showDirectoryPicker');
return result;
} catch (e) {
} catch (e, stackTrace) {
dPrint('[YearlyReport] Error in _showDirectoryPickerWrapper: $e');
dPrint('[YearlyReport] Stack trace: $stackTrace');
if (e.toString().contains('AbortError')) {
dPrint('[YearlyReport] User aborted the picker');
return null;
}
// API
if (e.toString().contains('TypeError') || e.toString().contains('undefined')) {
throw Exception('${S.current.yearly_report_web_browser_not_supported}\n\nTechnical details: $e');
}
rethrow;
}
}

View File

@ -1243,6 +1243,26 @@ class _SummaryPage extends StatelessWidget {
style: TextStyle(fontSize: 16, color: Colors.white.withValues(alpha: .6)),
),
),
const SizedBox(height: 32),
FadeInUp(
delay: const Duration(milliseconds: 900),
child: Button(
onPressed: () {
launchUrlString("https://github.com/StarCitizenToolBox/app");
},
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(FontAwesomeIcons.github),
const SizedBox(width: 12),
Text(S.current.support_dev_github_star_button),
],
),
),
),
),
],
),
);

View File

@ -6,6 +6,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:starcitizen_doctor/common/helper/yearly_report_analyzer.dart';
import 'package:starcitizen_doctor/widgets/widgets.dart';
import 'package:url_launcher/url_launcher_string.dart';
part 'yearly_report_pages.dart';