Skip to content

Commit f467587

Browse files
committed
feat(thread): check and show soft closed state
1 parent 39db988 commit f467587

File tree

6 files changed

+40
-3
lines changed

6 files changed

+40
-3
lines changed

lib/features/thread/v1/bloc/thread_bloc.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ class ThreadBloc extends Bloc<ThreadEvent, ThreadState> with LoggerMixin {
212212
final threadLink = document.querySelector('head > link')?.attributes['href'];
213213
final tid = Uri.parse(threadLink ?? '').queryParameters['tid'];
214214

215+
final threadSoftClosed = document.querySelector('div#postlist h1.ts img[title="关闭"]') != null;
215216
final threadClosed = document.querySelector('form#fastpostform') == null;
216217
final threadDataNode = document.querySelector('div#postlist');
217218
final postList = Post.buildListFromThreadDataNode(threadDataNode, document.currentPage() ?? 1);
@@ -319,6 +320,7 @@ class ThreadBloc extends Bloc<ThreadEvent, ThreadState> with LoggerMixin {
319320
havePermission: havePermission,
320321
permissionDeniedMessage: permissionDeniedMessage,
321322
needLogin: needLogin,
323+
threadSoftClosed: threadSoftClosed,
322324
threadClosed: threadClosed,
323325
postList: [...state.postList, ...postList],
324326
threadType: threadType,

lib/features/thread/v1/bloc/thread_state.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ThreadState with ThreadStateMappable {
3232
this.havePermission = true,
3333
this.permissionDeniedMessage,
3434
this.needLogin = false,
35+
this.threadSoftClosed = false,
3536
this.threadClosed = false,
3637
this.postList = const [],
3738
this.replyParameters,
@@ -99,6 +100,15 @@ class ThreadState with ThreadStateMappable {
99100
/// Only works when no user logged.
100101
final bool needLogin;
101102

103+
/// A soft closed state only means the thread is locked.
104+
///
105+
/// Like soft lock, soft closed is a state where the thread is closed but the user may still has write permission
106+
/// (For example, user is the moderator of current subreddit).
107+
///
108+
/// In this state we shall keep the post functionality as the prerequisites are still satisfied, but give a tip that
109+
/// the thread is closed and maybe it's not proper to post again.
110+
final bool threadSoftClosed;
111+
102112
/// Indicating current thread is closed or not.
103113
final bool threadClosed;
104114

lib/features/thread/v1/view/thread_page.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_bloc/flutter_bloc.dart';
33
import 'package:go_router/go_router.dart';
44
import 'package:tsdm_client/constants/constants.dart';
5+
import 'package:tsdm_client/constants/layout.dart';
56
import 'package:tsdm_client/constants/url.dart';
67
import 'package:tsdm_client/extensions/build_context.dart';
78
import 'package:tsdm_client/extensions/string.dart';
@@ -135,6 +136,8 @@ class _ThreadPageState extends State<ThreadPage> with SingleTickerProviderStateM
135136
}
136137

137138
Widget _buildContent(BuildContext context, ThreadState state) {
139+
final tr = context.t.threadPage;
140+
138141
return Column(
139142
children: [
140143
Expanded(
@@ -154,6 +157,25 @@ class _ThreadPageState extends State<ThreadPage> with SingleTickerProviderStateM
154157
latestModAct: state.latestModAct,
155158
),
156159
),
160+
if (state.threadSoftClosed && !state.threadClosed)
161+
ColoredBox(
162+
color: Theme.of(context).colorScheme.secondaryContainer,
163+
child: Padding(
164+
padding: edgeInsetsL12T4R12B4,
165+
child: Row(
166+
children: [
167+
Icon(Icons.lock_outline, size: 16, color: Theme.of(context).colorScheme.onSecondaryContainer),
168+
sizedBoxW4H4,
169+
Expanded(
170+
child: Text(
171+
tr.softCloseHint,
172+
style: TextStyle(color: Theme.of(context).colorScheme.onSecondaryContainer),
173+
),
174+
),
175+
],
176+
),
177+
),
178+
),
157179
_buildReplyBar(context, state),
158180
],
159181
);

lib/i18n/en.i18n.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,8 @@
365365
"draft": "Draft",
366366
"operationLog": {
367367
"title": "Operation Log"
368-
}
368+
},
369+
"softCloseHint": "Thread is closed, be attention before posting"
369370
},
370371
"noticePage": {
371372
"title": "Notifications",

lib/i18n/zh-CN.i18n.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,8 @@
365365
"draft": "草稿",
366366
"operationLog": {
367367
"title": "操作记录"
368-
}
368+
},
369+
"softCloseHint": "帖子已关闭,回复前请注意"
369370
},
370371
"noticePage": {
371372
"title": "通知",

lib/i18n/zh-TW.i18n.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,8 @@
365365
"draft": "草稿",
366366
"operationLog": {
367367
"title": "操作記錄"
368-
}
368+
},
369+
"softCloseHint": "帖子已关闭,回复前请注意"
369370
},
370371
"noticePage": {
371372
"title": "通知",

0 commit comments

Comments
 (0)