Files
venera/lib/utils/ext.dart
luckyray d874920c88 Feat: Image favorites (#126)
* feat: 增加图片收藏

* feat: 主体图片收藏页面实现

* feat: 点击打开大图浏览

* feat: 数据结构变更

* feat: 基本完成

* feat: 翻译与bug修复

* feat: 实机测试和问题修复

* feat: jm导入, pica历史记录nhentai有问题, 一键反转

* fix: 大小写不一致, 一个htManga, 一个htmanga

* feat: 拉取收藏优化

* feat: 改成以ep为准

* feat: 兜底一些可能报错场景

* chore: 没有用到

* feat: 尽量保证和网络收藏顺序一致

* feat: 支持显示热点tag

* feat: 支持双击收藏, 不过此时禁止放大图片

* fix: 自动塞封面逻辑完善, 切换快速收藏图片立刻生效

* Refactor

* fix updateValue

* feat: 双击功能提示

* fix: 被确定取消收藏的才删除

* Refactor ImageFavoritesPage

* translate author

* feat: 功能提示改到dialog中

* fix text editing

* fix text editing

* feat: 功能提示放到邮件或长按菜单中

* fix: 修复tag过滤不生效问题

* Improve image loading

* The default value of quickCollectImage should be false.

* Refactor DragListener

* Refactor ImageFavoriteItem & ImageFavoritePhotoView

* Refactor

* Fix `ImageFavoriteManager.has`

* Fix UI

* Improve UI

---------

Co-authored-by: nyne <me@nyne.dev>
2025-01-15 16:07:08 +08:00

112 lines
2.4 KiB
Dart

extension ListExt<T> on List<T>{
/// Remove all blank value and return the list.
List<T> getNoBlankList(){
List<T> newList = [];
for(var value in this){
if(value.toString() != ""){
newList.add(value);
}
}
return newList;
}
T? firstWhereOrNull(bool Function(T element) test){
for(var element in this){
if(test(element)){
return element;
}
}
return null;
}
void addIfNotNull(T? value){
if(value != null){
add(value);
}
}
bool isEqualsTo(List<T> list){
if(length != list.length){
return false;
}
for(int i=0; i<length; i++){
if(this[i] != list[i]){
return false;
}
}
return true;
}
}
extension StringExt on String{
///Remove all value that would display blank on the screen.
String get removeAllBlank => replaceAll("\n", "").replaceAll(" ", "").replaceAll("\t", "");
/// convert this to a one-element list.
List<String> toList() => [this];
String _nums(){
String res = "";
for(int i=0; i<length; i++){
res += this[i].isNum?this[i]:"";
}
return res;
}
String get nums => _nums();
String setValueAt(String value, int index){
return replaceRange(index, index+1, value);
}
String? subStringOrNull(int start, [int? end]){
if(start < 0 || (end != null && end > length)){
return null;
}
return substring(start, end);
}
String replaceLast(String from, String to) {
if (isEmpty || from.isEmpty) {
return this;
}
final lastIndex = lastIndexOf(from);
if (lastIndex == -1) {
return this;
}
final before = substring(0, lastIndex);
final after = substring(lastIndex + from.length);
return '$before$to$after';
}
static bool hasMatch(String? value, String pattern) {
return (value == null) ? false : RegExp(pattern).hasMatch(value);
}
bool _isURL(){
final regex = RegExp(
r'^((http|https|ftp)://)[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-|]*[\w@?^=%&/~+#-])?$',
caseSensitive: false);
return regex.hasMatch(this);
}
bool get isURL => _isURL();
bool get isNum => double.tryParse(this) != null;
bool get isInt => int.tryParse(this) != null;
}
abstract class ListOrNull{
static List<T>? from<T>(Iterable<dynamic>? i){
return i == null ? null : List.from(i);
}
}
abstract class MapOrNull{
static Map<K, V>? from<K, V>(Map<dynamic, dynamic>? i){
return i == null ? null : Map<K, V>.from(i);
}
}