mirror of
https://github.com/venera-app/venera.git
synced 2025-12-15 14:41:15 +00:00
Compare commits
6 Commits
upgrade-fl
...
v1.6.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
068d6148ad | ||
|
|
0b261f81ba | ||
|
|
781ff2553d | ||
|
|
0ce18cd738 | ||
| 40ef8a63b0 | |||
| 053293839e |
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
@@ -84,6 +84,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: rm -rf /opt/hostedtoolcache
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
"Show favorite status on comic tile": "在漫画缩略图上显示收藏状态",
|
||||
"Show history on comic tile": "在漫画缩略图上显示历史记录",
|
||||
"Keyword blocking": "关键词屏蔽",
|
||||
"Comment keyword blocking": "评论关键词屏蔽",
|
||||
"Tap to turn Pages": "点击翻页",
|
||||
"Page animation": "页面动画",
|
||||
"Reading mode": "阅读模式",
|
||||
@@ -529,6 +530,7 @@
|
||||
"Show favorite status on comic tile": "在漫畫縮圖上顯示收藏狀態",
|
||||
"Show history on comic tile": "在漫畫縮圖上顯示歷史記錄",
|
||||
"Keyword blocking": "關鍵字封鎖",
|
||||
"Comment keyword blocking": "評論關鍵字封鎖",
|
||||
"Tap to turn Pages": "點擊翻頁",
|
||||
"Page animation": "頁面動畫",
|
||||
"Reading mode": "閱讀模式",
|
||||
|
||||
@@ -13,7 +13,7 @@ export "widget_utils.dart";
|
||||
export "context.dart";
|
||||
|
||||
class _App {
|
||||
final version = "1.6.0";
|
||||
final version = "1.6.1";
|
||||
|
||||
bool get isAndroid => Platform.isAndroid;
|
||||
|
||||
|
||||
@@ -180,6 +180,7 @@ class Settings with ChangeNotifier {
|
||||
'showFavoriteStatusOnTile': true,
|
||||
'showHistoryStatusOnTile': false,
|
||||
'blockedWords': [],
|
||||
'blockedCommentWords': [],
|
||||
'defaultSearchTarget': null,
|
||||
'autoPageTurningInterval': 5, // in seconds
|
||||
'readerMode': 'galleryLeftToRight', // values of [ReaderMode]
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
part of 'comic_page.dart';
|
||||
|
||||
bool _shouldBlockComment(Comment comment) {
|
||||
var blockedWords = appdata.settings["blockedCommentWords"] as List;
|
||||
if (blockedWords.isEmpty) return false;
|
||||
|
||||
var content = comment.content.toLowerCase();
|
||||
for (var word in blockedWords) {
|
||||
if (content.contains(word.toString().toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class CommentsPage extends StatefulWidget {
|
||||
const CommentsPage({
|
||||
super.key,
|
||||
@@ -36,8 +49,9 @@ class _CommentsPageState extends State<CommentsPage> {
|
||||
_loading = false;
|
||||
});
|
||||
} else if (mounted) {
|
||||
var filteredComments = res.data.where((c) => !_shouldBlockComment(c)).toList();
|
||||
setState(() {
|
||||
_comments = res.data;
|
||||
_comments = filteredComments;
|
||||
_loading = false;
|
||||
maxPage = res.subData;
|
||||
});
|
||||
@@ -54,8 +68,9 @@ class _CommentsPageState extends State<CommentsPage> {
|
||||
if (res.error) {
|
||||
context.showMessage(message: res.errorMessage ?? "Unknown Error");
|
||||
} else {
|
||||
var filteredComments = res.data.where((c) => !_shouldBlockComment(c)).toList();
|
||||
setState(() {
|
||||
_comments!.addAll(res.data);
|
||||
_comments!.addAll(filteredComments);
|
||||
_page++;
|
||||
if (maxPage == null && res.data.isEmpty) {
|
||||
maxPage = _page;
|
||||
|
||||
@@ -21,7 +21,7 @@ class _CommentsPartState extends State<_CommentsPart> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
comments = widget.comments;
|
||||
comments = widget.comments.where((c) => !_shouldBlockComment(c)).toList();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
||||
@@ -258,29 +258,41 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
|
||||
else if (searchMode)
|
||||
SliverAppbar(
|
||||
leading: Tooltip(
|
||||
message: "Cancel".tl,
|
||||
message: multiSelectMode ? "Cancel".tl : "Cancel".tl,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
icon: multiSelectMode
|
||||
? const Icon(Icons.close)
|
||||
: const Icon(Icons.close),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
searchMode = false;
|
||||
keyword = "";
|
||||
update();
|
||||
});
|
||||
if (multiSelectMode) {
|
||||
setState(() {
|
||||
multiSelectMode = false;
|
||||
selectedComics.clear();
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
searchMode = false;
|
||||
keyword = "";
|
||||
update();
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
title: TextField(
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search".tl,
|
||||
border: InputBorder.none,
|
||||
),
|
||||
onChanged: (v) {
|
||||
keyword = v;
|
||||
update();
|
||||
},
|
||||
),
|
||||
title: multiSelectMode
|
||||
? Text(selectedComics.length.toString())
|
||||
: TextField(
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search".tl,
|
||||
border: InputBorder.none,
|
||||
),
|
||||
onChanged: (v) {
|
||||
keyword = v;
|
||||
update();
|
||||
},
|
||||
),
|
||||
actions: multiSelectMode ? selectActions : null,
|
||||
),
|
||||
SliverGridComics(
|
||||
comics: comics,
|
||||
@@ -344,6 +356,7 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
|
||||
return PopScope(
|
||||
canPop: !multiSelectMode && !searchMode,
|
||||
onPopInvokedWithResult: (didPop, result) {
|
||||
if (didPop) return;
|
||||
if (multiSelectMode) {
|
||||
setState(() {
|
||||
multiSelectMode = false;
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
part of 'reader.dart';
|
||||
|
||||
bool _shouldBlockComment(Comment comment) {
|
||||
var blockedWords = appdata.settings["blockedCommentWords"] as List;
|
||||
if (blockedWords.isEmpty) return false;
|
||||
|
||||
var content = comment.content.toLowerCase();
|
||||
for (var word in blockedWords) {
|
||||
if (content.contains(word.toString().toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class ChapterCommentsPage extends StatefulWidget {
|
||||
const ChapterCommentsPage({
|
||||
super.key,
|
||||
@@ -44,8 +57,9 @@ class _ChapterCommentsPageState extends State<ChapterCommentsPage> {
|
||||
_loading = false;
|
||||
});
|
||||
} else if (mounted) {
|
||||
var filteredComments = res.data.where((c) => !_shouldBlockComment(c)).toList();
|
||||
setState(() {
|
||||
_comments = res.data;
|
||||
_comments = filteredComments;
|
||||
_loading = false;
|
||||
maxPage = res.subData;
|
||||
});
|
||||
@@ -62,8 +76,9 @@ class _ChapterCommentsPageState extends State<ChapterCommentsPage> {
|
||||
if (res.error) {
|
||||
context.showMessage(message: res.errorMessage ?? "Unknown Error");
|
||||
} else {
|
||||
var filteredComments = res.data.where((c) => !_shouldBlockComment(c)).toList();
|
||||
setState(() {
|
||||
_comments!.addAll(res.data);
|
||||
_comments!.addAll(filteredComments);
|
||||
_page++;
|
||||
if (maxPage == null && res.data.isEmpty) {
|
||||
maxPage = _page;
|
||||
|
||||
@@ -60,6 +60,10 @@ class _ExploreSettingsState extends State<ExploreSettings> {
|
||||
title: "Keyword blocking".tl,
|
||||
builder: () => const _ManageBlockingWordView(),
|
||||
).toSliver(),
|
||||
_PopupWindowSetting(
|
||||
title: "Comment keyword blocking".tl,
|
||||
builder: () => const _ManageBlockingCommentWordView(),
|
||||
).toSliver(),
|
||||
SelectSetting(
|
||||
title: "Default Search Target".tl,
|
||||
settingKey: "defaultSearchTarget",
|
||||
@@ -250,4 +254,93 @@ Widget setSearchSourcesWidget() {
|
||||
settingsIndex: "searchSources",
|
||||
pages: pages,
|
||||
);
|
||||
}
|
||||
|
||||
class _ManageBlockingCommentWordView extends StatefulWidget {
|
||||
const _ManageBlockingCommentWordView();
|
||||
|
||||
@override
|
||||
State<_ManageBlockingCommentWordView> createState() =>
|
||||
_ManageBlockingCommentWordViewState();
|
||||
}
|
||||
|
||||
class _ManageBlockingCommentWordViewState extends State<_ManageBlockingCommentWordView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(appdata.settings["blockedCommentWords"] is List);
|
||||
return PopUpWidgetScaffold(
|
||||
title: "Comment keyword blocking".tl,
|
||||
tailing: [
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.add),
|
||||
label: Text("Add".tl),
|
||||
onPressed: add,
|
||||
),
|
||||
],
|
||||
body: ListView.builder(
|
||||
itemCount: appdata.settings["blockedCommentWords"].length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
title: Text(appdata.settings["blockedCommentWords"][index]),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () {
|
||||
appdata.settings["blockedCommentWords"].removeAt(index);
|
||||
appdata.saveData();
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void add() {
|
||||
showDialog(
|
||||
context: App.rootContext,
|
||||
builder: (context) {
|
||||
var controller = TextEditingController();
|
||||
String? error;
|
||||
return StatefulBuilder(builder: (context, setState) {
|
||||
return ContentDialog(
|
||||
title: "Add keyword".tl,
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
label: Text("Keyword".tl),
|
||||
errorText: error,
|
||||
),
|
||||
onChanged: (s) {
|
||||
if (error != null) {
|
||||
setState(() {
|
||||
error = null;
|
||||
});
|
||||
}
|
||||
},
|
||||
).paddingHorizontal(12),
|
||||
actions: [
|
||||
Button.filled(
|
||||
onPressed: () {
|
||||
if (appdata.settings["blockedCommentWords"]
|
||||
.contains(controller.text)) {
|
||||
setState(() {
|
||||
error = "Keyword already exists".tl;
|
||||
});
|
||||
return;
|
||||
}
|
||||
appdata.settings["blockedCommentWords"].add(controller.text);
|
||||
appdata.saveData();
|
||||
this.setState(() {});
|
||||
context.pop();
|
||||
},
|
||||
child: Text("Add".tl),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ name: venera
|
||||
description: "A comic app."
|
||||
publish_to: 'none'
|
||||
|
||||
version: 1.6.0+160
|
||||
version: 1.6.1+161
|
||||
|
||||
environment:
|
||||
sdk: '>=3.8.0 <4.0.0'
|
||||
|
||||
Reference in New Issue
Block a user