Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src-tauri/src/account/helpers/import/hmcl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,26 @@ async fn microsoft_to_player(
app: &AppHandle,
acc: &HmclMicrosoftAccount,
) -> SJMCLResult<PlayerInfo> {
let profile = fetch_minecraft_profile(app, acc.access_token.clone()).await?;
let profile_result = fetch_minecraft_profile(app, acc.access_token.clone()).await;
let profile = match profile_result {
Ok(p) => p,
Err(_) => {
return Ok(
PlayerInfo {
id: "".to_string(),
uuid: Uuid::from_str(&acc.uuid).map_err(|_| AccountError::ParseError)?,
name: acc.display_name.clone(),
player_type: PlayerType::Microsoft,
auth_account: None,
access_token: Some("%failed:access_token_expired%".to_string()),
refresh_token: Some(acc.refresh_token.clone()),
textures: load_preset_skin(app, PresetRole::Steve)?,
auth_server_url: None,
}
.with_generated_id(),
);
}
};

let mut textures = vec![];
if let Some(skins) = &profile.skins {
Expand Down
49 changes: 35 additions & 14 deletions src/components/modals/import-account-info-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from "@chakra-ui/react";
import React, { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { LuTriangleAlert } from "react-icons/lu";
import { LuCircleX, LuTriangleAlert } from "react-icons/lu";
import { BeatLoader } from "react-spinners";
import Empty from "@/components/common/empty";
import { OptionItemGroup } from "@/components/common/option-item";
Expand All @@ -31,7 +31,10 @@ import { useToast } from "@/contexts/toast";
import { ImportLauncherType, PlayerType } from "@/enums/account";
import { AuthServer, Player } from "@/models/account";
import { AccountService } from "@/services/account";
import { generatePlayerDesc } from "@/utils/account";
import {
EXPIRED_ACCESS_TOKEN_PLACEHOLDER,
generatePlayerDesc,
} from "@/utils/account";

interface ImportAccountInfoModalProps extends Omit<ModalProps, "children"> {
currAuthServers?: AuthServer[];
Expand Down Expand Up @@ -75,6 +78,8 @@ const ImportAccountInfoModal: React.FC<ImportAccountInfoModalProps> = ({

const isThirdParty = (p: Player) =>
p.playerType === PlayerType.ThirdParty && !!p.authServer?.authUrl;
const isExpired = (p: Player) =>
p.accessToken === EXPIRED_ACCESS_TOKEN_PLACEHOLDER;

const handleRetrieveOtherLauncherAccountInfo = useCallback(
(type: ImportLauncherType) => {
Expand All @@ -99,9 +104,9 @@ const ImportAccountInfoModal: React.FC<ImportAccountInfoModalProps> = ({
const pid = String((p as any).id);
if (isThirdParty(p)) {
nextPlayerChecked[pid] =
!!nextServerChecked[p.authServer!.authUrl];
!!nextServerChecked[p.authServer!.authUrl] && !isExpired(p);
} else {
nextPlayerChecked[pid] = true;
nextPlayerChecked[pid] = !isExpired(p);
}
});
setPlayerChecked(nextPlayerChecked);
Expand Down Expand Up @@ -156,6 +161,7 @@ const ImportAccountInfoModal: React.FC<ImportAccountInfoModalProps> = ({
const selectedPlayers = newPlayers.filter((p) => {
const pid = String((p as any).id);
if (!playerChecked[pid]) return false;
if (isExpired(p)) return false;

if (isThirdParty(p)) {
return !!serverChecked[p.authServer!.authUrl];
Expand Down Expand Up @@ -305,7 +311,7 @@ const ImportAccountInfoModal: React.FC<ImportAccountInfoModalProps> = ({
<Checkbox
colorScheme={primaryColor}
isChecked={!!playerChecked[pid]}
isDisabled={!serverEnabled}
isDisabled={!serverEnabled || isExpired(p)}
onChange={(e) =>
setPlayerChecked((prev) => ({
...prev,
Expand All @@ -319,16 +325,31 @@ const ImportAccountInfoModal: React.FC<ImportAccountInfoModalProps> = ({
/>
</HStack>
),
children: isInCurPlayers(p) && (
<Tooltip
label={t(
"ImportAccountInfoModal.tooltips.existingPlayer"
children: (
<HStack>
{isInCurPlayers(p) && (
<Tooltip
label={t(
"ImportAccountInfoModal.tooltips.existingPlayer"
)}
>
<Box color="orange.500">
<LuTriangleAlert />
</Box>
</Tooltip>
)}
>
<Box color="orange.500">
<LuTriangleAlert />
</Box>
</Tooltip>
{isExpired(p) && (
<Tooltip
label={t(
"ImportAccountInfoModal.tooltips.expired"
)}
>
<Box color="red.500">
<LuCircleX />
</Box>
</Tooltip>
)}
</HStack>
),
};
})}
Expand Down
5 changes: 3 additions & 2 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,8 @@
},
"tooltips": {
"existingServer": "Existing auth server data with the same address will be overwritten.",
"existingPlayer": "Existing player data with the same UUID will be overwritten."
"existingPlayer": "Existing player data with the same UUID will be overwritten.",
"expired": "This player token has expired and cannot be imported."
}
},
"ImportModpackModal": {
Expand Down Expand Up @@ -2611,4 +2612,4 @@
"title": "World Level Data - {{worldName}}"
}
}
}
}
5 changes: 3 additions & 2 deletions src/locales/zh-Hans.json
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,8 @@
},
"tooltips": {
"existingServer": "已存在相同地址的认证服务器,导入将会覆盖数据",
"existingPlayer": "已存在相同 UUID 的角色,导入将会覆盖数据"
"existingPlayer": "已存在相同 UUID 的角色,导入将会覆盖数据",
"expired": "登录令牌已过期,无法导入此角色"
}
},
"ImportModpackModal": {
Expand Down Expand Up @@ -2611,4 +2612,4 @@
"title": "世界基础数据 - {{worldName}}"
}
}
}
}
2 changes: 2 additions & 0 deletions src/utils/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { t } from "i18next";
import { PlayerType } from "@/enums/account";
import { Player } from "@/models/account";

export const EXPIRED_ACCESS_TOKEN_PLACEHOLDER = "%failed:access_token_expired%";

export function isUuidValid(uuid: string) {
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
uuid
Expand Down
Loading