mirror of
https://github.com/venera-app/venera.git
synced 2025-09-26 23:47:23 +00:00

* 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>
112 lines
2.4 KiB
Dart
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);
|
|
}
|
|
} |