UPDATE: Support RobinSR
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m9s
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m9s
This commit is contained in:
@@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "4.1.6",
|
||||||
|
"date": "12/04/2026",
|
||||||
|
"type": "update",
|
||||||
|
"items": [
|
||||||
|
"Support RobinSR"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"date": "17/03/2026",
|
"date": "17/03/2026",
|
||||||
|
|||||||
281
messages/cn.json
281
messages/cn.json
@@ -1,281 +0,0 @@
|
|||||||
{
|
|
||||||
"TabTitle": {
|
|
||||||
"title": "Firefly Tools",
|
|
||||||
"description": "Firefly tools by Firefly Shelter"
|
|
||||||
},
|
|
||||||
"DataPage": {
|
|
||||||
"skillType": "技能类型",
|
|
||||||
"skillName": "技能名称",
|
|
||||||
"character": "角色",
|
|
||||||
"id": "ID",
|
|
||||||
"path": "命运",
|
|
||||||
"rarity": "稀有度",
|
|
||||||
"element": "元素",
|
|
||||||
"technique": "秘技",
|
|
||||||
"talent": "天赋",
|
|
||||||
"basic": "普通攻击",
|
|
||||||
"skill": "技能",
|
|
||||||
"ultimate": "终结技",
|
|
||||||
"servant": "忆灵",
|
|
||||||
"damage": "伤害",
|
|
||||||
"type": "类型",
|
|
||||||
"warrior": "毁灭",
|
|
||||||
"knight": "守护",
|
|
||||||
"mage": "博学",
|
|
||||||
"priest": "丰饶",
|
|
||||||
"rogue": "狩猎",
|
|
||||||
"shaman": "同谐",
|
|
||||||
"warlock": "虚无",
|
|
||||||
"elation": "欢愉",
|
|
||||||
"memory": "记忆",
|
|
||||||
"fire": "火",
|
|
||||||
"ice": "冰",
|
|
||||||
"imaginary": "虚数",
|
|
||||||
"physical": "物理",
|
|
||||||
"quantum": "量子",
|
|
||||||
"thunder": "雷",
|
|
||||||
"wind": "风",
|
|
||||||
"hp": "生命值",
|
|
||||||
"atk": "攻击",
|
|
||||||
"speed": "速度",
|
|
||||||
"critRate": "暴击率",
|
|
||||||
"critDmg": "暴击伤害",
|
|
||||||
"breakEffect": "击破伤害",
|
|
||||||
"effectRes": "效果抗性",
|
|
||||||
"energyRegenerationRate": "能量恢复速率",
|
|
||||||
"effectHitRate": "效果命中率",
|
|
||||||
"outgoingHealingBoost": "治疗增强",
|
|
||||||
"fireDmgBoost": "火元素伤害增强",
|
|
||||||
"iceDmgBoost": "冰元素伤害增强",
|
|
||||||
"imaginaryDmgBoost": "虚数伤害增强",
|
|
||||||
"physicalDmgBoost": "物理伤害增强",
|
|
||||||
"quantumDmgBoost": "量子伤害增强",
|
|
||||||
"thunderDmgBoost": "雷元素伤害增强",
|
|
||||||
"windDmgBoost": "风元素伤害增强",
|
|
||||||
"pursued": "附加伤害",
|
|
||||||
"true damage": "真实伤害",
|
|
||||||
"elationdamage": "欢愉伤害",
|
|
||||||
"follow-up": "后续伤害",
|
|
||||||
"elemental damage": "击破与超击破伤害",
|
|
||||||
"dot": "持续伤害",
|
|
||||||
"qte": "QTE 技能",
|
|
||||||
"level": "等级",
|
|
||||||
"relics": "遗器",
|
|
||||||
"eidolons": "星魂",
|
|
||||||
"lightcones": "光锥",
|
|
||||||
"loadData": "加载数据",
|
|
||||||
"exportData": "导出数据",
|
|
||||||
"connectSetting": "连接设置",
|
|
||||||
"connected": "已连接",
|
|
||||||
"unconnected": "未连接",
|
|
||||||
"psConnection": "PS 连接",
|
|
||||||
"connectionType": "连接类型",
|
|
||||||
"status": "状态",
|
|
||||||
"connectPs": "连接 PS",
|
|
||||||
"other": "其他",
|
|
||||||
"freeSr": "FreeSR",
|
|
||||||
"database": "数据库",
|
|
||||||
"enka": "Enka",
|
|
||||||
"monsterSetting": "怪物设置",
|
|
||||||
"serverUrl": "服务器 URL",
|
|
||||||
"privateType": "私有类型",
|
|
||||||
"local": "本地",
|
|
||||||
"server": "服务器",
|
|
||||||
"username": "用户名",
|
|
||||||
"password": "密码",
|
|
||||||
"placeholderServerUrl": "输入服务器 URL",
|
|
||||||
"placeholderUsername": "输入用户名",
|
|
||||||
"placeholderPassword": "输入密码",
|
|
||||||
"connectedSuccess": "成功连接 PS",
|
|
||||||
"connectedFailed": "连接 PS 失败",
|
|
||||||
"syncSuccess": "已成功与 PS 同步数据",
|
|
||||||
"syncFailed": "与 PS 同步数据失败",
|
|
||||||
"sync": "同步",
|
|
||||||
"importSetting": "导入设置",
|
|
||||||
"profile": "配置档",
|
|
||||||
"default": "默认",
|
|
||||||
"copyProfiles": "复制配置档",
|
|
||||||
"addNewProfile": "添加新配置档",
|
|
||||||
"createNewProfile": "创建新配置档",
|
|
||||||
"editProfile": "编辑配置档",
|
|
||||||
"placeholderProfileName": "输入配置档名称",
|
|
||||||
"profileName": "配置档名称",
|
|
||||||
"create": "创建",
|
|
||||||
"update": "更新",
|
|
||||||
"characterInformation": "角色信息",
|
|
||||||
"skills": "技能",
|
|
||||||
"showcaseCard": "展示卡",
|
|
||||||
"comingSoon": "敬请期待",
|
|
||||||
"characterName": "角色名称",
|
|
||||||
"placeholderCharacter": "输入角色名称",
|
|
||||||
"characterSettings": "角色设置",
|
|
||||||
"levelConfiguration": "等级配置",
|
|
||||||
"characterLevel": "角色等级",
|
|
||||||
"max": "最大",
|
|
||||||
"ultimateEnergy": "终极能量",
|
|
||||||
"currentEnergy": "当前能量",
|
|
||||||
"setTo50": "设为50%",
|
|
||||||
"battleConfiguration": "战斗配置",
|
|
||||||
"useTechnique": "使用秘术",
|
|
||||||
"techniqueNote": "启用战前秘术效果",
|
|
||||||
"enhancement": "强化",
|
|
||||||
"enhancementLevel": "强化等级",
|
|
||||||
"origin": "来源",
|
|
||||||
"enhancedNote": "强化更高可解锁额外技能",
|
|
||||||
"lightconeEquipment": "光锥装备",
|
|
||||||
"lightconeSettings": "光锥设置",
|
|
||||||
"placeholderLevel": "输入等级",
|
|
||||||
"superimpositionRank": "叠加等级",
|
|
||||||
"ranksNote": "更高等级提供更强效果",
|
|
||||||
"changeLightcone": "更换光锥",
|
|
||||||
"removeLightcone": "移除光锥",
|
|
||||||
"equipLightcone": "装备光锥",
|
|
||||||
"noLightconeEquipped": "未装备光锥",
|
|
||||||
"equipLightconeNote": "装备光锥以增强角色能力",
|
|
||||||
"filter": "筛选",
|
|
||||||
"selectedCharacters": "已选角色",
|
|
||||||
"selectedProfiles": "已选配置档",
|
|
||||||
"clearAll": "清除全部",
|
|
||||||
"selectAll": "全选",
|
|
||||||
"copy": "复制",
|
|
||||||
"copied": "已复制",
|
|
||||||
"noAvatarSelected": "未选择角色",
|
|
||||||
"noAvatarToCopySelected": "未选择要复制的角色",
|
|
||||||
"pleaseSelectAtLeastOneProfile": "请至少选择一个配置档",
|
|
||||||
"pleaseEnterUid": "请输入 UID",
|
|
||||||
"failedToFetchEnkaData": "获取 Enka 数据失败",
|
|
||||||
"pleaseSelectAtLeastOneCharacter": "请至少选择一个角色",
|
|
||||||
"noDataToImport": "无可导入数据",
|
|
||||||
"pleaseSelectAFile": "请选择一个文件",
|
|
||||||
"fileMustBeAValidJsonFile": "文件必须为有效 JSON",
|
|
||||||
"importEnkaDataSuccess": "导入 Enka 数据成功",
|
|
||||||
"importFreeSRDataSuccess": "导入 FreeSR 数据成功",
|
|
||||||
"importDatabaseSuccess": "导入数据库成功",
|
|
||||||
"getData": "获取数据",
|
|
||||||
"import": "导入",
|
|
||||||
"freeSRImport": "导入 FreeSR",
|
|
||||||
"onlySupportFreeSRJsonFile": "仅支持 FreeSR JSON 文件",
|
|
||||||
"pickAFile": "选择文件",
|
|
||||||
"lightConeSetting": "光锥设置",
|
|
||||||
"relicMaker": "遗器制作",
|
|
||||||
"pleaseSelectAllOptions": "请选择所有选项",
|
|
||||||
"relicSavedSuccessfully": "遗器已成功保存",
|
|
||||||
"mainSettings": "主设置",
|
|
||||||
"mainStat": "主属性",
|
|
||||||
"set": "套装",
|
|
||||||
"pleaseSelectASet": "请选择一个套装",
|
|
||||||
"effectBonus": "效果加成",
|
|
||||||
"totalRoll": "总次数",
|
|
||||||
"randomizeStats": "随机属性",
|
|
||||||
"randomizeRolls": "随机次数",
|
|
||||||
"selectASubStat": "选择副属性",
|
|
||||||
"selectASet": "选择套装",
|
|
||||||
"selectAMainStat": "选择主属性",
|
|
||||||
"save": "保存",
|
|
||||||
"reset": "重置",
|
|
||||||
"roll": "滚动",
|
|
||||||
"step": "步数",
|
|
||||||
"memoryOfChaos": "混沌之忆",
|
|
||||||
"pureFiction": "虚构叙事",
|
|
||||||
"apocalypticShadow": "末日幻影",
|
|
||||||
"customEnemy": "自定义敌人",
|
|
||||||
"simulatedUniverse": "模拟宇宙",
|
|
||||||
"floor": "层数",
|
|
||||||
"side": "上/下半场",
|
|
||||||
"wave": "波次",
|
|
||||||
"stage": "关卡",
|
|
||||||
"useCycleCount": "使用轮次数?",
|
|
||||||
"useTurbulenceBuff": "使用紊乱增益?",
|
|
||||||
"firstHalfEnemies": "上半场敌人",
|
|
||||||
"secondHalfEnemies": "下半场敌人",
|
|
||||||
"listEnemies": "敌人列表",
|
|
||||||
"turbulenceBuff": "紊乱增益",
|
|
||||||
"noEventSelected": "未选择事件",
|
|
||||||
"noTurbulenceBuff": "未选择紊乱增益",
|
|
||||||
"upper": "上半",
|
|
||||||
"lower": "下半",
|
|
||||||
"upperToLower": "上半 -> 下半",
|
|
||||||
"lowerToUpper": "下半 -> 上半",
|
|
||||||
"selectMOCEvent": "选择 MOC 事件",
|
|
||||||
"selectPFEvent": "选择 PF 事件",
|
|
||||||
"selectASEvent": "选择 AS 事件",
|
|
||||||
"selectCEEvent": "选择 CE 事件",
|
|
||||||
"selectEvent": "选择事件",
|
|
||||||
"selectFloor": "选择层数",
|
|
||||||
"selectSide": "选择上/下半场",
|
|
||||||
"selectBuff": "选择 buff",
|
|
||||||
"selectStage": "选择关卡",
|
|
||||||
"previous": "上一页",
|
|
||||||
"next": "下一页",
|
|
||||||
"noMonstersFound": "未找到怪物",
|
|
||||||
"addNewWave": "添加新波次",
|
|
||||||
"searchStage": "搜索关卡...",
|
|
||||||
"noStageFound": "未找到关卡",
|
|
||||||
"searchMonster": "搜索怪物...",
|
|
||||||
"changeRelic": "更换遗物",
|
|
||||||
"deleteRelic": "删除遗物",
|
|
||||||
"deleteRelicConfirm": "确定要删除插槽中的遗物吗",
|
|
||||||
"setEffects": "设置效果",
|
|
||||||
"details": "详情",
|
|
||||||
"normal": "普通攻击",
|
|
||||||
"bpskill": "技能",
|
|
||||||
"maze": "技巧",
|
|
||||||
"ultra": "终结技",
|
|
||||||
"servantskill": "记灵技能",
|
|
||||||
"severaltalent": "记灵天赋",
|
|
||||||
"singleattack": "单体攻击",
|
|
||||||
"enhance": "强化",
|
|
||||||
"summon": "召唤",
|
|
||||||
"blast": "爆裂",
|
|
||||||
"restore": "恢复",
|
|
||||||
"support": "支援",
|
|
||||||
"aoeattack": "范围攻击",
|
|
||||||
"mazeattack": "迷宫秘技",
|
|
||||||
"impair": "削弱",
|
|
||||||
"active": "活跃",
|
|
||||||
"inactive": "不活跃",
|
|
||||||
"maxAll": "全部最大化",
|
|
||||||
"defence": "防御",
|
|
||||||
"maxAllSuccess": "技能等级已成功设置为最大。",
|
|
||||||
"maxAllFailed": "设置技能等级为最大失败。",
|
|
||||||
"noRelicEquipped": "未装备圣遗物",
|
|
||||||
"anomalyArbitration": "异相仲裁",
|
|
||||||
"normalMode": "普通模式",
|
|
||||||
"hardMode": "困难模式",
|
|
||||||
"selectPEAKEvent": "选择 PEAK 事件",
|
|
||||||
"mode": "模式",
|
|
||||||
"selectMode": "选择模式",
|
|
||||||
"rollBack": "回到之前的状态",
|
|
||||||
"upRoll": "增加副属性",
|
|
||||||
"downRoll": "减少副属性",
|
|
||||||
"actions": "操作",
|
|
||||||
"avatars": "头像",
|
|
||||||
"quickView": "快速预览",
|
|
||||||
"extraSetting": "额外设置",
|
|
||||||
"disableCensorship": "禁用审查",
|
|
||||||
"hideUI": "隐藏界面",
|
|
||||||
"theoryCraftMode": "Theory Craft 模式",
|
|
||||||
"cycleCount": "循环次数",
|
|
||||||
"pleaseSelectAllSubStats": "请选取所有副属性",
|
|
||||||
"subStatRollCountCannotBeZero": "副属性的行数不能为0",
|
|
||||||
"theoryCraft": "Theory Craft",
|
|
||||||
"multipathCharacter": "多命途角色",
|
|
||||||
"mainPath": "主角命途",
|
|
||||||
"march7Path": "三月七命途",
|
|
||||||
"challenge": "挑战",
|
|
||||||
"skipNode": "跳过节点",
|
|
||||||
"disableSkip": "禁用跳过",
|
|
||||||
"skipNode1": "跳过节点1",
|
|
||||||
"skipNode2": "跳过节点2",
|
|
||||||
"extraFeatures": "附加功能",
|
|
||||||
"detailTheoryCraft": "开启后可自定义循环数,并在敌人设置中调整生命值。",
|
|
||||||
"detailSkipNode": "开启后可跳过混沌回忆或虚构叙事的(节点1/节点2)。",
|
|
||||||
"detailChallengePeak": "允许更改当前异相中的「巅峰」赛季。",
|
|
||||||
"detailHiddenUi": "开启后将隐藏游戏界面。",
|
|
||||||
"detailDisableCensorship": "开启后将关闭游戏内的审查。",
|
|
||||||
"detailMultipathCharacter": "允许更改部分角色的命途。",
|
|
||||||
"trailblazer": "开拓者",
|
|
||||||
"listExtraEffect": "额外效果列表",
|
|
||||||
"extra": "额外"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -72,6 +72,7 @@
|
|||||||
"connectionType": "Connection Type",
|
"connectionType": "Connection Type",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"connectPs": "Connect PS",
|
"connectPs": "Connect PS",
|
||||||
|
"disconnect": "Disconnect",
|
||||||
"other": "Other",
|
"other": "Other",
|
||||||
"freeSr": "FreeSR",
|
"freeSr": "FreeSR",
|
||||||
"database": "Database",
|
"database": "Database",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"connectionType": "接続タイプ",
|
"connectionType": "接続タイプ",
|
||||||
"status": "ステータス",
|
"status": "ステータス",
|
||||||
"connectPs": "PS接続",
|
"connectPs": "PS接続",
|
||||||
|
"disconnect": "切断",
|
||||||
"other": "その他",
|
"other": "その他",
|
||||||
"freeSr": "FreeSR",
|
"freeSr": "FreeSR",
|
||||||
"database": "データベース",
|
"database": "データベース",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"connectionType": "연결 타입",
|
"connectionType": "연결 타입",
|
||||||
"status": "상태",
|
"status": "상태",
|
||||||
"connectPs": "PS 연결",
|
"connectPs": "PS 연결",
|
||||||
|
"disconnect": "연결 끊기",
|
||||||
"other": "기타",
|
"other": "기타",
|
||||||
"freeSr": "FreeSR",
|
"freeSr": "FreeSR",
|
||||||
"database": "데이터베이스",
|
"database": "데이터베이스",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"connectionType": "Loại kết nối",
|
"connectionType": "Loại kết nối",
|
||||||
"status": "Trạng thái",
|
"status": "Trạng thái",
|
||||||
"connectPs": "Kết nối PS",
|
"connectPs": "Kết nối PS",
|
||||||
|
"disconnect": "Ngắt kết nối",
|
||||||
"other": "Khác",
|
"other": "Khác",
|
||||||
"freeSr": "FreeSR",
|
"freeSr": "FreeSR",
|
||||||
"database": "Database",
|
"database": "Database",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"connectionType": "连接类型",
|
"connectionType": "连接类型",
|
||||||
"status": "状态",
|
"status": "状态",
|
||||||
"connectPs": "连接 PS",
|
"connectPs": "连接 PS",
|
||||||
|
"disconnect": "断开连接",
|
||||||
"other": "其他",
|
"other": "其他",
|
||||||
"freeSr": "FreeSR",
|
"freeSr": "FreeSR",
|
||||||
"database": "数据库",
|
"database": "数据库",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { connectToPS, syncDataToPS } from "@/helper"
|
import { connectToPS, syncDataToPS } from "@/helper"
|
||||||
import useConnectStore from "@/stores/connectStore"
|
import useConnectStore from "@/stores/connectStore"
|
||||||
import useGlobalStore from "@/stores/globalStore"
|
import useGlobalStore from "@/stores/globalStore"
|
||||||
|
import { PSConnectType } from "@/types"
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
||||||
@@ -21,11 +22,10 @@ export default function ConnectBar() {
|
|||||||
setUsername,
|
setUsername,
|
||||||
setPassword
|
setPassword
|
||||||
} = useConnectStore()
|
} = useConnectStore()
|
||||||
const { isConnectPS } = useGlobalStore()
|
const { isConnectPS, setIsConnectPS } = useGlobalStore()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-6 py-4">
|
<div className="px-6 py-4">
|
||||||
{/* Select connection type */}
|
|
||||||
<div className="form-control grid grid-cols-1 w-full mb-6">
|
<div className="form-control grid grid-cols-1 w-full mb-6">
|
||||||
<label className="label">
|
<label className="label">
|
||||||
<span className="label-text font-semibold text-purple-300">{transI18n("connectionType")}</span>
|
<span className="label-text font-semibold text-purple-300">{transI18n("connectionType")}</span>
|
||||||
@@ -33,15 +33,18 @@ export default function ConnectBar() {
|
|||||||
<select
|
<select
|
||||||
className="select w-full select-bordered border-purple-500/30 focus:border-purple-500 bg-base-200 mt-1"
|
className="select w-full select-bordered border-purple-500/30 focus:border-purple-500 bg-base-200 mt-1"
|
||||||
value={connectionType}
|
value={connectionType}
|
||||||
onChange={(e) => setConnectionType(e.target.value)}
|
onChange={(e) => {
|
||||||
|
setIsConnectPS(false)
|
||||||
|
setConnectionType(e.target.value)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<option value="FireflyGo">FireflyGo</option>
|
<option value={PSConnectType.FireflyGo}>FireflyGo</option>
|
||||||
<option value="Other">{transI18n("other")}</option>
|
<option value={PSConnectType.RobinSR}>RobinSR</option>
|
||||||
|
<option value={PSConnectType.Other}>{transI18n("other")}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Show host/port if Other */}
|
{connectionType === PSConnectType.Other && (
|
||||||
{connectionType === "Other" && (
|
|
||||||
<div className="flex flex-col md:space-x-4 mb-6 gap-2">
|
<div className="flex flex-col md:space-x-4 mb-6 gap-2">
|
||||||
<div className="form-control w-full mb-4 md:mb-0">
|
<div className="form-control w-full mb-4 md:mb-0">
|
||||||
<label className="label">
|
<label className="label">
|
||||||
@@ -105,7 +108,6 @@ export default function ConnectBar() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6 mb-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6 mb-2">
|
||||||
{/* Status */}
|
|
||||||
<div className="flex items-center justify-center md:justify-start">
|
<div className="flex items-center justify-center md:justify-start">
|
||||||
<span className="text-md mr-2">{transI18n("status")}:</span>
|
<span className="text-md mr-2">{transI18n("status")}:</span>
|
||||||
<span
|
<span
|
||||||
@@ -114,6 +116,15 @@ export default function ConnectBar() {
|
|||||||
>
|
>
|
||||||
{isConnectPS ? transI18n("connected") : transI18n("unconnected")}
|
{isConnectPS ? transI18n("connected") : transI18n("unconnected")}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
{isConnectPS && (
|
||||||
|
<span
|
||||||
|
className={`badge ${isConnectPS ? "badge-success" : "badge-error"
|
||||||
|
} badge-lg`}
|
||||||
|
>
|
||||||
|
{isConnectPS ? transI18n("connected") : transI18n("unconnected")}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Buttons */}
|
{/* Buttons */}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export const listCurrentLanguage = {
|
export const listCurrentLanguage = {
|
||||||
ja: "JP",
|
ja: "JP",
|
||||||
ko: "KR",
|
ko: "KR",
|
||||||
en: "US",
|
en: "EN",
|
||||||
vi: "VN",
|
vi: "VN",
|
||||||
zh: "CN"
|
zh: "CN"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,111 +5,101 @@ import useUserDataStore from "@/stores/userDataStore"
|
|||||||
import { converterToFreeSRJson } from "./converterToFreeSRJson"
|
import { converterToFreeSRJson } from "./converterToFreeSRJson"
|
||||||
import { psResponseSchema } from "@/zod"
|
import { psResponseSchema } from "@/zod"
|
||||||
import useGlobalStore from "@/stores/globalStore"
|
import useGlobalStore from "@/stores/globalStore"
|
||||||
|
import { ActionResult, ExtraData, ProxyPayload, ProxyResponse, PSConnectType, PSResponse } from "@/types"
|
||||||
|
|
||||||
export const connectToPS = async (): Promise<{ success: boolean, message: string }> => {
|
|
||||||
const {
|
|
||||||
connectionType,
|
|
||||||
privateType,
|
|
||||||
serverUrl,
|
|
||||||
username,
|
|
||||||
password
|
|
||||||
} = useConnectStore.getState()
|
|
||||||
const { setExtraData, setIsConnectPS } = useGlobalStore.getState()
|
|
||||||
|
|
||||||
let urlQuery = serverUrl
|
const getUrlQuery = (connectionType: PSConnectType | string, serverUrl: string): string => {
|
||||||
if (!urlQuery.startsWith("http://") && !urlQuery.startsWith("https://")) {
|
if (connectionType === PSConnectType.FireflyGo) return "http://localhost:21000/sync"
|
||||||
urlQuery = `http://${urlQuery}`
|
if (connectionType === PSConnectType.RobinSR) return "http://localhost:21000/srtools"
|
||||||
}
|
|
||||||
if (connectionType === "FireflyGo") {
|
if (!serverUrl.startsWith("http://") && !serverUrl.startsWith("https://")) {
|
||||||
urlQuery = "http://localhost:21000/sync"
|
return `http://${serverUrl}`
|
||||||
} else if (connectionType === "Other" && privateType === "Server") {
|
|
||||||
const response = await SendDataThroughProxy({data: {username, password, serverUrl, data: null, method: "POST"}})
|
|
||||||
if (response instanceof Error) {
|
|
||||||
return { success: false, message: response.message }
|
|
||||||
} else if (response.error) {
|
|
||||||
return { success: false, message: response.error }
|
|
||||||
} else {
|
|
||||||
const parsed = psResponseSchema.safeParse(response.data)
|
|
||||||
if (!parsed.success) {
|
|
||||||
return { success: false, message: "Invalid response schema" }
|
|
||||||
}
|
|
||||||
return { success: true, message: "" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const response = await SendDataToServer(username, password, urlQuery, null)
|
|
||||||
if (typeof response === "string") {
|
|
||||||
setIsConnectPS(false)
|
|
||||||
return { success: false, message: response }
|
|
||||||
} else if (response.status != 200) {
|
|
||||||
setIsConnectPS(false)
|
|
||||||
return { success: false, message: response.message }
|
|
||||||
} else {
|
|
||||||
setIsConnectPS(true)
|
|
||||||
|
|
||||||
setExtraData(response?.extra_data)
|
|
||||||
return { success: true, message: "" }
|
|
||||||
}
|
}
|
||||||
|
return serverUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
export const syncDataToPS = async (): Promise<{ success: boolean, message: string }> => {
|
const handleProxyRequest = async (payload: ProxyPayload): Promise<ActionResult> => {
|
||||||
const {
|
const response = await SendDataThroughProxy({
|
||||||
connectionType,
|
data: { ...payload, method: "POST" }
|
||||||
privateType,
|
}) as ProxyResponse | Error
|
||||||
serverUrl,
|
|
||||||
username,
|
if (response instanceof Error) {
|
||||||
password
|
return { success: false, message: response.message }
|
||||||
} = useConnectStore.getState()
|
|
||||||
|
|
||||||
const {extraData, setIsConnectPS, setExtraData, isEnableChangePath, isEnableLua} = useGlobalStore.getState()
|
|
||||||
|
|
||||||
|
|
||||||
const {avatars, battle_type, moc_config, pf_config, as_config, ce_config, peak_config} = useUserDataStore.getState()
|
|
||||||
const data = converterToFreeSRJson(avatars, battle_type, moc_config, pf_config, as_config, ce_config, peak_config)
|
|
||||||
|
|
||||||
let urlQuery = serverUrl
|
|
||||||
if (!urlQuery.startsWith("http://") && !urlQuery.startsWith("https://")) {
|
|
||||||
urlQuery = `http://${urlQuery}`
|
|
||||||
}
|
|
||||||
if (connectionType === "FireflyGo") {
|
|
||||||
urlQuery = "http://localhost:21000/sync"
|
|
||||||
} else if (connectionType === "Other" && privateType === "Server") {
|
|
||||||
const response = await SendDataThroughProxy({data: {username, password, serverUrl, data, method: "POST"}})
|
|
||||||
if (response instanceof Error) {
|
|
||||||
return { success: false, message: response.message }
|
|
||||||
} else if (response.error) {
|
|
||||||
return { success: false, message: response.error }
|
|
||||||
} else {
|
|
||||||
const parsed = psResponseSchema.safeParse(response.data)
|
|
||||||
if (!parsed.success) {
|
|
||||||
return { success: false, message: "Invalid response schema" }
|
|
||||||
}
|
|
||||||
return { success: true, message: "" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const newExtra = structuredClone(extraData)
|
|
||||||
|
|
||||||
if (newExtra && !isEnableChangePath) {
|
|
||||||
newExtra.multi_path = undefined
|
|
||||||
}
|
}
|
||||||
|
if (response.error) {
|
||||||
if (newExtra && !isEnableLua) {
|
return { success: false, message: response.error }
|
||||||
newExtra.lua = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const parsed = psResponseSchema.safeParse(response.data)
|
||||||
|
if (!parsed.success) {
|
||||||
|
return { success: false, message: "Invalid response schema" }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true, message: "" }
|
||||||
|
}
|
||||||
|
|
||||||
const response = await SendDataToServer(username, password, urlQuery, data, newExtra)
|
const handleDirectServerResponse = (
|
||||||
|
response: PSResponse | string,
|
||||||
|
setIsConnectPS: (val: boolean) => void,
|
||||||
|
onSuccess: (extraData?: ExtraData) => void
|
||||||
|
): ActionResult => {
|
||||||
if (typeof response === "string") {
|
if (typeof response === "string") {
|
||||||
setIsConnectPS(false)
|
setIsConnectPS(false)
|
||||||
return { success: false, message: response }
|
return { success: false, message: response }
|
||||||
} else if (response.status != 200) {
|
}
|
||||||
|
if (response.status !== 200) {
|
||||||
setIsConnectPS(false)
|
setIsConnectPS(false)
|
||||||
return { success: false, message: response.message }
|
return { success: false, message: response.message }
|
||||||
} else {
|
}
|
||||||
setIsConnectPS(true)
|
|
||||||
const newData = structuredClone(response?.extra_data)
|
setIsConnectPS(true)
|
||||||
|
onSuccess(response?.extra_data)
|
||||||
|
return { success: true, message: "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const connectToPS = async (): Promise<ActionResult> => {
|
||||||
|
const { connectionType, privateType, serverUrl, username, password } = useConnectStore.getState()
|
||||||
|
const { setExtraData, setIsConnectPS } = useGlobalStore.getState()
|
||||||
|
|
||||||
|
if (connectionType === "Other" && privateType === "Server") {
|
||||||
|
return handleProxyRequest({ username, password, serverUrl, data: undefined })
|
||||||
|
}
|
||||||
|
|
||||||
|
const urlQuery = getUrlQuery(connectionType, serverUrl)
|
||||||
|
const response = await SendDataToServer(username, password, urlQuery, undefined)
|
||||||
|
|
||||||
|
return handleDirectServerResponse(response, setIsConnectPS, (extraData) => {
|
||||||
|
setExtraData(extraData)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const syncDataToPS = async (): Promise<ActionResult> => {
|
||||||
|
const { connectionType, privateType, serverUrl, username, password } = useConnectStore.getState()
|
||||||
|
const { extraData, setIsConnectPS, setExtraData, isEnableChangePath, isEnableLua } = useGlobalStore.getState()
|
||||||
|
const { avatars, battle_type, moc_config, pf_config, as_config, ce_config, peak_config } = useUserDataStore.getState()
|
||||||
|
|
||||||
|
const data = converterToFreeSRJson(avatars, battle_type, moc_config, pf_config, as_config, ce_config, peak_config)
|
||||||
|
|
||||||
|
if (connectionType === "Other" && privateType === "Server") {
|
||||||
|
return handleProxyRequest({ username, password, serverUrl, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
const urlQuery = getUrlQuery(connectionType, serverUrl)
|
||||||
|
|
||||||
|
const payloadExtra: PSResponse['extra_data'] = structuredClone(extraData)
|
||||||
|
if (payloadExtra) {
|
||||||
|
if (!isEnableChangePath) payloadExtra.multi_path = undefined
|
||||||
|
if (!isEnableLua) payloadExtra.lua = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await SendDataToServer(username, password, urlQuery, data, payloadExtra)
|
||||||
|
|
||||||
|
return handleDirectServerResponse(response, setIsConnectPS, (responseExtraData) => {
|
||||||
|
const newData = structuredClone(responseExtraData)
|
||||||
if (newData) {
|
if (newData) {
|
||||||
newData.lua = extraData?.lua || null
|
newData.lua = extraData?.lua || null
|
||||||
}
|
}
|
||||||
setExtraData(newData)
|
setExtraData(newData)
|
||||||
return { success: true, message: "" }
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
|
import useConnectStore from "@/stores/connectStore";
|
||||||
import useDetailDataStore from "@/stores/detailDataStore";
|
import useDetailDataStore from "@/stores/detailDataStore";
|
||||||
import { ASConfigStore, AvatarJson, AvatarStore, BattleConfigJson, CEConfigStore, FreeSRJson, LightconeJson, MOCConfigStore, PEAKConfigStore, PFConfigStore, RelicJson } from "@/types";
|
import { ASConfigStore, AvatarJson, AvatarStore, BattleConfigJson, CEConfigStore, FreeSRJson, LightconeJson, MOCConfigStore, PEAKConfigStore, PFConfigStore, PSConnectType, RelicJson } from "@/types";
|
||||||
|
|
||||||
|
|
||||||
export function converterToFreeSRJson(
|
export function converterToFreeSRJson(
|
||||||
@@ -13,6 +14,7 @@ export function converterToFreeSRJson(
|
|||||||
peak_config: PEAKConfigStore,
|
peak_config: PEAKConfigStore,
|
||||||
): FreeSRJson {
|
): FreeSRJson {
|
||||||
const { skillConfig } = useDetailDataStore.getState()
|
const { skillConfig } = useDetailDataStore.getState()
|
||||||
|
const { connectionType } = useConnectStore.getState()
|
||||||
const lightcones: LightconeJson[] = []
|
const lightcones: LightconeJson[] = []
|
||||||
const relics: RelicJson[] = []
|
const relics: RelicJson[] = []
|
||||||
let battleJson: BattleConfigJson
|
let battleJson: BattleConfigJson
|
||||||
@@ -48,7 +50,7 @@ export function converterToFreeSRJson(
|
|||||||
}
|
}
|
||||||
} else if (battle_type === "CE") {
|
} else if (battle_type === "CE") {
|
||||||
battleJson = {
|
battleJson = {
|
||||||
battle_type: battle_type,
|
battle_type: connectionType === PSConnectType.FireflyGo ? battle_type : "DEFAULT",
|
||||||
blessings: ce_config.blessings,
|
blessings: ce_config.blessings,
|
||||||
custom_stats: [],
|
custom_stats: [],
|
||||||
cycle_count: ce_config.cycle_count,
|
cycle_count: ce_config.cycle_count,
|
||||||
@@ -58,7 +60,7 @@ export function converterToFreeSRJson(
|
|||||||
}
|
}
|
||||||
} else if (battle_type === "PEAK") {
|
} else if (battle_type === "PEAK") {
|
||||||
battleJson = {
|
battleJson = {
|
||||||
battle_type: battle_type,
|
battle_type: connectionType === PSConnectType.FireflyGo ? battle_type : "DEFAULT",
|
||||||
blessings: peak_config.blessings,
|
blessings: peak_config.blessings,
|
||||||
custom_stats: [],
|
custom_stats: [],
|
||||||
cycle_count: peak_config.cycle_count,
|
cycle_count: peak_config.cycle_count,
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export async function SendDataToServer(
|
|||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
serverUrl: string,
|
serverUrl: string,
|
||||||
data: FreeSRJson | null,
|
data?: FreeSRJson,
|
||||||
extraData?: ExtraData
|
extraData?: ExtraData
|
||||||
): Promise<PSResponse | string> {
|
): Promise<PSResponse | string> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ export * from "./modelConfig"
|
|||||||
export * from "./metaData"
|
export * from "./metaData"
|
||||||
export * from "./monsterDetail"
|
export * from "./monsterDetail"
|
||||||
export * from "./filter"
|
export * from "./filter"
|
||||||
export * from "./metaData"
|
export * from "./metaData"
|
||||||
|
export * from "./psConnect"
|
||||||
32
src/types/psConnect.ts
Normal file
32
src/types/psConnect.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { ExtraData } from "./extraData";
|
||||||
|
import { FreeSRJson } from "./srtools";
|
||||||
|
|
||||||
|
export enum PSConnectType {
|
||||||
|
FireflyGo = "FireflyGo",
|
||||||
|
RobinSR = "RobinSR",
|
||||||
|
Other = "Other",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProxyPayload {
|
||||||
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
serverUrl: string;
|
||||||
|
data?: FreeSRJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProxyResponse {
|
||||||
|
error?: string;
|
||||||
|
message?: string;
|
||||||
|
data?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PSResponse {
|
||||||
|
status: number;
|
||||||
|
message: string;
|
||||||
|
extra_data?: ExtraData
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ActionResult {
|
||||||
|
success: boolean;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
import { ExtraData } from "./extraData";
|
|
||||||
|
|
||||||
export interface SubAffix {
|
export interface SubAffix {
|
||||||
sub_affix_id: number;
|
sub_affix_id: number;
|
||||||
count: number;
|
count: number;
|
||||||
@@ -81,9 +79,4 @@ export interface FreeSRJson {
|
|||||||
loadout?: LoadoutJson[];
|
loadout?: LoadoutJson[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PSResponse {
|
|
||||||
status: number;
|
|
||||||
message: string;
|
|
||||||
extra_data?: ExtraData
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user