This commit is contained in:
DESKTOP-I3JPKHK\wy 2025-11-28 10:40:25 +08:00
parent 260a4df818
commit ecf000e466
1 changed files with 193 additions and 73 deletions

View File

@ -1089,80 +1089,10 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
}
Widget _buildRichText(String content, ColorScheme colorScheme) {
final spans = <TextSpan>[];
final regex = RegExp(r'\*\*(.*?)\*\*|__(.*?)__|`(.*?)`|\[(.*?)\]');
int lastIndex = 0;
//
final spans = _parseRichText(content, colorScheme);
for (final match in regex.allMatches(content)) {
if (match.start > lastIndex) {
spans.add(TextSpan(
text: content.substring(lastIndex, match.start),
style: TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.8),
height: 1.4,
),
));
}
if (match.group(1) != null) {
spans.add(TextSpan(
text: match.group(1),
style: TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.9),
height: 1.4,
fontWeight: FontWeight.bold,
),
));
} else if (match.group(2) != null) {
spans.add(TextSpan(
text: match.group(2),
style: TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.9),
height: 1.4,
fontStyle: FontStyle.italic,
),
));
} else if (match.group(3) != null) {
spans.add(TextSpan(
text: match.group(3),
style: TextStyle(
fontSize: 12,
color: colorScheme.primary,
height: 1.4,
fontFamily: 'monospace',
backgroundColor: colorScheme.primaryContainer.withOpacity(0.2),
),
));
} else if (match.group(4) != null) {
spans.add(TextSpan(
text: match.group(4),
style: TextStyle(
fontSize: 13,
color: colorScheme.primary,
height: 1.4,
fontWeight: FontWeight.w600,
),
));
}
lastIndex = match.end;
}
if (lastIndex < content.length) {
spans.add(TextSpan(
text: content.substring(lastIndex),
style: TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.8),
height: 1.4,
),
));
}
if (spans.isEmpty) {
if (spans.isEmpty || spans.length == 1 && spans[0].text == content) {
return Text(
content,
style: TextStyle(
@ -1182,6 +1112,196 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
);
}
///
///
///
/// - `****` -
/// - `__斜体__` -
/// - `` `` `` -
/// - `[]` -
///
///
/// - `__在[]__` -
/// - `[****]` -
/// - `` `****` `` -
///
///
/// 1.
/// 2.
/// 3.
/// 4.
List<TextSpan> _parseRichText(String content, ColorScheme colorScheme) {
final spans = <TextSpan>[];
// 使
// [] > ` > ** > __
final patterns = [
(regex: RegExp(r'\[([^\]]+)\]'), type: 'highlight'), // [] - ]
(regex: RegExp(r'`([^`]+)`'), type: 'code'), // `` - `
(regex: RegExp(r'\*\*([^*]+(?:\*(?!\*)[^*]*)*)\*\*'), type: 'bold'), // **** - **
(regex: RegExp(r'__([^_]+(?:_(?!_)[^_]*)*)__'), type: 'italic'), // __斜体__ - __
];
//
final allMatches = <({Match match, String type, int priority})>[];
for (int i = 0; i < patterns.length; i++) {
final pattern = patterns[i];
for (final match in pattern.regex.allMatches(content)) {
//
if (match.group(1) != null && match.group(1)!.isNotEmpty) {
allMatches.add((match: match, type: pattern.type, priority: i));
}
}
}
//
if (allMatches.isEmpty) {
return [
TextSpan(
text: content,
style: TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.8),
height: 1.4,
),
),
];
}
//
allMatches.sort((a, b) {
//
if (a.match.start != b.match.start) {
return a.match.start.compareTo(b.match.start);
}
// [] `
if (a.priority != b.priority) {
return a.priority.compareTo(b.priority);
}
//
return a.match.end.compareTo(b.match.end);
});
//
Match? selectedMatch;
String? selectedType;
for (final item in allMatches) {
bool isNested = false;
//
for (final other in allMatches) {
if (other.match != item.match &&
other.match.start <= item.match.start &&
other.match.end >= item.match.end &&
(other.match.start < item.match.start || other.match.end > item.match.end)) {
isNested = true;
break;
}
}
//
if (!isNested) {
selectedMatch = item.match;
selectedType = item.type;
break;
}
}
// 使
selectedMatch ??= allMatches.first.match;
selectedType ??= allMatches.first.type;
int lastIndex = 0;
//
if (selectedMatch.start > lastIndex) {
spans.add(TextSpan(
text: content.substring(lastIndex, selectedMatch.start),
style: TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.8),
height: 1.4,
),
));
}
//
final matchedContent = selectedMatch.group(1)!;
final nestedSpans = _parseRichText(matchedContent, colorScheme);
//
TextStyle baseStyle;
switch (selectedType) {
case 'bold':
baseStyle = TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.9),
height: 1.4,
fontWeight: FontWeight.bold,
);
break;
case 'italic':
baseStyle = TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.9),
height: 1.4,
fontStyle: FontStyle.italic,
);
break;
case 'code':
baseStyle = TextStyle(
fontSize: 12,
color: colorScheme.primary,
height: 1.4,
fontFamily: 'monospace',
backgroundColor: colorScheme.primaryContainer.withOpacity(0.2),
);
break;
case 'highlight':
baseStyle = TextStyle(
fontSize: 13,
color: colorScheme.primary,
height: 1.4,
fontWeight: FontWeight.w600,
);
break;
default:
baseStyle = TextStyle(
fontSize: 13,
color: colorScheme.onSurface.withOpacity(0.8),
height: 1.4,
);
}
// 使
if (nestedSpans.isNotEmpty &&
(nestedSpans.length > 1 || (nestedSpans.isNotEmpty && nestedSpans[0].text != matchedContent))) {
// spans
final styledSpans = nestedSpans.map((span) {
return TextSpan(
text: span.text,
style: span.style?.merge(baseStyle) ?? baseStyle,
children: span.children,
);
}).toList();
spans.addAll(styledSpans);
} else {
//
spans.add(TextSpan(
text: matchedContent,
style: baseStyle,
));
}
//
lastIndex = selectedMatch.end;
if (lastIndex < content.length) {
final remainingSpans = _parseRichText(content.substring(lastIndex), colorScheme);
spans.addAll(remainingSpans);
}
return spans;
}
Widget _buildEnhancedDownloadProgress(BuildContext context, ColorScheme colorScheme) {
final bool showRetryButton = _downloadedFilePath != null &&
!_isDownloading &&