Skip to content

Commit d7a1478

Browse files
authored
Merge pull request #674 from DanXi-Dev/hotfix-152
change: improve forum list behavior and desktop image save UX
2 parents d99a932 + fe1d725 commit d7a1478

13 files changed

Lines changed: 173 additions & 36 deletions

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
# 旦挞
55

6-
[![CI](https://github.com/DanXi-Dev/DanXi/actions/workflows/ci_ios.yml/badge.svg)](https://github.com/DanXi-Dev/DanXi/actions/workflows/ci_ios.yml)
76
[![Deploy to GitHub Pages](https://github.com/DanXi-Dev/DanXi/actions/workflows/deploy_to_gh-pages.yml/badge.svg)](https://github.com/DanXi-Dev/DanXi/actions/workflows/deploy_to_gh-pages.yml)
87

98
(原名旦夕、旦兮)
@@ -102,10 +101,10 @@ LIBGL_ALWAYS_SOFTWARE=1 ./danxi
102101

103102
```shell
104103
$ flutter --version
105-
Flutter 3.41.0 • channel stable • https://github.com/flutter/flutter.git
106-
Framework • revision 44a626f4f0 (2 天前) • 2026-02-10 10:16:12 -0800
107-
Engine • hash cc8e596aa65130a0678cc59613ed1c5125184db4 (revision 3452d735bd) (2 days ago) • 2026-02-09 22:03:17.000Z
108-
Tools • Dart 3.11.0 • DevTools 2.54.1
104+
Flutter 3.41.6 • channel stable • https://github.com/flutter/flutter.git
105+
Framework • revision db50e20168 (3 周前) • 2026-03-25 16:21:00 -0700
106+
Engine • hash 5cdd32777948fa7a648fac915f8da7120ac7e97a (revision 425cfb54d0) (19 days ago) • 2026-03-25 20:14:42.000Z
107+
Tools • Dart 3.11.4 • DevTools 2.54.2
109108
```
110109

111110
## 编译说明

README_EN.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
# Danta
55

6-
[![CI](https://github.com/DanXi-Dev/DanXi/actions/workflows/ci_ios.yml/badge.svg)](https://github.com/DanXi-Dev/DanXi/actions/workflows/ci_ios.yml)
76
[![Deploy to GitHub Pages](https://github.com/DanXi-Dev/DanXi/actions/workflows/deploy_to_gh-pages.yml/badge.svg)](https://github.com/DanXi-Dev/DanXi/actions/workflows/deploy_to_gh-pages.yml)
87

98
> **CAUTION**
@@ -108,10 +107,10 @@ See [flutter_inappwebview#460](https://github.com/pichillilorenzo/flutter_inappw
108107

109108
```shell
110109
$ flutter --version
111-
Flutter 3.41.0 • channel stable • https://github.com/flutter/flutter.git
112-
Framework • revision 44a626f4f0 (2 days ago) • 2026-02-10 10:16:12 -0800
113-
Engine • hash cc8e596aa65130a0678cc59613ed1c5125184db4 (revision 3452d735bd) (2 days ago) • 2026-02-09 22:03:17.000Z
114-
Tools • Dart 3.11.0 • DevTools 2.54.1
110+
Flutter 3.41.6 • channel stable • https://github.com/flutter/flutter.git
111+
Framework • revision db50e20168 (3 weeks ago) • 2026-03-25 16:21:00 -0700
112+
Engine • hash 5cdd32777948fa7a648fac915f8da7120ac7e97a (revision 425cfb54d0) (19 days ago) • 2026-03-25 20:14:42.000Z
113+
Tools • Dart 3.11.4 • DevTools 2.54.2
115114
```
116115

117116
## Notes on compilation

lib/feature/welcome_feature.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class WelcomeFeature extends Feature {
8989

9090
@override
9191
Widget? get customSubtitle {
92-
if (SettingsProvider.getInstance().debugMode) {
92+
if (PlatformX.isDebugMode(context)) {
9393
return const Text(
9494
"Welcome, developer. [Debug Mode Enabled]",
9595
style: TextStyle(color: Colors.red),

lib/l10n/intl_en.arb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@
531531
"clear_history_confirm": "Are you sure to clear local view history? this cannot be reverted. ",
532532
"export_log_confirmation": "Please confirm before exporting:\n1. An error occurred recently during the current application session. If not, please reproduce the error first, then return here to export the log immediately;\n2. The developer requesting the log is a trusted individual. The log may contain your personal sensitive information (including login credentials), so please share with caution.\n\nConfirm to export the log?",
533533
"export_log_exporting": "Exporting logs…",
534+
"open_image_folder": "Open Containing Folder",
535+
"open_image_folder_failed": "Unable to open containing folder",
534536
"export_log_to_path": "Log file has been exported to a temporary file: {path}. Please send this file to a developer.",
535537
"export_log_success": "Export successful",
536538
"hole_frozen": "Frozen",

lib/l10n/intl_ja.arb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@
514514
"clear_history_confirm": "ローカルの閲覧履歴を削除しますか?この過程は不可逆です",
515515
"export_log_confirmation": "エクスポートする前に確認してください。\n1. 今回のアプリ実行中に、最近エラーが発生しましたか?発生していない場合は、まずエラーを再現させてから、すぐにここに戻ってログを再エクスポートしてください。\n2. ログの共有を求めているのは信頼できる開発者ですか?ログには、あなたの個人情報(ログイン情報を含む)が含まれる可能性がありますので、共有には十分注意してください。\n\nログをエクスポートしますか?",
516516
"export_log_exporting": "ログをエクスポート中…",
517+
"open_image_folder": "保存先フォルダを開く",
518+
"open_image_folder_failed": "画像の保存先フォルダを開けませんでした",
517519
"export_log_to_path": "ログファイルは一時ファイルにエクスポートされました:{path}。開発者に送信してください。",
518520
"export_log_success": "エクスポートに成功しました",
519521
"hole_frozen": "凍結",

lib/l10n/intl_zh_Hans.arb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@
525525
"clear_history_confirm": "是否清除本地浏览记录?清除后无法恢复。",
526526
"export_log_confirmation": "导出前请确认:\n1. 在本次应用运行期间内最近发生过错误。如果没有,请先重现错误,然后立刻返回这里重新导出日志;\n2. 要求你分享日志的是可信的开发者。日志中可能包含你的个人敏感信息(包括登录凭据),请谨慎分享。\n\n确认导出日志?",
527527
"export_log_exporting": "导出日志中…",
528+
"open_image_folder": "打开所在文件夹",
529+
"open_image_folder_failed": "无法打开图片所在文件夹",
528530
"export_log_to_path": "日志文件已导出到临时文件:{path},请自行处理该文件。",
529531
"export_log_success": "导出成功",
530532
"hole_frozen": "已冻结",

lib/l10n/intl_zh_Hant.arb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@
525525
"clear_history_confirm": "是否清除本機瀏覽記錄?清除後無法恢復。",
526526
"export_log_confirmation": "匯出前請確認:\n1. 在本次應用執行期間內最近發生過錯誤。如果沒有,請先重現錯誤,然後立刻返回此處重新匯出日誌;\n2. 要求你分享日誌的是可信的開發者。日誌中可能包含你的個人敏感資訊(包括登入憑證),請謹慎分享。\n\n確認匯出日誌?",
527527
"export_log_exporting": "匯出日誌中…",
528+
"open_image_folder": "打開所在資料夾",
529+
"open_image_folder_failed": "無法打開圖片所在資料夾",
528530
"export_log_to_path": "日誌檔案已匯出到暫存檔案:{path},請自行處理該檔案。",
529531
"export_log_success": "匯出成功",
530532
"hole_frozen": "已凍結",

lib/page/forum/image_viewer.dart

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,44 @@ class ImageViewerPageState extends State<ImageViewerPage> {
186186
Noticing.showNotice(context, S.of(context).image_save_failed);
187187
}
188188
} else if (context.mounted) {
189-
Noticing.showNotice(context, image.absolute.path);
189+
if (PlatformX.isDesktop) {
190+
Future<void> openContainingFolderAction() async {
191+
final bool opened =
192+
await PlatformX.openContainingFolder(image.absolute.path);
193+
if (!opened && context.mounted) {
194+
await Noticing.showNotice(
195+
context,
196+
S.of(context).open_image_folder_failed,
197+
);
198+
}
199+
}
200+
201+
if (PlatformX.isMaterial(context)) {
202+
ScaffoldMessenger.of(context).showSnackBar(
203+
SnackBar(
204+
content: Text(image.absolute.path),
205+
action: SnackBarAction(
206+
label: S.of(context).open_image_folder,
207+
onPressed: () => unawaited(openContainingFolderAction()),
208+
),
209+
),
210+
);
211+
} else {
212+
await Noticing.showNotice(
213+
context,
214+
image.absolute.path,
215+
useSnackBar: false,
216+
customActions: [
217+
CustomDialogActionItem(
218+
S.of(context).open_image_folder,
219+
() => unawaited(openContainingFolderAction()),
220+
)
221+
],
222+
);
223+
}
224+
} else {
225+
Noticing.showNotice(context, image.absolute.path);
226+
}
190227
}
191228
}
192229

lib/page/subpage_forum.dart

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,29 @@ class ForumSubpage extends PlatformSubpage<ForumSubpage> {
217217
RefreshListEvent().fire();
218218
}
219219

220+
final SortOrder currentSortOrder =
221+
cxt.select<SettingsProvider, SortOrder?>(
222+
(value) => value.forumSortOrder) ??
223+
SortOrder.LAST_REPLIED;
224+
final PopupMenuOption lastRepliedOption = PopupMenuOption(
225+
label: S.of(cxt).last_replied,
226+
cupertino: (context, platform) => CupertinoPopupMenuOptionData(
227+
isDefaultAction: currentSortOrder == SortOrder.LAST_REPLIED),
228+
onTap: (_) => onChangeSortOrder(cxt, SortOrder.LAST_REPLIED));
229+
final PopupMenuOption lastCreatedOption = PopupMenuOption(
230+
label: S.of(cxt).last_created,
231+
cupertino: (context, platform) => CupertinoPopupMenuOptionData(
232+
isDefaultAction: currentSortOrder == SortOrder.LAST_CREATED),
233+
onTap: (_) => onChangeSortOrder(cxt, SortOrder.LAST_CREATED));
234+
final List<PopupMenuOption> sortOptions = [
235+
lastRepliedOption,
236+
lastCreatedOption
237+
];
238+
final PopupMenuOption currentSortOption =
239+
currentSortOrder == SortOrder.LAST_CREATED
240+
? lastCreatedOption
241+
: lastRepliedOption;
242+
220243
return [
221244
if (cxt.select<ForumProvider, bool>(
222245
(value) => value.userInfo?.is_admin ?? false)) ...[
@@ -231,19 +254,18 @@ class ForumSubpage extends PlatformSubpage<ForumSubpage> {
231254
AppBarButtonItem(
232255
S.of(cxt).sort_order,
233256
PlatformPopupMenuX(
234-
options: [
235-
PopupMenuOption(
236-
label: S.of(cxt).last_replied,
237-
onTap: (_) =>
238-
onChangeSortOrder(cxt, SortOrder.LAST_REPLIED)),
239-
PopupMenuOption(
240-
label: S.of(cxt).last_created,
241-
onTap: (_) =>
242-
onChangeSortOrder(cxt, SortOrder.LAST_CREATED))
243-
],
257+
options: sortOptions,
244258
cupertino: (context, platform) => CupertinoPopupMenuData(
245259
cancelButtonData: CupertinoPopupMenuCancelButtonData(
246260
child: Text(S.of(context).cancel))),
261+
material: (context, platform) => MaterialPopupMenuData(
262+
initialValue: currentSortOption,
263+
itemBuilder: (context) => sortOptions
264+
.map((option) => CheckedPopupMenuItem<PopupMenuOption>(
265+
value: option,
266+
checked: option == currentSortOption,
267+
child: Text(option.label ?? '')))
268+
.toList()),
247269
icon: Icon(PlatformX.isMaterial(cxt)
248270
? Icons.filter_list
249271
: CupertinoIcons.sort_down_circle),
@@ -405,7 +427,7 @@ class ForumSubpageState extends PlatformSubpageState<ForumSubpage> {
405427
.generateReceiver(listViewController, (lastElement) {
406428
DateTime time = DateTime.now();
407429
if (lastElement != null) {
408-
time = DateTime.parse(lastElement.time_updated!);
430+
time = DateTime.parse(lastElement.time_created!);
409431
}
410432
return ForumRepository.getInstance()
411433
.loadUserHoles(time, sortOrder: SortOrder.LAST_CREATED);
@@ -432,17 +454,23 @@ class ForumSubpageState extends PlatformSubpageState<ForumSubpage> {
432454
case PostsType.NORMAL_POSTS:
433455
List<OTHole>? loadedPost = await adaptLayer
434456
.generateReceiver(listViewController, (lastElement) {
457+
final SortOrder sortOrder =
458+
context.read<SettingsProvider>().forumSortOrder ??
459+
SortOrder.LAST_REPLIED;
435460
DateTime time = DateTime.now();
436461
if (lastElement != null) {
437-
time = DateTime.parse(lastElement.time_updated!);
462+
time = DateTime.parse(switch (sortOrder) {
463+
SortOrder.LAST_CREATED => lastElement.time_created!,
464+
SortOrder.LAST_REPLIED => lastElement.time_updated!
465+
});
438466
}
439467

440-
final requestDivisionId =
468+
final DivisionIdentifier? requestDivisionId =
441469
_tagFilter == null ? getDivisionId(context) : null;
442470
return ForumRepository.getInstance().loadHoles(
443-
time, requestDivisionId!,
471+
time, requestDivisionId,
444472
tag: _tagFilter,
445-
sortOrder: context.read<SettingsProvider>().forumSortOrder);
473+
sortOrder: sortOrder);
446474
}).call(page);
447475

448476
// If not more posts, notify ListView that we reached the end.
@@ -459,8 +487,10 @@ class ForumSubpageState extends PlatformSubpageState<ForumSubpage> {
459487
// Filter blocked posts
460488
List<OTTag> hiddenTags =
461489
SettingsProvider.getInstance().hiddenTags ?? [];
462-
loadedPost?.removeWhere((element) => element.tags!.any((thisTag) =>
463-
hiddenTags.any((blockTag) => thisTag.name == blockTag.name)));
490+
loadedPost?.removeWhere((element) =>
491+
element.tags?.any((thisTag) =>
492+
hiddenTags.any((blockTag) => thisTag.name == blockTag.name)) ??
493+
false);
464494
// Filter hidden posts
465495
List<int> hiddenPosts = SettingsProvider.getInstance().hiddenHoles;
466496
loadedPost?.removeWhere((element) =>

lib/page/subpage_settings.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ class SettingsPageState extends State<SettingsPage> {
721721

722722
// FDUHOLE
723723
_buildForumSettingsCard(context),
724-
if (SettingsProvider.getInstance().debugMode)
724+
if (PlatformX.isDebugMode(context))
725725
//Theme Selection
726726
Card(
727727
child: ListTile(
@@ -739,7 +739,7 @@ class SettingsPageState extends State<SettingsPage> {
739739
.changeToMaterialPlatform(),
740740
),
741741
),
742-
if (SettingsProvider.getInstance().debugMode)
742+
if (PlatformX.isDebugMode(context))
743743
Card(
744744
child: ListTile(
745745
title: const Text("Fancy Watermark"),
@@ -979,7 +979,7 @@ class SettingsPageState extends State<SettingsPage> {
979979
});
980980
},
981981
),
982-
if (SettingsProvider.getInstance().debugMode)
982+
if (PlatformX.isDebugMode(context))
983983
ListTile(
984984
leading: const Icon(Icons.speed),
985985
title: const Text("Light Rendering"),

0 commit comments

Comments
 (0)