Files
xianyan/lib/core/utils/extensions.dart
Developer 7564e8893d chore: 完成多平台适配与代码优化
此提交包含多项变更:
1. 新增鸿蒙平台支持,完善设备检测与数据库适配
2. 替换旧版分享插件API为SharePlus
3. 批量迁移StateNotifier到Notifier以适配新版Riverpod
4. 修复zip编码判断、图表API参数等bug
5. 更新应用图标、启动页资源与多尺寸适配图标
6. 调整Android最小SDK版本与应用名称
7. 优化日志打印与正则表达式使用
8. 修正编辑器画布样式初始化与配置逻辑
9. 更新依赖与CI插件配置
2026-05-17 07:17:07 +08:00

166 lines
5.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// ============================================================
/// 闲言APP — 通用扩展方法
/// 创建时间: 2026-04-20
/// 更新时间: 2026-05-16
/// 作用: String / BuildContext / Color 等常用扩展
/// 上次更新: RegExp() → regex() 消除 Dart 3.11 废弃警告
/// ============================================================
import 'package:flutter/material.dart';
import 'package:xianyan/core/utils/pattern_utils.dart';
import 'device_detection.dart';
// ============================================================
// String 扩展
// ============================================================
/// 字符串扩展方法
extension StringX on String {
/// 是否为空白 (null 或纯空格)
bool get isBlank => trim().isEmpty;
/// 是否非空白
bool get isNotBlank => trim().isNotEmpty;
/// 截断到指定长度
String ellipsis(int maxLength, {String suffix = ''}) {
if (length <= maxLength) return this;
return '${substring(0, maxLength)}$suffix';
}
/// 首字母大写
String get capitalize {
if (isEmpty) return this;
return '${this[0].toUpperCase()}${substring(1)}';
}
/// 去除HTML标签保留纯文本
String get stripHtml {
if (isEmpty) return this;
var result = this;
result = result.replaceAll(regex(r'<br\s*/?>', caseSensitive: false), '\n');
result = result.replaceAll(regex(r'<p\s*/?>', caseSensitive: false), '\n');
result = result.replaceAll(regex(r'</p>', caseSensitive: false), '');
result = result.replaceAll(
regex(r'<strong[^>]*>(.*?)</strong>', caseSensitive: false, dotAll: true),
r'$1',
);
result = result.replaceAll(
regex(r'<em[^>]*>(.*?)</em>', caseSensitive: false, dotAll: true),
r'$1',
);
result = result.replaceAll(regex(r'<[^>]*>'), '');
result = result.replaceAll(regex(r'\n{3,}'), '\n\n');
return result.trim();
}
/// 解码HTML实体
String get decodeHtmlEntities {
if (isEmpty) return this;
return replaceAll('&amp;', '&')
.replaceAll('&lt;', '<')
.replaceAll('&gt;', '>')
.replaceAll('&quot;', '"')
.replaceAll('&#39;', "'")
.replaceAll('&nbsp;', ' ');
}
/// 去除HTML标签 + 解码HTML实体
String get cleanHtml => stripHtml.decodeHtmlEntities;
}
// ============================================================
// BuildContext 扩展
// ============================================================
/// BuildContext 扩展方法
extension BuildContextX on BuildContext {
/// 获取主题
ThemeData get theme => Theme.of(this);
/// 获取颜色方案
ColorScheme get colorScheme => Theme.of(this).colorScheme;
/// 获取 TextTheme
TextTheme get textTheme => Theme.of(this).textTheme;
/// 获取屏幕尺寸
Size get screenSize => MediaQuery.sizeOf(this);
/// 获取屏幕宽度
double get screenWidth => screenSize.width;
/// 获取屏幕高度
double get screenHeight => screenSize.height;
/// 获取底部安全区域
double get bottomPadding => MediaQuery.paddingOf(this).bottom;
/// 获取顶部安全区域
double get topPadding => MediaQuery.paddingOf(this).top;
/// 是否为小屏 (< mobile断点)
bool get isSmallScreen => screenWidth < Breakpoints.mobile;
/// 是否为中屏 (mobile - desktop断点)
bool get isMediumScreen =>
screenWidth >= Breakpoints.mobile && screenWidth < Breakpoints.desktop;
/// 是否为大屏 (>= desktop断点)
bool get isLargeScreen => screenWidth >= Breakpoints.desktop;
/// 是否横屏
bool get isLandscape => screenWidth > screenHeight;
/// 是否竖屏
bool get isPortrait => screenWidth < screenHeight;
/// 屏幕尺寸分类
ScreenSizeClass get sizeClass =>
DeviceDetection.sizeClassFromWidth(screenWidth);
/// 布局列数
int get layoutColumns => sizeClass.layoutColumns;
}
// ============================================================
// Color 扩展
// ============================================================
/// Color 扩展方法
extension ColorX on Color {
/// 调整透明度 (0.0 - 1.0)
Color withAlpha(double alpha) {
return withValues(alpha: alpha.clamp(0.0, 1.0));
}
}
// ============================================================
// DateTime 扩展
// ============================================================
/// DateTime 扩展方法
extension DateTimeX on DateTime {
/// 友好时间文本 (如 "3分钟前")
String get timeAgo {
final now = DateTime.now();
final diff = now.difference(this);
if (diff.inSeconds < 60) return '刚刚';
if (diff.inMinutes < 60) return '${diff.inMinutes}分钟前';
if (diff.inHours < 24) return '${diff.inHours}小时前';
if (diff.inDays < 30) return '${diff.inDays}天前';
if (diff.inDays < 365) return '${diff.inDays ~/ 30}个月前';
return '${diff.inDays ~/ 365}年前';
}
/// 格式化日期 yyyy-MM-dd
String get formatDate =>
'$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}';
/// 格式化时间 HH:mm
String get formatTime =>
'${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}';
}