feat: 万花筒专区可设置门的通关状态
通关态与前两个动作一样落在 userKaleidxScopeList 同一行,是 isClear。 用三态下拉(不改动 / 已通关 / 未通关)而不是勾选框,因为通关可以往回改。 - 标记通关时补 clearDate,格式按客户端 TimeManager.GetDateString 的 yyyy-MM-dd HH:mm:ss.f;已有首次通关日期不覆盖,撤销通关时一起清空 - 上行是整行替换,只叠加要改的位,playCount / best 成绩 / 日期保持原值 - 通关态只在 found && key 的前提下才显示得出来,缺钥匙时给一条短提示 - 校验放宽:三个动作任选其一即可执行
This commit is contained in:
1 parent
44c4a1daae
commit
6438fb2171
7 files changed
+241
-27
No files matched your search
@@ -12,10 +12,10 @@ import '../widgets/app_notice.dart';
|
||||
import '../widgets/cooldown_mixin.dart';
|
||||
import '../widgets/step_progress.dart';
|
||||
|
||||
/// 万花筒专区:发现新的宿命之门 + 获取门的钥匙。
|
||||
/// 万花筒专区:发现新的宿命之门、获取门的钥匙、设置门的通关状态。
|
||||
///
|
||||
/// 两个动作落在 `upsertUserAll.userKaleidxScopeList` 同一行的两个布尔位上
|
||||
/// (`isGateFound` / `isKeyFound`)。钥匙不走 `userItemList`:
|
||||
/// 三个动作都落在 `upsertUserAll.userKaleidxScopeList` 同一行的三个布尔位上
|
||||
/// (`isGateFound` / `isKeyFound` / `isClear`)。钥匙不走 `userItemList`:
|
||||
/// `ExportUserItems` 从不输出 itemKind 15,下行也没有读它的路径。
|
||||
class KaleidxScopePage extends StatefulWidget {
|
||||
final int userId;
|
||||
@@ -37,6 +37,9 @@ class KaleidxScopePage extends StatefulWidget {
|
||||
State<KaleidxScopePage> createState() => _KaleidxScopePageState();
|
||||
}
|
||||
|
||||
/// 通关态可以往两个方向改,所以用三态而不是又一个勾选框。
|
||||
enum _ClearChoice { keep, cleared, uncleared }
|
||||
|
||||
class _KaleidxScopePageState extends State<KaleidxScopePage>
|
||||
with CooldownMixin<KaleidxScopePage> {
|
||||
final _gateIdController = TextEditingController();
|
||||
@@ -44,6 +47,7 @@ class _KaleidxScopePageState extends State<KaleidxScopePage>
|
||||
|
||||
bool _discover = true;
|
||||
bool _giveKey = false;
|
||||
_ClearChoice _clearChoice = _ClearChoice.keep;
|
||||
|
||||
Map<String, Map<String, dynamic>> _userAllData = const {};
|
||||
List<UserKaleidxScopeBean> _serverScopes = const [];
|
||||
@@ -88,12 +92,30 @@ class _KaleidxScopePageState extends State<KaleidxScopePage>
|
||||
return null;
|
||||
}
|
||||
|
||||
/// 整行替换,所以已存在的门必须拿服务器原行做底,只改那两个布尔位。
|
||||
bool? get _targetClear => switch (_clearChoice) {
|
||||
_ClearChoice.keep => null,
|
||||
_ClearChoice.cleared => true,
|
||||
_ClearChoice.uncleared => false,
|
||||
};
|
||||
|
||||
/// 整行替换,所以已存在的门必须拿服务器原行做底,只改要改的位。
|
||||
List<UserKaleidxScopeBean> _buildRows() {
|
||||
final clear = _targetClear;
|
||||
final timestamp = UserAllPayloadBuilder.nowTimestamp();
|
||||
return [
|
||||
for (final id in _pending)
|
||||
_serverRow(id)?.withActions(discover: _discover, giveKey: _giveKey) ??
|
||||
UserKaleidxScopeBean.discovered(id, giveKey: _giveKey),
|
||||
_serverRow(id)?.withActions(
|
||||
discover: _discover,
|
||||
giveKey: _giveKey,
|
||||
clear: clear,
|
||||
timestamp: timestamp,
|
||||
) ??
|
||||
UserKaleidxScopeBean.discovered(
|
||||
id,
|
||||
giveKey: _giveKey,
|
||||
clear: clear,
|
||||
timestamp: timestamp,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -139,7 +161,7 @@ class _KaleidxScopePageState extends State<KaleidxScopePage>
|
||||
_snack(AppStrings.kaleidxNeedGateId);
|
||||
return;
|
||||
}
|
||||
if (!_discover && !_giveKey) {
|
||||
if (!_discover && !_giveKey && _clearChoice == _ClearChoice.keep) {
|
||||
_snack(AppStrings.kaleidxNeedAction);
|
||||
return;
|
||||
}
|
||||
@@ -366,10 +388,42 @@ class _KaleidxScopePageState extends State<KaleidxScopePage>
|
||||
enabled: enabled,
|
||||
onChanged: (v) => setState(() => _giveKey = v),
|
||||
),
|
||||
if (_giveKey) ...[
|
||||
const SizedBox(height: 4),
|
||||
const SizedBox(height: 10),
|
||||
DropdownButtonFormField<_ClearChoice>(
|
||||
initialValue: _clearChoice,
|
||||
decoration: InputDecoration(
|
||||
labelText: AppStrings.kaleidxClearLabel,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
contentPadding: const EdgeInsets.all(14),
|
||||
),
|
||||
items: const [
|
||||
DropdownMenuItem(
|
||||
value: _ClearChoice.keep,
|
||||
child: Text(AppStrings.kaleidxClearKeep),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: _ClearChoice.cleared,
|
||||
child: Text(AppStrings.kaleidxClearCleared),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: _ClearChoice.uncleared,
|
||||
child: Text(AppStrings.kaleidxClearUncleared),
|
||||
),
|
||||
],
|
||||
onChanged: enabled
|
||||
? (v) => setState(
|
||||
() => _clearChoice = v ?? _ClearChoice.keep,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
if (_giveKey || _clearChoice == _ClearChoice.cleared) ...[
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
AppStrings.kaleidxKeyNeedsGate,
|
||||
_giveKey
|
||||
? AppStrings.kaleidxKeyNeedsGate
|
||||
: AppStrings.kaleidxClearNeedsKey,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
height: 1.5,
|
||||
|
||||
Reference in new issue
Block a user