feat(state): 迁移 friends/suppliesState/clanUserInfo/battleInviteState/partner/userRenameState
This commit is contained in:
1 parent
af005ab019
commit
0183f191d3
13 files changed
+1149
-54
No files matched your search
@@ -143,7 +143,7 @@
|
||||
`names/root_wiring.json` + `TankiOffline/.../App/State/RootState.kt`、`RootWiring.kt`。
|
||||
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
|
||||
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
|
||||
- 已迁移切片 **53/89**:
|
||||
- 已迁移切片 **59/89**:
|
||||
- `inviteState` → `aD` / `pD.er5`(`InviteReducer.kt`)
|
||||
- `loginByPassword` → `gD` / `MD.cr6`(`LoginReducer.kt`,含 `SetLogin`/`SetPassword` 把 status 打回 `NONE` 的原语义)
|
||||
- `twitchState` → `g9` / `y9.gta`(`TwitchReducer.kt`;`SetAccount` 是 Twitch 账号,不是 UID)
|
||||
@@ -309,12 +309,33 @@
|
||||
新增 `ReportKind { BATTLE_NAME, LOBBY_CHAT_MESSAGE, BATTLE_CHAT_MESSAGE }` 与 `ReportEntry(kind, targetId, expireTime)`;
|
||||
三类举报都追加一条记录、有效期 +1 天。原 reducer 还把列表写回 localStorage 的 `SENT_REPORTS`,
|
||||
属 storage port 职责,纯 reducer 不做 IO(Init 保留现有列表)。
|
||||
- `friends` → `KD` / `NL().cr9`(`FriendsReducer.kt`):8 字段,13 个分支。
|
||||
新增 `FriendSearchState { HIDDEN, SEARCHING, FOUND, NOT_FOUND }`(对应 `YD()`);
|
||||
四个集合分别做集合 / 单值增删;`SetValidationStatus` 原判据是 `status.equals(pk())`,
|
||||
`pk()` 是校验通过单例,离线重建按「非空即 FOUND」收口。
|
||||
`AddUsersToNewAccepted` 与 clan 切片的同名动作合并成一个类(`clanId, userIds`),friends 只读 `userIds`。
|
||||
- `suppliesState` → `wE` / `$t.fq9`(`SuppliesStateReducer.kt`):1 字段 `Map`,
|
||||
`qE`→`SetSupplyCount(supplyId, count)` 写一个键值。
|
||||
- `clanUserInfo` → `hO` / `de.gr1`(`ClanUserInfoReducer.kt`):1 字段 `Map`,
|
||||
`Loaded(users)` 是**合并**(`jm` = copy + `putAll`),不是覆盖。
|
||||
- `battleInviteState` → `att` / `Ttt().nth`(`BattleInviteStateReducer.kt`):3 字段,6 个分支。
|
||||
`mtt` 的 `toString` 名 `InviteToBattle` 与另一个只有 `battleId` 的同名动作冲突,
|
||||
改用 `AddInvitedUser(receiverId)`;`dtt`→`ClearSelectedForInvite`。
|
||||
- `partner` → `UJ` / `(inline@partner)`(`PartnerReducer.kt`):15 字段,11 个内联分支。
|
||||
`_Z`→`UpdatePartnerInviteAction`、`tZ`/`JJ`→`MarkAccountLinked`/`MarkAccountNotLinked`、
|
||||
`hZ`→`SetPartnerItemEnabled`(`Km` = Pair,写 `itemsEnabledForPartner`);
|
||||
`loginForBindingStatus` 复用登录切片的 `ByPasswordStatus`。
|
||||
- `userRenameState` → `O8` / `Rf.pte`(`UserRenameReducer.kt`):10 字段,11 个分支。
|
||||
新增 `RenameUidState { EMPTY, SHORT, RESERVED, FORBIDDEN, NOT_VALID, FREE }`(对应 `D8()`);
|
||||
`SetValidationStatus` 按 ordinal 映射输入状态(EMPTY→SHORT、SHORT→NOT_VALID、RESERVED→RESERVED、
|
||||
FORBIDDEN/NOT_VALID→FORBIDDEN、FREE→FREE)并把 `isResponseDelivered` 置 true;
|
||||
`G8`→`ResetRenameDialog` 复位弹窗字段但保留 rubies / hash / email。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 52 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **36 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 53/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **627 项全绿**,含 89 槽位完整性、52 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 58 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **30 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 59/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **685 项全绿**,含 89 槽位完整性、58 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -331,6 +352,8 @@
|
||||
captchaState 的 5 个、modalScreen 的 1 个、droppableGold 的 2 个、creatorTagState 的 1 个、
|
||||
battleTutorial 的 2 个、spectator 的 4 个、antiAddiction 的 3 个、moderation 的 13 个、
|
||||
迁移 / 注册共用的 10 个(`Mit`…`_rt`)匿名类 / 单例同样按效果定名并登记。
|
||||
friends 的 2 个、suppliesState 的 1 个、battleInviteState 的 2 个、partner 的 4 个、
|
||||
userRenameState 的 5 个也已登记(其中 `mtt` 因同名类冲突改名为 `AddInvitedUser`)。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
+113
-23
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T07:23:39.141Z",
|
||||
"generatedAt": "2026-10-24T07:48:13.464Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -59,7 +59,13 @@
|
||||
"moderation",
|
||||
"migrationState",
|
||||
"register",
|
||||
"userReportsState"
|
||||
"userReportsState",
|
||||
"friends",
|
||||
"suppliesState",
|
||||
"clanUserInfo",
|
||||
"battleInviteState",
|
||||
"partner",
|
||||
"userRenameState"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -998,6 +1004,90 @@
|
||||
"Name": "ResetAuthenticationForm",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "login=\"\"、两个状态复位(两个切片都读)"
|
||||
},
|
||||
{
|
||||
"Local": "_L",
|
||||
"Name": "SetContextMenuUser",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "contextMenuUser=参数(`n.er7(cd, t.er9_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "hL",
|
||||
"Name": "ClearContextMenuUser",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "contextMenuUser=null(`n.er7(cd, null)`)"
|
||||
},
|
||||
{
|
||||
"Local": "qE",
|
||||
"Name": "SetSupplyCount",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "count 写键值(`n.bq9(cg(n.aq9_1, Vd(t.gq9_1, t.hq9_1)))`)"
|
||||
},
|
||||
{
|
||||
"Local": "mtt",
|
||||
"Name": "AddInvitedUser",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "invitedUsers += receiverId(原名 InviteToBattle,与另一个只有 battleId 的同名动作冲突,改名 AddInvitedUser)"
|
||||
},
|
||||
{
|
||||
"Local": "dtt",
|
||||
"Name": "ClearSelectedForInvite",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "selectedForInvite = emptySet()(`Yg()`)"
|
||||
},
|
||||
{
|
||||
"Local": "_Z",
|
||||
"Name": "UpdatePartnerInviteAction",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inviteAction=参数(`n.osf(…, t.osg_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "tZ",
|
||||
"Name": "MarkAccountLinked",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isAccountAlreadyLinked=true(`n.osf(…, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "JJ",
|
||||
"Name": "MarkAccountNotLinked",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isAccountAlreadyLinked=false(`n.osf(…, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "hZ",
|
||||
"Name": "SetPartnerItemEnabled",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "itemsEnabledForPartner 写键值(`cg(n.ksf_1, new Km(t.msg_1, t.nsg_1))`)"
|
||||
},
|
||||
{
|
||||
"Local": "B8",
|
||||
"Name": "MarkFreeRenameAvailable",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isFreeRenameAvailable=true(`n.cte(!0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "F8",
|
||||
"Name": "MarkRenameSucceeded",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isFreeRenameAvailable=false、renameSuccessful=true(`n.cte(!1, cd, cd, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "U8",
|
||||
"Name": "MarkRenameFailed",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "renameSuccessful=false(`n.cte(cd, cd, cd, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "G8",
|
||||
"Name": "ResetRenameDialog",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "复位 shopItemId / uidInputState / renameSuccessful / 两个 response 位(`n.cte(cd, null, n6(), null, cd, !1, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "Q8",
|
||||
"Name": "HideLinkErrorWarning",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "showLinkErrorWarning=false(`n.cte(…, !1)`)"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -1679,22 +1769,22 @@
|
||||
"Reducer": "NL().cr9",
|
||||
"Delegate": "NL().cr9(t, n.ypv_1)",
|
||||
"Actions": [
|
||||
"?_L",
|
||||
"?hL",
|
||||
"AddUsersToAccepted",
|
||||
"AddUsersToIncoming",
|
||||
"AddUsersToNewAccepted",
|
||||
"AddUsersToNewIncoming",
|
||||
"ChangeFriendAddFindState",
|
||||
"ClearContextMenuUser",
|
||||
"RemoveUserFromAccepted",
|
||||
"RemoveUserFromIncoming",
|
||||
"RemoveUserFromNewAccepted",
|
||||
"RemoveUsersFromNewIncoming",
|
||||
"SetContextMenuUser",
|
||||
"SetLimits",
|
||||
"SetValidationStatus"
|
||||
],
|
||||
"Default": "new KD()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "remoteUserDataStorage",
|
||||
@@ -1892,10 +1982,10 @@
|
||||
"Reducer": "$t.fq9",
|
||||
"Delegate": "$t.fq9(t, n.ipw_1)",
|
||||
"Actions": [
|
||||
"?qE"
|
||||
"SetSupplyCount"
|
||||
],
|
||||
"Default": "new wE()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "matchmakingGroup",
|
||||
@@ -2064,7 +2154,7 @@
|
||||
"Loaded"
|
||||
],
|
||||
"Default": "new hO()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "tankActionsLogState",
|
||||
@@ -2253,15 +2343,15 @@
|
||||
"Reducer": "Ttt().nth",
|
||||
"Delegate": "Ttt().nth(t, n.cpx_1)",
|
||||
"Actions": [
|
||||
"?dtt",
|
||||
"AddInvitedUser",
|
||||
"ClearSelectedForInvite",
|
||||
"EnableSetBattleInviteNotifications",
|
||||
"InvitationResponse",
|
||||
"InviteToBattle",
|
||||
"RemoveUserFromInvited",
|
||||
"SelectUserToInvite"
|
||||
],
|
||||
"Default": "new att()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "keyboardSettings",
|
||||
@@ -2340,20 +2430,20 @@
|
||||
"Reducer": "(inline@partner)",
|
||||
"Delegate": "(function (t, n) { var i; if (t instanceof VJ) i = n.osf(t.rsf_1, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.ssf_1); else if (t instanceof nZ) { var r = t.bsg_1, e = t.csg_1, u = t.dsg_1, s = t.esg_1, o = t.fsg_1, _ = t.gsg_1; i = n.osf(cd, cd, cd, r, e, u, cd, cd, o, _, s); } else i = t instanceof iZ ? n.osf(cd, t.hsg_1) : t instanceof uZ ? n.osf(cd, cd, t.ksg_1) : t instanceof eZ ? n.osf(cd, cd, cd, cd, cd, cd, cd, t.jsg_1) : t instanceof _Z ? n.osf(cd, cd, cd, cd, cd, cd, t.osg_1) : t instanceof X …",
|
||||
"Actions": [
|
||||
"?JJ",
|
||||
"?_Z",
|
||||
"?hZ",
|
||||
"?tZ",
|
||||
"InitPartnerInviteAction",
|
||||
"InitSocialNetworkParameters",
|
||||
"MarkAccountLinked",
|
||||
"MarkAccountNotLinked",
|
||||
"SetLoginParams",
|
||||
"SetLoginStatusForBinding",
|
||||
"SetPartnerId",
|
||||
"SetPartnerItemEnabled",
|
||||
"SetPartnerParameters",
|
||||
"SetPartnerReady"
|
||||
"SetPartnerReady",
|
||||
"UpdatePartnerInviteAction"
|
||||
],
|
||||
"Default": "new UJ()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "entrance",
|
||||
@@ -2477,12 +2567,12 @@
|
||||
"Reducer": "Rf.pte",
|
||||
"Delegate": "Rf.pte(t, n.qpx_1)",
|
||||
"Actions": [
|
||||
"?B8",
|
||||
"?F8",
|
||||
"?G8",
|
||||
"?Q8",
|
||||
"?U8",
|
||||
"ChangeUidInputState",
|
||||
"HideLinkErrorWarning",
|
||||
"MarkFreeRenameAvailable",
|
||||
"MarkRenameFailed",
|
||||
"MarkRenameSucceeded",
|
||||
"ResetRenameDialog",
|
||||
"ResponseActual",
|
||||
"ResponseDelivered",
|
||||
"SetChangeUidParams",
|
||||
@@ -2490,7 +2580,7 @@
|
||||
"SetValidationStatus"
|
||||
],
|
||||
"Default": "new O8()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "eventGoods",
|
||||
|
||||
@@ -237,6 +237,26 @@ const AnonymousActionNames = new Map([
|
||||
['Git', 'RegisterFailed'],
|
||||
['hrt', 'ResetRegisterStatus'],
|
||||
['_rt', 'ResetAuthenticationForm'],
|
||||
// friends 切片(KD / PL.cr9):_L/hL 没有 toString。
|
||||
['_L', 'SetContextMenuUser'],
|
||||
['hL', 'ClearContextMenuUser'],
|
||||
// suppliesState 切片(wE / yE.fq9):qE 没有 toString。
|
||||
['qE', 'SetSupplyCount'],
|
||||
// battleInviteState 切片(att / Ett.nth):dtt 没有 toString;
|
||||
// mtt 的 toString 名 InviteToBattle 与另一个只有 battleId 的同名动作冲突,这里改用不冲突的类名。
|
||||
['mtt', 'AddInvitedUser'],
|
||||
['dtt', 'ClearSelectedForInvite'],
|
||||
// partner 切片(UJ / 内联 reducer):_Z/tZ/JJ/hZ 没有 toString。
|
||||
['_Z', 'UpdatePartnerInviteAction'],
|
||||
['tZ', 'MarkAccountLinked'],
|
||||
['JJ', 'MarkAccountNotLinked'],
|
||||
['hZ', 'SetPartnerItemEnabled'],
|
||||
// userRenameState 切片(O8 / Rf.pte):B8/F8/U8/G8/Q8 没有 toString。
|
||||
['B8', 'MarkFreeRenameAvailable'],
|
||||
['F8', 'MarkRenameSucceeded'],
|
||||
['U8', 'MarkRenameFailed'],
|
||||
['G8', 'ResetRenameDialog'],
|
||||
['Q8', 'HideLinkErrorWarning'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -678,6 +698,12 @@ const Migrated = {
|
||||
migrationState: { Type: 'MigrationStateSlice', Reduce: 'ReduceMigrationState' },
|
||||
register: { Type: 'RegisterStateSlice', Reduce: 'ReduceRegister' },
|
||||
userReportsState: { Type: 'UserReportsStateSlice', Reduce: 'ReduceUserReports' },
|
||||
friends: { Type: 'FriendsStateSlice', Reduce: 'ReduceFriends' },
|
||||
suppliesState: { Type: 'SuppliesStateSlice', Reduce: 'ReduceSupplies' },
|
||||
clanUserInfo: { Type: 'ClanUserInfoStateSlice', Reduce: 'ReduceClanUserInfo' },
|
||||
battleInviteState: { Type: 'BattleInviteStateSlice', Reduce: 'ReduceBattleInvite' },
|
||||
partner: { Type: 'PartnerStateSlice', Reduce: 'ReducePartner' },
|
||||
userRenameState: { Type: 'UserRenameStateSlice', Reduce: 'ReduceUserRename' },
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -979,6 +1005,40 @@ const AuthAnonymousEffects = {
|
||||
_rt: 'login=""、两个状态复位(两个切片都读)',
|
||||
};
|
||||
|
||||
// friends 切片(KD / PL.cr9):_L/hL 没有 toString。
|
||||
const FriendsAnonymousEffects = {
|
||||
_L: 'contextMenuUser=参数(`n.er7(cd, t.er9_1)`)',
|
||||
hL: 'contextMenuUser=null(`n.er7(cd, null)`)',
|
||||
};
|
||||
|
||||
// suppliesState 切片(wE / yE.fq9):qE 没有 toString。
|
||||
const SuppliesAnonymousEffects = {
|
||||
qE: 'count 写键值(`n.bq9(cg(n.aq9_1, Vd(t.gq9_1, t.hq9_1)))`)',
|
||||
};
|
||||
|
||||
// battleInviteState 切片(att / Ett.nth):dtt 没有 toString;mtt 名字冲突另收口。
|
||||
const BattleInviteAnonymousEffects = {
|
||||
mtt: 'invitedUsers += receiverId(原名 InviteToBattle,与另一个只有 battleId 的同名动作冲突,改名 AddInvitedUser)',
|
||||
dtt: 'selectedForInvite = emptySet()(`Yg()`)',
|
||||
};
|
||||
|
||||
// partner 切片(UJ / 内联 reducer):_Z/tZ/JJ/hZ 没有 toString。
|
||||
const PartnerAnonymousEffects = {
|
||||
_Z: 'inviteAction=参数(`n.osf(…, t.osg_1)`)',
|
||||
tZ: 'isAccountAlreadyLinked=true(`n.osf(…, !0)`)',
|
||||
JJ: 'isAccountAlreadyLinked=false(`n.osf(…, !1)`)',
|
||||
hZ: 'itemsEnabledForPartner 写键值(`cg(n.ksf_1, new Km(t.msg_1, t.nsg_1))`)',
|
||||
};
|
||||
|
||||
// userRenameState 切片(O8 / Rf.pte):B8/F8/U8/G8/Q8 没有 toString。
|
||||
const UserRenameAnonymousEffects = {
|
||||
B8: 'isFreeRenameAvailable=true(`n.cte(!0)`)',
|
||||
F8: 'isFreeRenameAvailable=false、renameSuccessful=true(`n.cte(!1, cd, cd, !0)`)',
|
||||
U8: 'renameSuccessful=false(`n.cte(cd, cd, cd, !1)`)',
|
||||
G8: '复位 shopItemId / uidInputState / renameSuccessful / 两个 response 位(`n.cte(cd, null, n6(), null, cd, !1, !1)`)',
|
||||
Q8: 'showLinkErrorWarning=false(`n.cte(…, !1)`)',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(P, 'names', 'root_wiring.json'),
|
||||
JSON.stringify(
|
||||
@@ -1175,6 +1235,36 @@ fs.writeFileSync(
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(FriendsAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(SuppliesAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(BattleInviteAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(PartnerAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(UserRenameAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
],
|
||||
Markers: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// BattleInviteStateReducer.kt —— 战斗邀请切片(对应 module_10032 的 att 状态 + Ett.nth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 att:3 个字段,toString 名 "BattleInviteState(…)"。
|
||||
// 默认:isEnabled=true、invitedUsers=emptySet()、selectedForInvite=emptySet()。
|
||||
// 根委派:`Ttt().nth(t, n.cpx_1)`。
|
||||
// reducer(6 个实例臂):
|
||||
// mtt(InviteToBattle) → invitedUsers += receiverId
|
||||
// ytt(InvitationResponse) → invitedUsers -= userId
|
||||
// wtt(SelectUserToInvite) → selectedForInvite += userId
|
||||
// ptt(RemoveUserFromInvited) → selectedForInvite -= userId
|
||||
// dtt(无 toString) → selectedForInvite = emptySet()
|
||||
// ftt(EnableSetBattleInviteNotifications)→ isEnabled
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.EnableSetBattleInviteNotifications
|
||||
import App.State.InvitationResponse
|
||||
import App.State.RemoveUserFromInvited
|
||||
import App.State.SelectUserToInvite
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `mtt`(`InviteToBattle`):把被邀请者加入已邀请集合。
|
||||
* 生成物里的 `InviteToBattle` 只保留了另一个同名的 `battleId` 动作,缺 `receiverId`,
|
||||
* 因此这里单独收口成 `AddInvitedUser(userId)`。 */
|
||||
data class AddInvitedUser(val userId: Any?)
|
||||
|
||||
/** 原 `dtt`:清空待邀请列表。 */
|
||||
object ClearSelectedForInvite
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class BattleInviteStateSlice(
|
||||
val IsEnabled: Boolean = true,
|
||||
val InvitedUsers: Set<Any?> = emptySet(),
|
||||
val SelectedForInvite: Set<Any?> = emptySet(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceBattleInvite(
|
||||
State0: BattleInviteStateSlice,
|
||||
Action: Any,
|
||||
): BattleInviteStateSlice = when (Action) {
|
||||
is AddInvitedUser ->
|
||||
State0.copy(InvitedUsers = State0.InvitedUsers + Action.userId)
|
||||
is InvitationResponse ->
|
||||
State0.copy(InvitedUsers = State0.InvitedUsers - Action.userId)
|
||||
is SelectUserToInvite ->
|
||||
State0.copy(SelectedForInvite = State0.SelectedForInvite + Action.userId)
|
||||
is RemoveUserFromInvited ->
|
||||
State0.copy(SelectedForInvite = State0.SelectedForInvite - Action.userId)
|
||||
is ClearSelectedForInvite -> State0.copy(SelectedForInvite = emptySet())
|
||||
is EnableSetBattleInviteNotifications -> State0.copy(IsEnabled = Action.isEnabled)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// ClanUserInfoReducer.kt —— 战队成员信息切片(对应 module_10032 的 hO 状态 + cO.gr1)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 hO:1 个字段,toString 名 "ClanUserInfo(users=…)"。
|
||||
// 默认:users = ag() = emptyMap()。
|
||||
// 根委派:`de.gr1(t, n.opw_1)`。
|
||||
// reducer:`t instanceof aO ? n.dr1(jm(n.cr1_1, t.fr1_1)) : n`
|
||||
// —— `jm` = Map.copy + putAll(`i3` 是 putAll),即把动作里的用户表合并进来。
|
||||
// 动作 `aO` = Loaded(users)。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.Loaded
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class ClanUserInfoStateSlice(
|
||||
val Users: Map<Any?, Any?> = emptyMap(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceClanUserInfo(
|
||||
State0: ClanUserInfoStateSlice,
|
||||
Action: Any,
|
||||
): ClanUserInfoStateSlice = when (Action) {
|
||||
is Loaded -> {
|
||||
val Incoming = Action.users as? Map<Any?, Any?> ?: emptyMap()
|
||||
State0.copy(Users = State0.Users + Incoming)
|
||||
}
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// FriendsReducer.kt —— 好友切片(对应 module_10032 的 KD 状态 + PL.cr9)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 KD:8 个字段,toString 名 "FriendsState(…)"。
|
||||
// 默认:userSearchState=HIDDEN、contextMenuUser=null、两个 limit=0、四个集合 emptySet()。
|
||||
// 根委派:`NL().cr9(t, n.ypv_1)`。
|
||||
// reducer(13 个实例臂):
|
||||
// uL(ChangeFriendAddFindState)→ userSearchState
|
||||
// _L(无 toString) → contextMenuUser = 参数
|
||||
// hL(无 toString) → contextMenuUser = null
|
||||
// aL(SetLimits) → acceptedLimit / incomingLimit
|
||||
// cL / pL → accepted ∓
|
||||
// lL / vL → newAccepted ∓
|
||||
// dL / zL → incoming ∓
|
||||
// gL / kL → newIncoming ∓
|
||||
// U9(SetValidationStatus) → userSearchState = FOUND / NOT_FOUND
|
||||
//
|
||||
// 枚举直接对应源码 `YD()`:HIDDEN / SEARCHING / FOUND / NOT_FOUND。
|
||||
// 原判据是 `status.equals(pk())`,`pk()` 是校验通过的单例(`new tJ()`);
|
||||
// 离线重建没有这个单例的 Kotlin 值,这里按「传了非空状态即视为找到」收口。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.AddUsersToAccepted
|
||||
import App.State.AddUsersToIncoming
|
||||
import App.State.AddUsersToNewAccepted
|
||||
import App.State.AddUsersToNewIncoming
|
||||
import App.State.ChangeFriendAddFindState
|
||||
import App.State.RemoveUserFromAccepted
|
||||
import App.State.RemoveUserFromIncoming
|
||||
import App.State.RemoveUserFromNewAccepted
|
||||
import App.State.RemoveUsersFromNewIncoming
|
||||
import App.State.SetLimits
|
||||
import App.State.SetValidationStatus
|
||||
|
||||
/* ------------------------------------------------------------------ 枚举 */
|
||||
|
||||
enum class FriendSearchState {
|
||||
HIDDEN,
|
||||
SEARCHING,
|
||||
FOUND,
|
||||
NOT_FOUND,
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `_L`:打开某个好友的右键菜单。 */
|
||||
data class SetContextMenuUser(val user: Any?)
|
||||
|
||||
/** 原 `hL`:关闭右键菜单。 */
|
||||
object ClearContextMenuUser
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class FriendsStateSlice(
|
||||
val UserSearchState: FriendSearchState = FriendSearchState.HIDDEN,
|
||||
val ContextMenuUser: Any? = null,
|
||||
val AcceptedLimit: Int = 0,
|
||||
val IncomingLimit: Int = 0,
|
||||
val Accepted: Set<Any?> = emptySet(),
|
||||
val NewAccepted: Set<Any?> = emptySet(),
|
||||
val Incoming: Set<Any?> = emptySet(),
|
||||
val NewIncoming: Set<Any?> = emptySet(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
/** 原 `Zg`:集合 += 集合 / 单值。 */
|
||||
private fun Plus(Target: Set<Any?>, Value: Any?): Set<Any?> =
|
||||
if (Value is Iterable<*>) Target + Value.toSet() else Target + Value
|
||||
|
||||
/** 原 `Qg`:集合 -= 集合 / 单值。 */
|
||||
private fun Minus(Target: Set<Any?>, Value: Any?): Set<Any?> =
|
||||
if (Value is Iterable<*>) Target - Value.toSet() else Target - Value
|
||||
|
||||
fun ReduceFriends(
|
||||
State0: FriendsStateSlice,
|
||||
Action: Any,
|
||||
): FriendsStateSlice = when (Action) {
|
||||
is ChangeFriendAddFindState ->
|
||||
State0.copy(UserSearchState = Action.state as FriendSearchState)
|
||||
is SetContextMenuUser -> State0.copy(ContextMenuUser = Action.user)
|
||||
is ClearContextMenuUser -> State0.copy(ContextMenuUser = null)
|
||||
is SetLimits -> State0.copy(
|
||||
AcceptedLimit = Action.acceptedLimit,
|
||||
IncomingLimit = Action.incomingLimit,
|
||||
)
|
||||
is AddUsersToAccepted -> State0.copy(Accepted = Plus(State0.Accepted, Action.usersId))
|
||||
is RemoveUserFromAccepted -> State0.copy(Accepted = Minus(State0.Accepted, Action.userId))
|
||||
// 生成物里 `AddUsersToNewAccepted` 与 clan 切片的同名动作合并成了一个类
|
||||
// (`clanId, userIds`),friends 只读 `userIds`。
|
||||
is AddUsersToNewAccepted ->
|
||||
State0.copy(NewAccepted = Plus(State0.NewAccepted, Action.userIds))
|
||||
is RemoveUserFromNewAccepted ->
|
||||
State0.copy(NewAccepted = Minus(State0.NewAccepted, Action.userId))
|
||||
is AddUsersToIncoming -> State0.copy(Incoming = Plus(State0.Incoming, Action.usersId))
|
||||
is RemoveUserFromIncoming -> State0.copy(Incoming = Minus(State0.Incoming, Action.userId))
|
||||
is AddUsersToNewIncoming ->
|
||||
State0.copy(NewIncoming = Plus(State0.NewIncoming, Action.usersId))
|
||||
is RemoveUsersFromNewIncoming ->
|
||||
State0.copy(NewIncoming = Minus(State0.NewIncoming, Action.usersId))
|
||||
is SetValidationStatus -> State0.copy(
|
||||
UserSearchState =
|
||||
if (Action.status == null) FriendSearchState.NOT_FOUND else FriendSearchState.FOUND,
|
||||
)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// PartnerReducer.kt —— 合作方(partner)切片(对应 module_10032 的 UJ 状态 + 内联 reducer)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 UJ:15 个字段,toString 名 "PartnerState(…)";copy 是 osf(15 字段 + 回调)。
|
||||
// 默认:partnerId=null、loginParams=emptyMap()、params=emptyMap()、三个能力位 false、
|
||||
// paymentAction=null、inviteAction=null、canOpenExternalLinks=false、
|
||||
// hasAccountBinding=false、failedRedirectUrl=null、loginForBindingStatus=OD()(NONE)、
|
||||
// isAccountAlreadyLinked=false、itemsEnabledForPartner=emptyMap()、isPartnerReady=false。
|
||||
// 根委派:内联 IIFE,字段 `fpy_1`;委派表记作 `(inline@partner)`,11 个动作。
|
||||
// reducer:
|
||||
// VJ(SetPartnerId) → partnerId + failedRedirectUrl
|
||||
// nZ(InitSocialNetworkParameters)→ 3 个能力位 + canOpenExternalLinks + hasAccountBinding + failedRedirectUrl
|
||||
// iZ(SetLoginParams) → loginParams
|
||||
// uZ(SetPartnerParameters) → params
|
||||
// eZ(InitPartnerInviteAction) → inviteAction
|
||||
// _Z(无 toString) → inviteAction(另一个派发点)
|
||||
// XJ(SetLoginStatusForBinding) → loginForBindingStatus(复用登录切片的 ByPasswordStatus)
|
||||
// tZ / JJ(无 toString) → isAccountAlreadyLinked = true / false
|
||||
// hZ(无 toString) → itemsEnabledForPartner 写一个键值(`Km` = Pair)
|
||||
// rZ(SetPartnerReady) → isPartnerReady
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.InitPartnerInviteAction
|
||||
import App.State.InitSocialNetworkParameters
|
||||
import App.State.SetLoginParams
|
||||
import App.State.SetLoginStatusForBinding
|
||||
import App.State.SetPartnerId
|
||||
import App.State.SetPartnerParameters
|
||||
import App.State.SetPartnerReady
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `_Z`:更新邀请动作(与 InitPartnerInviteAction 同字段,另一个派发点)。 */
|
||||
data class UpdatePartnerInviteAction(val action: Any?)
|
||||
|
||||
/** 原 `tZ`:标记账号已绑定。 */
|
||||
object MarkAccountLinked
|
||||
|
||||
/** 原 `JJ`:标记账号未绑定。 */
|
||||
object MarkAccountNotLinked
|
||||
|
||||
/** 原 `hZ`:写某个合作方物品的启用状态。 */
|
||||
data class SetPartnerItemEnabled(val itemId: Any?, val enabled: Boolean)
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class PartnerStateSlice(
|
||||
val PartnerId: Any? = null,
|
||||
val LoginParams: Map<Any?, Any?> = emptyMap(),
|
||||
val Params: Map<Any?, Any?> = emptyMap(),
|
||||
val HasOwnPaymentSystem: Boolean = false,
|
||||
val HasSocialFunction: Boolean = false,
|
||||
val HasClientPaymentAction: Boolean = false,
|
||||
val PaymentAction: Any? = null,
|
||||
val InviteAction: Any? = null,
|
||||
val CanOpenExternalLinks: Boolean = false,
|
||||
val HasAccountBinding: Boolean = false,
|
||||
val FailedRedirectUrl: Any? = null,
|
||||
val LoginForBindingStatus: ByPasswordStatus = ByPasswordStatus.NONE,
|
||||
val IsAccountAlreadyLinked: Boolean = false,
|
||||
val ItemsEnabledForPartner: Map<Any?, Any?> = emptyMap(),
|
||||
val IsPartnerReady: Boolean = false,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun AsMap(Value: Any?): Map<Any?, Any?> =
|
||||
Value as? Map<Any?, Any?> ?: emptyMap()
|
||||
|
||||
fun ReducePartner(
|
||||
State0: PartnerStateSlice,
|
||||
Action: Any,
|
||||
): PartnerStateSlice = when (Action) {
|
||||
is SetPartnerId -> State0.copy(
|
||||
PartnerId = Action.partnerId,
|
||||
FailedRedirectUrl = Action.failedRedirectUrl,
|
||||
)
|
||||
is InitSocialNetworkParameters -> State0.copy(
|
||||
HasOwnPaymentSystem = Action.hasOwnPaymentSystem,
|
||||
HasSocialFunction = Action.hasSocialFunction,
|
||||
HasClientPaymentAction = Action.hasClientPaymentAction,
|
||||
CanOpenExternalLinks = Action.canOpenExternalLinks,
|
||||
HasAccountBinding = Action.hasAccountBinding,
|
||||
FailedRedirectUrl = Action.failedRedirectUrl,
|
||||
)
|
||||
is SetLoginParams -> State0.copy(LoginParams = AsMap(Action.params))
|
||||
is SetPartnerParameters -> State0.copy(Params = AsMap(Action.params))
|
||||
is InitPartnerInviteAction -> State0.copy(InviteAction = Action.action)
|
||||
is UpdatePartnerInviteAction -> State0.copy(InviteAction = Action.action)
|
||||
is SetLoginStatusForBinding ->
|
||||
State0.copy(LoginForBindingStatus = Action.status as ByPasswordStatus)
|
||||
is MarkAccountLinked -> State0.copy(IsAccountAlreadyLinked = true)
|
||||
is MarkAccountNotLinked -> State0.copy(IsAccountAlreadyLinked = false)
|
||||
is SetPartnerItemEnabled -> State0.copy(
|
||||
ItemsEnabledForPartner =
|
||||
State0.ItemsEnabledForPartner + (Action.itemId to Action.enabled),
|
||||
)
|
||||
is SetPartnerReady -> State0.copy(IsPartnerReady = Action.isReady)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SuppliesStateReducer.kt —— 补给计数切片(对应 module_10032 的 wE 状态 + yE.fq9)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 wE:1 个字段,toString 名 "SuppliesState(count=…)"。
|
||||
// 默认:count = ag() = emptyMap()。
|
||||
// 根委派:`$t.fq9(t, n.ipw_1)`。
|
||||
// reducer:`t instanceof qE ? n.bq9(cg(n.aq9_1, Vd(t.gq9_1, t.hq9_1))) : n`
|
||||
// —— `qE(key, value)` 往 Map 里写一个键值(`cg` = put,`Vd` = Pair)。
|
||||
package App.State.Reducers
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `qE`:写一个补给 id 的剩余次数。 */
|
||||
data class SetSupplyCount(val supplyId: Any?, val count: Any?)
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class SuppliesStateSlice(
|
||||
val Count: Map<Any?, Any?> = emptyMap(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceSupplies(
|
||||
State0: SuppliesStateSlice,
|
||||
Action: Any,
|
||||
): SuppliesStateSlice = when (Action) {
|
||||
is SetSupplyCount ->
|
||||
State0.copy(Count = State0.Count + (Action.supplyId to Action.count))
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
// UserRenameReducer.kt —— 改名切片(对应 module_10032 的 O8 状态 + t6.pte)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 O8:10 个字段,toString 名 "UserRenameState(…)";copy 是 cte(10 字段 + 回调)。
|
||||
// 默认:isFreeRenameAvailable=false、userRenameShopItemId=null、uidInputState=EMPTY、
|
||||
// renameSuccessful=null、rubiesForRename=Int.MAX_VALUE、两个 response 位 false、
|
||||
// changeUidHash=null、email=null、showLinkErrorWarning=true。
|
||||
// 根委派:`Rf.pte(t, n.qpx_1)`。
|
||||
// reducer(11 个实例臂):
|
||||
// H8(ChangeUidInputState)→ uidInputState
|
||||
// B8(无 toString) → isFreeRenameAvailable=true
|
||||
// F8(无 toString) → isFreeRenameAvailable=false、renameSuccessful=true
|
||||
// U8(无 toString) → renameSuccessful=false
|
||||
// U9(SetValidationStatus)→ isResponseDelivered=true;
|
||||
// uidInputState 按校验状态映射
|
||||
// (源码 `switch (status.k3_1)`:EMPTY→SHORT、SHORT→NOT_VALID、
|
||||
// RESERVED→RESERVED、FORBIDDEN/NOT_VALID→FORBIDDEN、FREE→FREE)
|
||||
// V8(SetRubiesForRename) → rubiesForRename
|
||||
// G8(无 toString) → 整片复位(shopItemId=null、uidInputState=EMPTY、renameSuccessful=null、
|
||||
// 两个 response 位 false)
|
||||
// K8(ResponseDelivered) → isResponseDelivered
|
||||
// Y8(ResponseActual) → isResponseActual
|
||||
// X8(SetChangeUidParams) → changeUidHash、email
|
||||
// Q8(无 toString) → showLinkErrorWarning=false
|
||||
//
|
||||
// 枚举 `UidInputState` 直接对应源码 `D8()`:EMPTY / SHORT / RESERVED / FORBIDDEN / NOT_VALID / FREE。
|
||||
// `SetValidationStatus.status` 在原包里是同一枚举;离线重建按该枚举的 ordinal 映射。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.ChangeUidInputState
|
||||
import App.State.ResponseActual
|
||||
import App.State.ResponseDelivered
|
||||
import App.State.SetChangeUidParams
|
||||
import App.State.SetRubiesForRename
|
||||
import App.State.SetValidationStatus
|
||||
|
||||
/* ------------------------------------------------------------------ 枚举 */
|
||||
|
||||
enum class RenameUidState {
|
||||
EMPTY,
|
||||
SHORT,
|
||||
RESERVED,
|
||||
FORBIDDEN,
|
||||
NOT_VALID,
|
||||
FREE,
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `B8`:免费改名可用。 */
|
||||
object MarkFreeRenameAvailable
|
||||
|
||||
/** 原 `F8`:改名成功(同时把免费名额用掉)。 */
|
||||
object MarkRenameSucceeded
|
||||
|
||||
/** 原 `U8`:改名失败。 */
|
||||
object MarkRenameFailed
|
||||
|
||||
/** 原 `G8`:复位改名弹窗(保留 rubiesForRename / email 等外层字段)。 */
|
||||
object ResetRenameDialog
|
||||
|
||||
/** 原 `Q8`:隐藏链接错误提示。 */
|
||||
object HideLinkErrorWarning
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class UserRenameStateSlice(
|
||||
val IsFreeRenameAvailable: Boolean = false,
|
||||
val UserRenameShopItemId: Any? = null,
|
||||
val UidInputState: RenameUidState = RenameUidState.EMPTY,
|
||||
val RenameSuccessful: Any? = null,
|
||||
val RubiesForRename: Int = Int.MAX_VALUE,
|
||||
val IsResponseDelivered: Boolean = false,
|
||||
val IsResponseActual: Boolean = false,
|
||||
val ChangeUidHash: Any? = null,
|
||||
val Email: Any? = null,
|
||||
val ShowLinkErrorWarning: Boolean = true,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
/** 原 `switch (status.k3_1)`:校验状态 → 输入框状态。 */
|
||||
private fun MapValidationStatus(Status: Any?): RenameUidState? =
|
||||
when ((Status as? RenameUidState)?.ordinal) {
|
||||
0 -> RenameUidState.SHORT
|
||||
1 -> RenameUidState.NOT_VALID
|
||||
2 -> RenameUidState.RESERVED
|
||||
3, 4 -> RenameUidState.FORBIDDEN
|
||||
5 -> RenameUidState.FREE
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun ReduceUserRename(
|
||||
State0: UserRenameStateSlice,
|
||||
Action: Any,
|
||||
): UserRenameStateSlice = when (Action) {
|
||||
is ChangeUidInputState ->
|
||||
State0.copy(UidInputState = Action.uidInputState as RenameUidState)
|
||||
is MarkFreeRenameAvailable -> State0.copy(IsFreeRenameAvailable = true)
|
||||
is MarkRenameSucceeded -> State0.copy(
|
||||
IsFreeRenameAvailable = false,
|
||||
RenameSuccessful = true,
|
||||
)
|
||||
is MarkRenameFailed -> State0.copy(RenameSuccessful = false)
|
||||
is SetValidationStatus -> State0.copy(
|
||||
UidInputState = MapValidationStatus(Action.status) ?: State0.UidInputState,
|
||||
IsResponseDelivered = true,
|
||||
)
|
||||
is SetRubiesForRename -> State0.copy(RubiesForRename = Action.rubiesForRename)
|
||||
is ResetRenameDialog -> State0.copy(
|
||||
UserRenameShopItemId = null,
|
||||
UidInputState = RenameUidState.EMPTY,
|
||||
RenameSuccessful = null,
|
||||
IsResponseDelivered = false,
|
||||
IsResponseActual = false,
|
||||
)
|
||||
is ResponseDelivered -> State0.copy(IsResponseDelivered = Action.isDelivered)
|
||||
is ResponseActual -> State0.copy(IsResponseActual = Action.isResponseActual)
|
||||
is SetChangeUidParams -> State0.copy(
|
||||
ChangeUidHash = Action.changeUidHash,
|
||||
Email = Action.email,
|
||||
)
|
||||
is HideLinkErrorWarning -> State0.copy(ShowLinkErrorWarning = false)
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 53 个切片里,52 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 59 个切片里,58 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -55,9 +55,15 @@
|
||||
// migrationState → ReduceMigrationState($it / Uv.rtg,根委派 `Uv.rtg(t, n.ipv_1)`)
|
||||
// register → ReduceRegister(Cit / cp.stg,根委派 `cp.stg(t, n.hpv_1)`)
|
||||
// userReportsState → ReduceUserReports(Zst / qot.zth,根委派 `(null == sd && new qot(), sd).zth(t, n.dpy_1)`)
|
||||
// friends → ReduceFriends(KD / NL().cr9,根委派 `NL().cr9(t, n.ypv_1)`)
|
||||
// suppliesState → ReduceSupplies(wE / $t.fq9,根委派 `$t.fq9(t, n.ipw_1)`)
|
||||
// clanUserInfo → ReduceClanUserInfo(hO / de.gr1,根委派 `de.gr1(t, n.opw_1)`)
|
||||
// battleInviteState → ReduceBattleInvite(att / Ttt().nth,根委派 `Ttt().nth(t, n.cpx_1)`)
|
||||
// partner → ReducePartner(UJ / `(inline@partner)`,根委派内联 IIFE)
|
||||
// userRenameState → ReduceUserRename(O8 / Rf.pte,根委派 `Rf.pte(t, n.qpx_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 36 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 30 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
@@ -67,7 +73,9 @@ import App.State.Reducers.ReduceAnnouncement
|
||||
import App.State.Reducers.ReduceAntiAddiction
|
||||
import App.State.Reducers.ReduceBattleResult
|
||||
import App.State.Reducers.ReduceBattleTutorial
|
||||
import App.State.Reducers.ReduceBattleInvite
|
||||
import App.State.Reducers.ReduceCaptcha
|
||||
import App.State.Reducers.ReduceClanUserInfo
|
||||
import App.State.Reducers.ReduceContextTutorial
|
||||
import App.State.Reducers.ReduceCreatorTag
|
||||
import App.State.Reducers.ReduceDroppableGold
|
||||
@@ -75,6 +83,7 @@ import App.State.Reducers.ReduceEntrance
|
||||
import App.State.Reducers.ReduceEventGoods
|
||||
import App.State.Reducers.ReduceGarage
|
||||
import App.State.Reducers.ReduceGaragePreview
|
||||
import App.State.Reducers.ReduceFriends
|
||||
import App.State.Reducers.ReduceHome
|
||||
import App.State.Reducers.ReduceIcons
|
||||
import App.State.Reducers.ReduceInvite
|
||||
@@ -92,6 +101,7 @@ import App.State.Reducers.ReduceNews
|
||||
import App.State.Reducers.ReduceNotificationByCountry
|
||||
import App.State.Reducers.ReduceNotifications
|
||||
import App.State.Reducers.ReducePasswordChange
|
||||
import App.State.Reducers.ReducePartner
|
||||
import App.State.Reducers.ReduceProBattle
|
||||
import App.State.Reducers.ReducePromoCode
|
||||
import App.State.Reducers.ReducePurchaseDialog
|
||||
@@ -108,11 +118,13 @@ import App.State.Reducers.ReduceSpectator
|
||||
import App.State.Reducers.ReduceSupportUrl
|
||||
import App.State.Reducers.ReduceSettings
|
||||
import App.State.Reducers.ReduceShop
|
||||
import App.State.Reducers.ReduceSupplies
|
||||
import App.State.Reducers.ReduceSystem
|
||||
import App.State.Reducers.ReduceTips
|
||||
import App.State.Reducers.ReduceTwitch
|
||||
import App.State.Reducers.ReduceTwoStepVerification
|
||||
import App.State.Reducers.ReduceUser
|
||||
import App.State.Reducers.ReduceUserRename
|
||||
import App.State.Reducers.ReduceUserReports
|
||||
|
||||
/** 根 reducer:`k6`。 */
|
||||
@@ -180,6 +192,12 @@ object RootReducer {
|
||||
MigrationState = ReduceMigrationState(State0.MigrationState, Action),
|
||||
Register = ReduceRegister(State0.Register, Action),
|
||||
UserReportsState = ReduceUserReports(State0.UserReportsState, Action),
|
||||
Friends = ReduceFriends(State0.Friends, Action),
|
||||
SuppliesState = ReduceSupplies(State0.SuppliesState, Action),
|
||||
ClanUserInfo = ReduceClanUserInfo(State0.ClanUserInfo, Action),
|
||||
BattleInviteState = ReduceBattleInvite(State0.BattleInviteState, Action),
|
||||
Partner = ReducePartner(State0.Partner, Action),
|
||||
UserRenameState = ReduceUserRename(State0.UserRenameState, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,17 @@ import App.State.Reducers.AccountSettingsStateSlice
|
||||
import App.State.Reducers.AnnouncementStateSlice
|
||||
import App.State.Reducers.AntiAddictionStateSlice
|
||||
import App.State.Reducers.AvailabilityByRankStateSlice
|
||||
import App.State.Reducers.BattleInviteStateSlice
|
||||
import App.State.Reducers.BattleResultStateSlice
|
||||
import App.State.Reducers.BattleTutorialStateSlice
|
||||
import App.State.Reducers.CaptchaStateSlice
|
||||
import App.State.Reducers.ClanUserInfoStateSlice
|
||||
import App.State.Reducers.ContextTutorialStateSlice
|
||||
import App.State.Reducers.CreatorTagStateSlice
|
||||
import App.State.Reducers.DroppableGoldStateSlice
|
||||
import App.State.Reducers.EntranceStateSlice
|
||||
import App.State.Reducers.EventGoodsStateSlice
|
||||
import App.State.Reducers.FriendsStateSlice
|
||||
import App.State.Reducers.GarageStateSlice
|
||||
import App.State.Reducers.GaragePreviewStateSlice
|
||||
import App.State.Reducers.HomeStateSlice
|
||||
@@ -32,6 +35,7 @@ import App.State.Reducers.ModerationStateSlice
|
||||
import App.State.Reducers.NewsStateSlice
|
||||
import App.State.Reducers.NotificationByCountryStateSlice
|
||||
import App.State.Reducers.NotificationsStateSlice
|
||||
import App.State.Reducers.PartnerStateSlice
|
||||
import App.State.Reducers.PasswordChangeStateSlice
|
||||
import App.State.Reducers.ProBattleStateSlice
|
||||
import App.State.Reducers.PromoCodeStateSlice
|
||||
@@ -48,12 +52,14 @@ import App.State.Reducers.SecuritySettingsStateSlice
|
||||
import App.State.Reducers.SettingsStateSlice
|
||||
import App.State.Reducers.ShopStateSlice
|
||||
import App.State.Reducers.SpectatorStateSlice
|
||||
import App.State.Reducers.SuppliesStateSlice
|
||||
import App.State.Reducers.SupportUrlStateSlice
|
||||
import App.State.Reducers.SystemStateSlice
|
||||
import App.State.Reducers.TipsStateSlice
|
||||
import App.State.Reducers.TwitchStateSlice
|
||||
import App.State.Reducers.TwoStepVerificationStateSlice
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.UserRenameStateSlice
|
||||
import App.State.Reducers.UserReportsStateSlice
|
||||
|
||||
/**
|
||||
@@ -113,8 +119,8 @@ data class RootState(
|
||||
val LootBoxes: LootBoxesStateSlice = LootBoxesStateSlice(),
|
||||
/** 原 notifications(jJ / B_.ise)。已迁移。 */
|
||||
val Notifications: NotificationsStateSlice = NotificationsStateSlice(),
|
||||
/** 原 friends(KD / NL().cr9)。未迁移:原样透传。 */
|
||||
val Friends: Any? = null,
|
||||
/** 原 friends(KD / NL().cr9)。已迁移。 */
|
||||
val Friends: FriendsStateSlice = FriendsStateSlice(),
|
||||
/** 原 remoteUserDataStorage($Q / vh.isl)。未迁移:原样透传。 */
|
||||
val RemoteUserDataStorage: Any? = null,
|
||||
/** 原 battlesSelect(fA / Mi.vqk)。未迁移:原样透传。 */
|
||||
@@ -133,8 +139,8 @@ data class RootState(
|
||||
val BattleResult: BattleResultStateSlice = BattleResultStateSlice(),
|
||||
/** 原 battleUsers(uP / sr.hqs)。未迁移:原样透传。 */
|
||||
val BattleUsers: Any? = null,
|
||||
/** 原 suppliesState(wE / $t.fq9)。未迁移:原样透传。 */
|
||||
val SuppliesState: Any? = null,
|
||||
/** 原 suppliesState(wE / $t.fq9)。已迁移。 */
|
||||
val SuppliesState: SuppliesStateSlice = SuppliesStateSlice(),
|
||||
/** 原 matchmakingGroup(rW / NW().is0)。未迁移:原样透传。 */
|
||||
val MatchmakingGroup: Any? = null,
|
||||
/** 原 shop(j4 / (inline@shop))。已迁移。 */
|
||||
@@ -145,8 +151,8 @@ data class RootState(
|
||||
val BattleViewState: Any? = null,
|
||||
/** 原 rankUpDialogState(LO / Se.br3)。已迁移。 */
|
||||
val RankUpDialogState: RankUpDialogStateSlice = RankUpDialogStateSlice(),
|
||||
/** 原 clanUserInfo(hO / de.gr1)。未迁移:原样透传。 */
|
||||
val ClanUserInfo: Any? = null,
|
||||
/** 原 clanUserInfo(hO / de.gr1)。已迁移。 */
|
||||
val ClanUserInfo: ClanUserInfoStateSlice = ClanUserInfoStateSlice(),
|
||||
/** 原 tankActionsLogState(vI / wi.gqe)。未迁移:原样透传。 */
|
||||
val TankActionsLogState: Any? = null,
|
||||
/** 原 battleMessage(FE / vT().rqb)。未迁移:原样透传。 */
|
||||
@@ -173,8 +179,8 @@ data class RootState(
|
||||
val SecuritySettings: SecuritySettingsStateSlice = SecuritySettingsStateSlice(),
|
||||
/** 原 purchaseDialogState(CO / je.ur2)。已迁移。 */
|
||||
val PurchaseDialogState: PurchaseDialogStateSlice = PurchaseDialogStateSlice(),
|
||||
/** 原 battleInviteState(att / Ttt().nth)。未迁移:原样透传。 */
|
||||
val BattleInviteState: Any? = null,
|
||||
/** 原 battleInviteState(att / Ttt().nth)。已迁移。 */
|
||||
val BattleInviteState: BattleInviteStateSlice = BattleInviteStateSlice(),
|
||||
/** 原 keyboardSettings(Sut / bw.oth)。未迁移:原样透传。 */
|
||||
val KeyboardSettings: Any? = null,
|
||||
/** 原 touchscreenHudSettings(j7 / N7().xsv)。未迁移:原样透传。 */
|
||||
@@ -185,8 +191,8 @@ data class RootState(
|
||||
val Language: Language = App.State.Language.EN,
|
||||
/** 原 launchParams(? / (pass-through))。已迁移(透传,强类型)。 */
|
||||
val LaunchParams: LaunchParamsStateSlice = emptyMap(),
|
||||
/** 原 partner(UJ / (inline@partner))。未迁移:原样透传。 */
|
||||
val Partner: Any? = null,
|
||||
/** 原 partner(UJ / (inline@partner))。已迁移。 */
|
||||
val Partner: PartnerStateSlice = PartnerStateSlice(),
|
||||
/** 原 entrance(hD / Bv.pth)。已迁移。 */
|
||||
val Entrance: EntranceStateSlice = EntranceStateSlice(),
|
||||
/** 原 antiAddiction(UC / W.iq8)。已迁移。 */
|
||||
@@ -201,8 +207,8 @@ data class RootState(
|
||||
val Announcement: AnnouncementStateSlice = AnnouncementStateSlice(),
|
||||
/** 原 notificationByCountry(gJ / R_.ssd)。已迁移。 */
|
||||
val NotificationByCountry: NotificationByCountryStateSlice = NotificationByCountryStateSlice(),
|
||||
/** 原 userRenameState(O8 / Rf.pte)。未迁移:原样透传。 */
|
||||
val UserRenameState: Any? = null,
|
||||
/** 原 userRenameState(O8 / Rf.pte)。已迁移。 */
|
||||
val UserRenameState: UserRenameStateSlice = UserRenameStateSlice(),
|
||||
/** 原 eventGoods(W7 / Wc.esx)。已迁移。 */
|
||||
val EventGoods: EventGoodsStateSlice = EventGoodsStateSlice(),
|
||||
/** 原 creatorTagState(qO / ze.er2)。已迁移。 */
|
||||
|
||||
@@ -40,7 +40,7 @@ object RootWiring {
|
||||
SliceWiring("accountSettings", "vpv_1", "oet", "Lp.mtg", "Lp.mtg(t, n.vpv_1)", listOf("ClearAccountRemovalTimer", "ClearInputUid", "ResetPasswordFields", "SetAccountRemovalDays", "SetCountry", "SetCurrentPassword", "SetCurrentPasswordMandatory", "SetEmail", "SetEmailConfirmed", "SetNewPassword", "SetPasswordStatus", "SetRepeatNewPassword", "SetUnlockButtonForRenameUid")),
|
||||
SliceWiring("lootBoxes", "wpv_1", "aH", "ws.wrv", "ws.wrv(t, n.wpv_1)", listOf("AddKeys", "ClearRewards", "LootBoxOpeningFailed", "SelectCategory", "SetContainerData", "SetCurrentContainer", "SetGoToGarage", "SetIsAccelerated", "SetIsBlockOpenButtons", "SetIsOpening", "SetIsReopening", "SetIsShopVisited", "SetKeys", "SetPeriodOfGiveLootBox", "SetPossibleRewards", "SetRewards", "SetTimeToGiveLootBox", "ShownRewards")),
|
||||
SliceWiring("notifications", "xpv_1", "jJ", "B_.ise", "B_.ise(t, n.xpv_1)", listOf("AddNotification", "InitNotificationSound", "RemoveFirstNotification", "RemoveNotifications")),
|
||||
SliceWiring("friends", "ypv_1", "KD", "NL().cr9", "NL().cr9(t, n.ypv_1)", listOf("?_L", "?hL", "AddUsersToAccepted", "AddUsersToIncoming", "AddUsersToNewAccepted", "AddUsersToNewIncoming", "ChangeFriendAddFindState", "RemoveUserFromAccepted", "RemoveUserFromIncoming", "RemoveUserFromNewAccepted", "RemoveUsersFromNewIncoming", "SetLimits", "SetValidationStatus")),
|
||||
SliceWiring("friends", "ypv_1", "KD", "NL().cr9", "NL().cr9(t, n.ypv_1)", listOf("AddUsersToAccepted", "AddUsersToIncoming", "AddUsersToNewAccepted", "AddUsersToNewIncoming", "ChangeFriendAddFindState", "ClearContextMenuUser", "RemoveUserFromAccepted", "RemoveUserFromIncoming", "RemoveUserFromNewAccepted", "RemoveUsersFromNewIncoming", "SetContextMenuUser", "SetLimits", "SetValidationStatus")),
|
||||
SliceWiring("remoteUserDataStorage", "zpv_1", "\$Q", "vh.isl", "vh.isl(t, n.zpv_1)", listOf("UpdateClanTags", "UpdateOnlineStatus", "UpdatePremiumStatus", "UpdateRanks", "UpdateUids", "UserEnterBattle", "UserLeaveBattle", "UserLeaveGroup")),
|
||||
SliceWiring("battlesSelect", "apw_1", "fA", "Mi.vqk", "Mi.vqk(t, n.apw_1)", listOf("?dA", "?gA", "AddBattle", "AddUser", "AddUsers", "ChangeName", "EnterToBattleInfo", "InitProBattleRewardLimit", "LimitReached", "RemoveBattle", "RemoveUser", "RoundFinish", "RoundStarted", "SetReEnterProtectBattleId", "SwapTeam", "UpdateFund", "UpdateSuspicion", "UpdateTeamScore", "UpdateUserScore", "UpdateUserSuspicion")),
|
||||
SliceWiring("maps", "bpw_1", "OA", "Oi.sql", "Oi.sql(t, n.bpw_1)", listOf("AddMap")),
|
||||
@@ -50,7 +50,7 @@ object RootWiring {
|
||||
SliceWiring("lobbyLoader", "fpw_1", "KW", "Bs.es1", "Bs.es1(t, n.fpw_1)", listOf("HideLoader", "ShowLoader")),
|
||||
SliceWiring("battleResult", "gpw_1", "sR", "Fi.aqp", "Fi.aqp(t, n.gpw_1)", listOf("DoInit", "ResetBattleRewards", "SetHasBattleResult", "SetIncreasedReward", "SetRewards", "SetSimpleReward")),
|
||||
SliceWiring("battleUsers", "hpw_1", "uP", "sr.hqs", "sr.hqs(t, n.hpw_1)", listOf("?_P", "?hP", "?lP", "?oP", "?qP", "?sP", "InitSuspiciousState", "InitUserLevels", "RemoveTankInfo", "SetGearScore", "SetTankInfo", "SetTankResistance", "UpdateUserLevel", "UpdateUserRank", "UpdateUserScoreKillsAndDeaths", "UpdateUserSuspiciousState", "UpdateUsersClanTag", "UpdateUsersScoreKillsAndDeaths")),
|
||||
SliceWiring("suppliesState", "ipw_1", "wE", "\$t.fq9", "\$t.fq9(t, n.ipw_1)", listOf("?qE")),
|
||||
SliceWiring("suppliesState", "ipw_1", "wE", "\$t.fq9", "\$t.fq9(t, n.ipw_1)", listOf("SetSupplyCount")),
|
||||
SliceWiring("matchmakingGroup", "jpw_1", "rW", "NW().is0", "NW().is0(t, n.jpw_1)", listOf("?zW", "AcceptedInviteToGroup", "AddUser", "AddUserToSelected", "InitMatchmakingGroup", "Invite", "RejectedInviteToGroup", "RemoveUserToSelected", "SetAllowedFromFriends", "SetSelectedUsers", "UpdateMountItems", "UpdateUserReadiness", "UserRemoved")),
|
||||
SliceWiring("shop", "kpw_1", "j4", "(inline@shop)", "(function (t, n) { var i; if (t instanceof w4) i = n.qt6(cd, cd, cd, cd, cd, cd, cd, t.lt6_1); else if (t instanceof Yut) i = n.qt6(cd, cd, cd, cd, !0); else if (t instanceof F5) i = new j4(cd, cd, cd, cd, cd, cd, cd, n.qq3_1); else if (t instanceof h4) i = n.qt6(cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.st5_1); else if (t instanceof c4) i = n.qt6(cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.ut5_1); else if (t instanceof u4) i = n.qt6( cd, cd, cd, cd, cd, cd, …", listOf("?x4", "AddCategoriesWithBonus", "AddItemToOrderProcessing", "BlockBackButton", "BraintreeLoadingInterrupt", "ClearPreviousScreen", "ClearTargetCategory", "ClearTargetProductId", "CurrentPayMode", "DeleteOneTimePurchaseItem", "InitAdditionalDescription", "InitAmountString", "InitCategory", "InitCoinPackage", "InitCompensation", "InitCrystalKitPackage", "InitFeatureItem", "InitGroup", "InitItemViewType", "InitKeysPackage", "InitKitBundle", "InitKitPackage", "InitLootBoxAndPaint", "InitOneTimePurchaseItem", "InitPayModeAction", "InitPaymentModeAsShopItem", "InitPaymentProviderItems", "InitPaymentViewType", "InitRestrictionByPayMode", "InitRewardedVideosBlocks", "InitShopCard", "InitShopCardDiscount", "InitShopCardView", "InitShopItem", "InitShopItemName", "InitSingleItemKit", "InitSpecialKitPackage", "MobilePaymentStateChanged", "PaymentProviderFinishFail", "PaymentProviderFinishSuccess", "PaymentProviderInProgress", "PaymentUrlReceiveFailed", "PaymentUrlReceived", "RemoveDiscountItemForItem", "RemoveItemFromOrderProcessing", "ResetPaymentState", "ResetShop", "SavePreviousScreen", "SaveTargetProductId", "SaveTargetVisitedCategory", "SelectCategory", "SelectCategoryId", "SelectItem", "SetBraintreeToken", "SetCoinPaymentProviderUrl", "SetGoToHomeAfterBuy", "SetInitShopItemId", "SetPurchaseCompleted", "SetStripeIntentParams", "SetupDiscountCategoryByItem", "SetupDiscountItem", "SetupDiscountItemForItem", "ShopCardExpired", "ShopCardRemoved", "ShopCardSold", "ShopLoaded", "ToggleShopActivity", "TryToBuyOneTimePurchase", "UnblockBackButton")),
|
||||
SliceWiring("battlePauseState", "lpw_1", "dT", "NT().mqc", "NT().mqc(t, n.lpw_1)", listOf("?TT", "?xT", "OnPauseMode", "SetIdleKickPeriod")),
|
||||
@@ -70,13 +70,13 @@ object RootWiring {
|
||||
SliceWiring("controlSettings", "zpw_1", "i2", "_2().ess", "_2().ess(t, n.zpw_1)", listOf("?_C", "UpdateSettings")),
|
||||
SliceWiring("securitySettings", "apx_1", "V2", "pc.qsv", "pc.qsv(t, n.apx_1)", listOf("SetProfileBlockStatus")),
|
||||
SliceWiring("purchaseDialogState", "bpx_1", "CO", "je.ur2", "je.ur2(t, n.bpx_1)", listOf("ChangeEmailStatus", "ResetPurchaseDialog", "SuccessfullyPurchase")),
|
||||
SliceWiring("battleInviteState", "cpx_1", "att", "Ttt().nth", "Ttt().nth(t, n.cpx_1)", listOf("?dtt", "EnableSetBattleInviteNotifications", "InvitationResponse", "InviteToBattle", "RemoveUserFromInvited", "SelectUserToInvite")),
|
||||
SliceWiring("battleInviteState", "cpx_1", "att", "Ttt().nth", "Ttt().nth(t, n.cpx_1)", listOf("AddInvitedUser", "ClearSelectedForInvite", "EnableSetBattleInviteNotifications", "InvitationResponse", "RemoveUserFromInvited", "SelectUserToInvite")),
|
||||
SliceWiring("keyboardSettings", "dpx_1", "Sut", "bw.oth", "bw.oth(t, n.dpx_1)", listOf("?Iut", "?_C", "ChangeAction", "RemoveAction", "ResetAction")),
|
||||
SliceWiring("touchscreenHudSettings", "epx_1", "j7", "N7().xsv", "N7().xsv(t, n.epx_1)", listOf("?E7", "?_C", "UpdateSettings")),
|
||||
SliceWiring("mainQuest", "fpx_1", "WZ", "ih.bsk", "ih.bsk(t, n.fpx_1)", listOf("AddRewardedQuest", "QuestsLoaded", "ResetQuestsLoaded", "SetBattleUpdatedQuests", "SetEventPassShopItemId", "SetQuests", "UpdateQuests")),
|
||||
SliceWiring("language", "gpx_1", "?", "m6().jtg", "m6().jtg(t, n.gpx_1)", listOf("SetLanguage")),
|
||||
SliceWiring("launchParams", "hpx_1", "?", "(pass-through)", "n.hpx_1", listOf()),
|
||||
SliceWiring("partner", "ipx_1", "UJ", "(inline@partner)", "(function (t, n) { var i; if (t instanceof VJ) i = n.osf(t.rsf_1, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.ssf_1); else if (t instanceof nZ) { var r = t.bsg_1, e = t.csg_1, u = t.dsg_1, s = t.esg_1, o = t.fsg_1, _ = t.gsg_1; i = n.osf(cd, cd, cd, r, e, u, cd, cd, o, _, s); } else i = t instanceof iZ ? n.osf(cd, t.hsg_1) : t instanceof uZ ? n.osf(cd, cd, t.ksg_1) : t instanceof eZ ? n.osf(cd, cd, cd, cd, cd, cd, cd, t.jsg_1) : t instanceof _Z ? n.osf(cd, cd, cd, cd, cd, cd, t.osg_1) : t instanceof X …", listOf("?JJ", "?_Z", "?hZ", "?tZ", "InitPartnerInviteAction", "InitSocialNetworkParameters", "SetLoginParams", "SetLoginStatusForBinding", "SetPartnerId", "SetPartnerParameters", "SetPartnerReady")),
|
||||
SliceWiring("partner", "ipx_1", "UJ", "(inline@partner)", "(function (t, n) { var i; if (t instanceof VJ) i = n.osf(t.rsf_1, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.ssf_1); else if (t instanceof nZ) { var r = t.bsg_1, e = t.csg_1, u = t.dsg_1, s = t.esg_1, o = t.fsg_1, _ = t.gsg_1; i = n.osf(cd, cd, cd, r, e, u, cd, cd, o, _, s); } else i = t instanceof iZ ? n.osf(cd, t.hsg_1) : t instanceof uZ ? n.osf(cd, cd, t.ksg_1) : t instanceof eZ ? n.osf(cd, cd, cd, cd, cd, cd, cd, t.jsg_1) : t instanceof _Z ? n.osf(cd, cd, cd, cd, cd, cd, t.osg_1) : t instanceof X …", listOf("InitPartnerInviteAction", "InitSocialNetworkParameters", "MarkAccountLinked", "MarkAccountNotLinked", "SetLoginParams", "SetLoginStatusForBinding", "SetPartnerId", "SetPartnerItemEnabled", "SetPartnerParameters", "SetPartnerReady", "UpdatePartnerInviteAction")),
|
||||
SliceWiring("entrance", "jpx_1", "hD", "Bv.pth", "Bv.pth(t, n.jpx_1)", listOf("HideSocialNetworks", "SetAgeWarnShow", "SetAuthorizedByChinaSdkToken", "SetClassic", "SetControlsForChina", "SetRunningInChinaDataCenter", "SetRunningInChinaPartners")),
|
||||
SliceWiring("antiAddiction", "kpx_1", "UC", "W.iq8", "W.iq8(t, n.kpx_1)", listOf("EnableRealNameCheck", "RequireUserIdVerification", "SetRealNameAndIdNumber", "SetValidateAntiAddictionUserDataStatus", "UpdatePlayingTime")),
|
||||
SliceWiring("spectator", "lpx_1", "HA", "Li.jqm", "Li.jqm(t, n.lpx_1)", listOf("AddSpectator", "RemoveSpectator", "SetSpectator", "SetSpectators", "SetSpectatorsListVisible", "UpdateHudLayout")),
|
||||
@@ -84,7 +84,7 @@ object RootWiring {
|
||||
SliceWiring("rulesUpdated", "npx_1", "i1", "Ch.dsm", "Ch.dsm(t, n.npx_1)", listOf("UpdateRules")),
|
||||
SliceWiring("announcement", "opx_1", "lC", "PC().rq5", "PC().rq5(t, n.opx_1)", listOf("DisableAnnouncement", "SetAnnouncementItems", "SetAnnouncementModelLoaded", "SetSkipNextPromotedAnnounce")),
|
||||
SliceWiring("notificationByCountry", "ppx_1", "gJ", "R_.ssd", "R_.ssd(t, n.ppx_1)", listOf("Init", "MarkHomeScreenDialogShown")),
|
||||
SliceWiring("userRenameState", "qpx_1", "O8", "Rf.pte", "Rf.pte(t, n.qpx_1)", listOf("?B8", "?F8", "?G8", "?Q8", "?U8", "ChangeUidInputState", "ResponseActual", "ResponseDelivered", "SetChangeUidParams", "SetRubiesForRename", "SetValidationStatus")),
|
||||
SliceWiring("userRenameState", "qpx_1", "O8", "Rf.pte", "Rf.pte(t, n.qpx_1)", listOf("ChangeUidInputState", "HideLinkErrorWarning", "MarkFreeRenameAvailable", "MarkRenameFailed", "MarkRenameSucceeded", "ResetRenameDialog", "ResponseActual", "ResponseDelivered", "SetChangeUidParams", "SetRubiesForRename", "SetValidationStatus")),
|
||||
SliceWiring("eventGoods", "rpx_1", "W7", "Wc.esx", "Wc.esx(t, n.rpx_1)", listOf("InitEventGoods")),
|
||||
SliceWiring("creatorTagState", "spx_1", "qO", "ze.er2", "ze.er2(t, n.spx_1)", listOf("ClearCreatorTag", "SetAttachedCreatorTag", "SetCreatorTag", "SetCreatorTags")),
|
||||
SliceWiring("twoStepVerificationState", "tpx_1", "x9", "_f.atb", "_f.atb(t, n.tpx_1)", listOf("ActivationStatus2FA", "Enable2FaRequest", "SetSecretAndQRCode", "SetUse2FA", "VerificationStatus")),
|
||||
@@ -106,7 +106,7 @@ object RootWiring {
|
||||
)
|
||||
|
||||
/** 已迁移(强类型;launchParams 为透传,不调用 reducer)的字段。 */
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState")
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState", "friends", "suppliesState", "clanUserInfo", "battleInviteState", "partner", "userRenameState")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// ⑥ 动作目录:816 个类与 138 个真实派发名对齐
|
||||
// ⑦ 回放:真实 toString 样例的类/字段/类型校验
|
||||
// ⑧ 全目录动作类都能按 KClass 路由
|
||||
// ⑨~㊿/51-63 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// ⑨~㊿/51-69 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// Shop(含 U7 类别表与 w3 物品表两个子 reducer)/ Screen / LootBoxes / Garage / GaragePreview / Entrance / User / Settings /
|
||||
// AccountSettings / ProBattle / Language / Announcement / News / Notifications / Quests /
|
||||
// LobbyLoader / PurchaseDialogState / PromoCode / SupportUrl / RulesUpdated / NotificationByCountry / AvailabilityByRank /
|
||||
@@ -17,7 +17,8 @@
|
||||
// TipsState / RankUpDialogState / BattleResult / CaptchaState / ModalScreen / DroppableGold / EventGoods /
|
||||
// CreatorTagState / RewardedVideosState / PasswordChangeState /
|
||||
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
||||
// Moderation / MigrationState / Register / UserReports;
|
||||
// Moderation / MigrationState / Register / UserReports /
|
||||
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -534,6 +535,63 @@ import App.State.Reducers.ReduceUserReports
|
||||
import App.State.Reducers.ReportEntry
|
||||
import App.State.Reducers.ReportKind
|
||||
import App.State.Reducers.UserReportsStateSlice
|
||||
import App.State.ChangeFriendAddFindState
|
||||
import App.State.AddUsersToAccepted
|
||||
import App.State.AddUsersToIncoming
|
||||
import App.State.AddUsersToNewAccepted
|
||||
import App.State.AddUsersToNewIncoming
|
||||
import App.State.RemoveUserFromAccepted
|
||||
import App.State.RemoveUserFromIncoming
|
||||
import App.State.RemoveUserFromNewAccepted
|
||||
import App.State.RemoveUsersFromNewIncoming
|
||||
import App.State.SetLimits
|
||||
import App.State.SetValidationStatus
|
||||
import App.State.Reducers.ClearContextMenuUser
|
||||
import App.State.Reducers.FriendSearchState
|
||||
import App.State.Reducers.FriendsStateSlice
|
||||
import App.State.Reducers.ReduceFriends
|
||||
import App.State.Reducers.SetContextMenuUser
|
||||
import App.State.Reducers.ReduceSupplies
|
||||
import App.State.Reducers.SetSupplyCount
|
||||
import App.State.Reducers.SuppliesStateSlice
|
||||
import App.State.ClanNotifierData
|
||||
import App.State.Loaded
|
||||
import App.State.Reducers.ClanUserInfoStateSlice
|
||||
import App.State.Reducers.ReduceClanUserInfo
|
||||
import App.State.EnableSetBattleInviteNotifications
|
||||
import App.State.InvitationResponse
|
||||
import App.State.RemoveUserFromInvited
|
||||
import App.State.SelectUserToInvite
|
||||
import App.State.Reducers.AddInvitedUser
|
||||
import App.State.Reducers.BattleInviteStateSlice
|
||||
import App.State.Reducers.ClearSelectedForInvite
|
||||
import App.State.Reducers.ReduceBattleInvite
|
||||
import App.State.InitPartnerInviteAction
|
||||
import App.State.InitSocialNetworkParameters
|
||||
import App.State.SetLoginParams
|
||||
import App.State.SetLoginStatusForBinding
|
||||
import App.State.SetPartnerId
|
||||
import App.State.SetPartnerParameters
|
||||
import App.State.SetPartnerReady
|
||||
import App.State.Reducers.MarkAccountLinked
|
||||
import App.State.Reducers.MarkAccountNotLinked
|
||||
import App.State.Reducers.PartnerStateSlice
|
||||
import App.State.Reducers.ReducePartner
|
||||
import App.State.Reducers.SetPartnerItemEnabled
|
||||
import App.State.Reducers.UpdatePartnerInviteAction
|
||||
import App.State.ChangeUidInputState
|
||||
import App.State.ResponseActual
|
||||
import App.State.ResponseDelivered
|
||||
import App.State.SetChangeUidParams
|
||||
import App.State.SetRubiesForRename
|
||||
import App.State.Reducers.HideLinkErrorWarning
|
||||
import App.State.Reducers.MarkFreeRenameAvailable
|
||||
import App.State.Reducers.MarkRenameFailed
|
||||
import App.State.Reducers.MarkRenameSucceeded
|
||||
import App.State.Reducers.ReduceUserRename
|
||||
import App.State.Reducers.ResetRenameDialog
|
||||
import App.State.Reducers.RenameUidState
|
||||
import App.State.Reducers.UserRenameStateSlice
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -961,7 +1019,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 53 个已迁移切片(52 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 59 个已迁移切片(58 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -1025,7 +1083,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 53 个已迁移字段,其余 36 个待迁",
|
||||
"根:迁移表 = 59 个已迁移字段,其余 30 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -1042,8 +1100,10 @@ object StateCheck {
|
||||
"system", "contextTutorial", "battleTutorial", "spectator",
|
||||
"twoStepVerificationState", "antiAddiction", "moderation",
|
||||
"migrationState", "register", "userReportsState",
|
||||
"friends", "suppliesState", "clanUserInfo", "battleInviteState",
|
||||
"partner", "userRenameState",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 36
|
||||
RootWiring.Unmigrated.size == 30
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -1099,7 +1159,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 53/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 59/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -4815,6 +4875,364 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// 64 切片 reducer:Friends(KD / NL().cr9,8 字段;13 个动作)
|
||||
run {
|
||||
val S0 = FriendsStateSlice()
|
||||
Check(
|
||||
"切片 Friends:默认值完整",
|
||||
S0.UserSearchState == FriendSearchState.HIDDEN && S0.ContextMenuUser == null &&
|
||||
S0.AcceptedLimit == 0 && S0.IncomingLimit == 0 &&
|
||||
S0.Accepted.isEmpty() && S0.NewAccepted.isEmpty() &&
|
||||
S0.Incoming.isEmpty() && S0.NewIncoming.isEmpty()
|
||||
)
|
||||
val S1 = ReduceFriends(S0, ChangeFriendAddFindState(FriendSearchState.SEARCHING))
|
||||
Check(
|
||||
"切片 Friends:ChangeFriendAddFindState 写搜索状态",
|
||||
S1.UserSearchState == FriendSearchState.SEARCHING
|
||||
)
|
||||
Check(
|
||||
"切片 Friends:SetValidationStatus 命中即 FOUND,null 即 NOT_FOUND",
|
||||
ReduceFriends(S1, SetValidationStatus("ok")).UserSearchState ==
|
||||
FriendSearchState.FOUND &&
|
||||
ReduceFriends(S1, SetValidationStatus(null)).UserSearchState ==
|
||||
FriendSearchState.NOT_FOUND
|
||||
)
|
||||
Check(
|
||||
"切片 Friends:SetLimits 写两个上限",
|
||||
ReduceFriends(S1, SetLimits(50, 30)).let {
|
||||
it.AcceptedLimit == 50 && it.IncomingLimit == 30
|
||||
}
|
||||
)
|
||||
Check(
|
||||
"切片 Friends:右键菜单设置 / 清除",
|
||||
ReduceFriends(S1, SetContextMenuUser("u1")).ContextMenuUser == "u1" &&
|
||||
ReduceFriends(S1, ClearContextMenuUser).ContextMenuUser == null
|
||||
)
|
||||
val S2 = ReduceFriends(S1, AddUsersToAccepted(listOf(1L, 2L)))
|
||||
Check(
|
||||
"切片 Friends:AddUsersToAccepted 整批入集合",
|
||||
S2.Accepted == setOf<Any?>(1L, 2L)
|
||||
)
|
||||
Check(
|
||||
"切片 Friends:RemoveUserFromAccepted 删单值",
|
||||
ReduceFriends(S2, RemoveUserFromAccepted(1L)).Accepted == setOf<Any?>(2L)
|
||||
)
|
||||
val S3 = ReduceFriends(S2, AddUsersToNewAccepted(clanId = 0, userIds = listOf(3L, 4L)))
|
||||
Check(
|
||||
"切片 Friends:AddUsersToNewAccepted 读 userIds",
|
||||
S3.NewAccepted == setOf<Any?>(3L, 4L)
|
||||
)
|
||||
Check(
|
||||
"切片 Friends:RemoveUserFromNewAccepted / AddUsersToIncoming",
|
||||
ReduceFriends(S3, RemoveUserFromNewAccepted(3L)).NewAccepted == setOf<Any?>(4L) &&
|
||||
ReduceFriends(S3, AddUsersToIncoming(listOf(5L))).Incoming == setOf<Any?>(5L)
|
||||
)
|
||||
Check(
|
||||
"切片 Friends:RemoveUsersFromNewIncoming 按集合减",
|
||||
ReduceFriends(
|
||||
ReduceFriends(S3, AddUsersToNewIncoming(listOf(6L, 7L))),
|
||||
RemoveUsersFromNewIncoming(listOf(6L)),
|
||||
).NewIncoming == setOf<Any?>(7L)
|
||||
)
|
||||
Check(
|
||||
"切片 Friends:无关动作不改状态",
|
||||
ReduceFriends(S3, AddFrags(1)) == S3
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, ChangeFriendAddFindState(FriendSearchState.FOUND))
|
||||
Check(
|
||||
"根:ChangeFriendAddFindState 只动 friends",
|
||||
Root1.Friends.UserSearchState == FriendSearchState.FOUND &&
|
||||
Root1.Partner == Root0.Partner
|
||||
)
|
||||
val W = RootWiring.ByField("friends")!!
|
||||
Check(
|
||||
"根:friends 委派到 KD / NL().cr9 且 13 个动作",
|
||||
W.SliceClass == "KD" && W.Reducer == "NL().cr9" && W.Actions.size == 13
|
||||
)
|
||||
}
|
||||
|
||||
// 65 切片 reducer:Supplies(wE / $t.fq9,1 字段;SetSupplyCount)
|
||||
run {
|
||||
val S0 = SuppliesStateSlice()
|
||||
Check("切片 Supplies:默认空 Map", S0.Count.isEmpty())
|
||||
val S1 = ReduceSupplies(S0, SetSupplyCount("mine", 3))
|
||||
Check(
|
||||
"切片 Supplies:SetSupplyCount 写键值",
|
||||
S1.Count == mapOf<Any?, Any?>("mine" to 3)
|
||||
)
|
||||
Check(
|
||||
"切片 Supplies:再次写入覆盖旧值",
|
||||
ReduceSupplies(S1, SetSupplyCount("mine", 1)).Count ==
|
||||
mapOf<Any?, Any?>("mine" to 1)
|
||||
)
|
||||
Check("切片 Supplies:无关动作不改状态", ReduceSupplies(S1, AddFrags(1)) == S1)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetSupplyCount("k", 9))
|
||||
Check(
|
||||
"根:SetSupplyCount 只动 suppliesState",
|
||||
Root1.SuppliesState.Count == mapOf<Any?, Any?>("k" to 9) &&
|
||||
Root1.ClanUserInfo == Root0.ClanUserInfo
|
||||
)
|
||||
val W = RootWiring.ByField("suppliesState")!!
|
||||
Check(
|
||||
"根:suppliesState 委派到 wE / \$t.fq9",
|
||||
W.SliceClass == "wE" && W.Reducer == "\$t.fq9" &&
|
||||
W.Actions == listOf("SetSupplyCount")
|
||||
)
|
||||
}
|
||||
|
||||
// 66 切片 reducer:ClanUserInfo(hO / de.gr1,1 字段;Loaded 合并)
|
||||
run {
|
||||
val S0 = ClanUserInfoStateSlice()
|
||||
Check("切片 ClanUserInfo:默认空 Map", S0.Users.isEmpty())
|
||||
val S1 = ReduceClanUserInfo(S0, Loaded(mapOf("u1" to ClanNotifierData(1L, null, 11L))))
|
||||
Check(
|
||||
"切片 ClanUserInfo:Loaded 写入用户表",
|
||||
S1.Users.keys == setOf<Any?>("u1") &&
|
||||
(S1.Users["u1"] as ClanNotifierData).userId == 11L
|
||||
)
|
||||
Check(
|
||||
"切片 ClanUserInfo:第二次 Loaded 是合并不是覆盖",
|
||||
ReduceClanUserInfo(S1, Loaded(mapOf("u2" to ClanNotifierData(2L, null, 22L)))).Users.keys ==
|
||||
setOf<Any?>("u1", "u2")
|
||||
)
|
||||
Check(
|
||||
"切片 ClanUserInfo:无关动作不改状态",
|
||||
ReduceClanUserInfo(S1, AddFrags(1)) == S1
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, Loaded(mapOf("x" to ClanNotifierData(3L, null, 33L))))
|
||||
Check(
|
||||
"根:Loaded 只动 clanUserInfo",
|
||||
Root1.ClanUserInfo.Users.keys == setOf<Any?>("x") &&
|
||||
Root1.SuppliesState == Root0.SuppliesState
|
||||
)
|
||||
val W = RootWiring.ByField("clanUserInfo")!!
|
||||
Check(
|
||||
"根:clanUserInfo 委派到 hO / de.gr1",
|
||||
W.SliceClass == "hO" && W.Reducer == "de.gr1" &&
|
||||
W.Actions == listOf("Loaded")
|
||||
)
|
||||
}
|
||||
|
||||
// 67 切片 reducer:BattleInvite(att / Ttt().nth,3 字段;6 个动作)
|
||||
run {
|
||||
val S0 = BattleInviteStateSlice()
|
||||
Check(
|
||||
"切片 BattleInvite:默认开启、两个集合为空",
|
||||
S0.IsEnabled && S0.InvitedUsers.isEmpty() && S0.SelectedForInvite.isEmpty()
|
||||
)
|
||||
val S1 = ReduceBattleInvite(S0, AddInvitedUser(1L))
|
||||
Check("切片 BattleInvite:AddInvitedUser 入已邀请集合", S1.InvitedUsers == setOf<Any?>(1L))
|
||||
Check(
|
||||
"切片 BattleInvite:InvitationResponse 从已邀请集合删",
|
||||
ReduceBattleInvite(S1, InvitationResponse(1L, "ok")).InvitedUsers.isEmpty()
|
||||
)
|
||||
val S2 = ReduceBattleInvite(S1, SelectUserToInvite(2L))
|
||||
Check(
|
||||
"切片 BattleInvite:SelectUserToInvite 入待邀请集合",
|
||||
S2.SelectedForInvite == setOf<Any?>(2L)
|
||||
)
|
||||
Check(
|
||||
"切片 BattleInvite:RemoveUserFromInvited 从待邀请集合删",
|
||||
ReduceBattleInvite(S2, RemoveUserFromInvited(2L)).SelectedForInvite.isEmpty()
|
||||
)
|
||||
Check(
|
||||
"切片 BattleInvite:ClearSelectedForInvite 清空",
|
||||
ReduceBattleInvite(S2, ClearSelectedForInvite).SelectedForInvite.isEmpty()
|
||||
)
|
||||
Check(
|
||||
"切片 BattleInvite:EnableSetBattleInviteNotifications 写开关",
|
||||
!ReduceBattleInvite(S2, EnableSetBattleInviteNotifications(false)).IsEnabled
|
||||
)
|
||||
Check(
|
||||
"切片 BattleInvite:无关动作不改状态",
|
||||
ReduceBattleInvite(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, AddInvitedUser(9L))
|
||||
Check(
|
||||
"根:AddInvitedUser 只动 battleInviteState",
|
||||
Root1.BattleInviteState.InvitedUsers == setOf<Any?>(9L) &&
|
||||
Root1.UserRenameState == Root0.UserRenameState
|
||||
)
|
||||
val W = RootWiring.ByField("battleInviteState")!!
|
||||
Check(
|
||||
"根:battleInviteState 委派到 att / Ttt().nth 且 6 个动作",
|
||||
W.SliceClass == "att" && W.Reducer == "Ttt().nth" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"AddInvitedUser", "InvitationResponse", "SelectUserToInvite",
|
||||
"RemoveUserFromInvited", "ClearSelectedForInvite",
|
||||
"EnableSetBattleInviteNotifications",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 68 切片 reducer:Partner(UJ / (inline@partner),15 字段;11 个动作)
|
||||
run {
|
||||
val S0 = PartnerStateSlice()
|
||||
Check(
|
||||
"切片 Partner:默认值完整",
|
||||
S0.PartnerId == null && S0.LoginParams.isEmpty() && S0.Params.isEmpty() &&
|
||||
!S0.HasOwnPaymentSystem && !S0.HasSocialFunction &&
|
||||
!S0.HasClientPaymentAction && S0.PaymentAction == null &&
|
||||
S0.InviteAction == null && !S0.CanOpenExternalLinks &&
|
||||
!S0.HasAccountBinding && S0.FailedRedirectUrl == null &&
|
||||
S0.LoginForBindingStatus == ByPasswordStatus.NONE &&
|
||||
!S0.IsAccountAlreadyLinked && S0.ItemsEnabledForPartner.isEmpty() &&
|
||||
!S0.IsPartnerReady
|
||||
)
|
||||
val S1 = ReducePartner(S0, SetPartnerId("p1", "https://fail"))
|
||||
Check(
|
||||
"切片 Partner:SetPartnerId 同时写失败跳转",
|
||||
S1.PartnerId == "p1" && S1.FailedRedirectUrl == "https://fail"
|
||||
)
|
||||
val S2 = ReducePartner(
|
||||
S1,
|
||||
InitSocialNetworkParameters(
|
||||
hasOwnPaymentSystem = true, hasSocialFunction = true,
|
||||
hasClientPaymentAction = false, failedRedirectUrl = null,
|
||||
canOpenExternalLinks = true, hasAccountBinding = true,
|
||||
),
|
||||
)
|
||||
Check(
|
||||
"切片 Partner:InitSocialNetworkParameters 写 6 个字段",
|
||||
S2.HasOwnPaymentSystem && S2.HasSocialFunction && !S2.HasClientPaymentAction &&
|
||||
S2.CanOpenExternalLinks && S2.HasAccountBinding
|
||||
)
|
||||
Check(
|
||||
"切片 Partner:loginParams / params 分别写入",
|
||||
ReducePartner(S2, SetLoginParams(mapOf("a" to 1))).LoginParams ==
|
||||
mapOf<Any?, Any?>("a" to 1) &&
|
||||
ReducePartner(S2, SetPartnerParameters(mapOf("b" to 2))).Params ==
|
||||
mapOf<Any?, Any?>("b" to 2)
|
||||
)
|
||||
Check(
|
||||
"切片 Partner:两种邀请动作都写 inviteAction",
|
||||
ReducePartner(S2, InitPartnerInviteAction("i1")).InviteAction == "i1" &&
|
||||
ReducePartner(S2, UpdatePartnerInviteAction("i2")).InviteAction == "i2"
|
||||
)
|
||||
Check(
|
||||
"切片 Partner:SetLoginStatusForBinding 写绑定状态",
|
||||
ReducePartner(S2, SetLoginStatusForBinding(ByPasswordStatus.WRONG_PASSWORD))
|
||||
.LoginForBindingStatus == ByPasswordStatus.WRONG_PASSWORD
|
||||
)
|
||||
Check(
|
||||
"切片 Partner:已绑定标记两态",
|
||||
ReducePartner(S2, MarkAccountLinked).IsAccountAlreadyLinked &&
|
||||
!ReducePartner(S2, MarkAccountNotLinked).IsAccountAlreadyLinked
|
||||
)
|
||||
Check(
|
||||
"切片 Partner:SetPartnerItemEnabled 写物品开关 Map",
|
||||
ReducePartner(S2, SetPartnerItemEnabled("item", true))
|
||||
.ItemsEnabledForPartner == mapOf<Any?, Any?>("item" to true)
|
||||
)
|
||||
Check(
|
||||
"切片 Partner:SetPartnerReady 写就绪位",
|
||||
ReducePartner(S2, SetPartnerReady(true)).IsPartnerReady
|
||||
)
|
||||
Check("切片 Partner:无关动作不改状态", ReducePartner(S2, AddFrags(1)) == S2)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetPartnerReady(true))
|
||||
Check(
|
||||
"根:SetPartnerReady 只动 partner",
|
||||
Root1.Partner.IsPartnerReady && Root1.Friends == Root0.Friends
|
||||
)
|
||||
val W = RootWiring.ByField("partner")!!
|
||||
Check(
|
||||
"根:partner 是内联 reducer 且 11 个动作",
|
||||
W.SliceClass == "UJ" && W.Reducer == "(inline@partner)" && W.Actions.size == 11
|
||||
)
|
||||
}
|
||||
|
||||
// 69 切片 reducer:UserRename(O8 / Rf.pte,10 字段;11 个动作)
|
||||
run {
|
||||
val S0 = UserRenameStateSlice()
|
||||
Check(
|
||||
"切片 UserRename:默认值完整",
|
||||
!S0.IsFreeRenameAvailable && S0.UserRenameShopItemId == null &&
|
||||
S0.UidInputState == RenameUidState.EMPTY && S0.RenameSuccessful == null &&
|
||||
S0.RubiesForRename == Int.MAX_VALUE && !S0.IsResponseDelivered &&
|
||||
!S0.IsResponseActual && S0.ChangeUidHash == null && S0.Email == null &&
|
||||
S0.ShowLinkErrorWarning
|
||||
)
|
||||
val S1 = ReduceUserRename(S0, ChangeUidInputState(RenameUidState.SHORT))
|
||||
Check(
|
||||
"切片 UserRename:ChangeUidInputState 写输入状态",
|
||||
S1.UidInputState == RenameUidState.SHORT
|
||||
)
|
||||
Check(
|
||||
"切片 UserRename:免费改名 / 改名成功 / 改名失败",
|
||||
ReduceUserRename(S1, MarkFreeRenameAvailable).IsFreeRenameAvailable &&
|
||||
ReduceUserRename(S1, MarkRenameSucceeded).let {
|
||||
!it.IsFreeRenameAvailable && it.RenameSuccessful == true
|
||||
} &&
|
||||
ReduceUserRename(S1, MarkRenameFailed).RenameSuccessful == false
|
||||
)
|
||||
Check(
|
||||
"切片 UserRename:SetValidationStatus 按 ordinal 映射输入状态",
|
||||
ReduceUserRename(S1, SetValidationStatus(RenameUidState.FREE)).let {
|
||||
it.UidInputState == RenameUidState.FREE && it.IsResponseDelivered
|
||||
} &&
|
||||
ReduceUserRename(S1, SetValidationStatus(RenameUidState.SHORT)).UidInputState ==
|
||||
RenameUidState.NOT_VALID &&
|
||||
ReduceUserRename(S1, SetValidationStatus(RenameUidState.NOT_VALID))
|
||||
.UidInputState == RenameUidState.FORBIDDEN
|
||||
)
|
||||
Check(
|
||||
"切片 UserRename:SetRubiesForRename 写价格",
|
||||
ReduceUserRename(S1, SetRubiesForRename(99)).RubiesForRename == 99
|
||||
)
|
||||
val S2 = ReduceUserRename(
|
||||
ReduceUserRename(
|
||||
ReduceUserRename(S1, SetChangeUidParams("hash", "mail")),
|
||||
ResponseDelivered(true),
|
||||
),
|
||||
ResponseActual(true),
|
||||
)
|
||||
Check(
|
||||
"切片 UserRename:改绑参数与两个 response 位",
|
||||
S2.ChangeUidHash == "hash" && S2.Email == "mail" &&
|
||||
S2.IsResponseDelivered && S2.IsResponseActual
|
||||
)
|
||||
Check(
|
||||
"切片 UserRename:ResetRenameDialog 复位弹窗字段",
|
||||
ReduceUserRename(S2, ResetRenameDialog).let {
|
||||
it.UserRenameShopItemId == null &&
|
||||
it.UidInputState == RenameUidState.EMPTY &&
|
||||
it.RenameSuccessful == null && !it.IsResponseDelivered &&
|
||||
!it.IsResponseActual && it.ChangeUidHash == "hash"
|
||||
}
|
||||
)
|
||||
Check(
|
||||
"切片 UserRename:HideLinkErrorWarning 关提示",
|
||||
!ReduceUserRename(S2, HideLinkErrorWarning).ShowLinkErrorWarning
|
||||
)
|
||||
Check(
|
||||
"切片 UserRename:无关动作不改状态",
|
||||
ReduceUserRename(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetRubiesForRename(5))
|
||||
Check(
|
||||
"根:SetRubiesForRename 只动 userRenameState",
|
||||
Root1.UserRenameState.RubiesForRename == 5 &&
|
||||
Root1.Partner == Root0.Partner
|
||||
)
|
||||
val W = RootWiring.ByField("userRenameState")!!
|
||||
Check(
|
||||
"根:userRenameState 委派到 O8 / Rf.pte 且 11 个动作",
|
||||
W.SliceClass == "O8" && W.Reducer == "Rf.pte" && W.Actions.size == 11
|
||||
)
|
||||
}
|
||||
|
||||
val Failed = Results.filter { !it.second }
|
||||
println("TankiOffline 状态层自检:${Results.size} 项")
|
||||
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)
|
||||
|
||||
Reference in new issue
Block a user