Skip to content

Commit af877d6

Browse files
refactor: move Ravealts into Add Accounts dropdown under Alt Providers
Moves the Ravealts purchase button from a standalone toolbar button into the "Add Accounts" dropdown menu as an "Alt Providers" section between Java Edition and Bedrock Edition. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 938ddf8 commit af877d6

File tree

2 files changed

+127
-156
lines changed

2 files changed

+127
-156
lines changed

locales/en-US/instance.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
"microsoftRefreshToken": "Microsoft Refresh Token",
119119
"microsoftCookies": "Microsoft Cookies",
120120
"microsoftAccessToken": "Microsoft Access Token",
121+
"altProviders": "Alt Providers",
121122
"dialog": {
122123
"title": "Import {{type}} accounts",
123124
"description": "Paste your accounts here, one per line"

src/routes/_dashboard/instance/$instance/accounts.tsx

Lines changed: 126 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -201,161 +201,6 @@ function GenerateAccountsButton() {
201201
);
202202
}
203203

204-
function RavealtsButton() {
205-
const { t } = useTranslation("instance");
206-
const queryClient = useQueryClient();
207-
const { instanceInfoQueryOptions } = Route.useRouteContext();
208-
const transport = use(TransportContext);
209-
const { data: instanceInfo } = useSuspenseQuery(instanceInfoQueryOptions);
210-
const { trackEvent } = useAptabase();
211-
const [dialogOpen, setDialogOpen] = useState(false);
212-
213-
const { mutateAsync: addAccountsBatchMutation } = useMutation({
214-
mutationKey: [
215-
"instance",
216-
"accounts",
217-
"add-batch-ravealts",
218-
instanceInfo.id,
219-
],
220-
scope: { id: `instance-accounts-${instanceInfo.id}` },
221-
mutationFn: async (accounts: ProfileAccount[]) => {
222-
await addInstanceAccountsBatch(
223-
accounts,
224-
instanceInfo,
225-
transport,
226-
queryClient,
227-
instanceInfoQueryOptions.queryKey,
228-
);
229-
},
230-
onSettled: async () => {
231-
await queryClient.invalidateQueries({
232-
queryKey: instanceInfoQueryOptions.queryKey,
233-
});
234-
},
235-
});
236-
237-
const handleImportAccounts = useCallback(
238-
(payload: string[], credentialType: AccountTypeCredentials) => {
239-
if (transport === null) return;
240-
241-
void trackEvent("ravealts_purchase", {
242-
count: payload.length,
243-
type: credentialType,
244-
});
245-
246-
const service = new MCAuthServiceClient(transport);
247-
const abortController = new AbortController();
248-
const loadingData: ExternalToast = {
249-
cancel: {
250-
label: t("common:cancel"),
251-
onClick: () => {
252-
abortController.abort();
253-
},
254-
},
255-
};
256-
const total = payload.length;
257-
let failed = 0;
258-
let success = 0;
259-
const accountsToAdd: ProfileAccount[] = [];
260-
const loadingReport = () =>
261-
t("account.listImportToast.loading", {
262-
checked: success + failed,
263-
total,
264-
success,
265-
failed,
266-
});
267-
const toastId = toast.loading(loadingReport(), loadingData);
268-
const { responses } = service.loginCredentials(
269-
{
270-
instanceId: instanceInfo.id,
271-
service: credentialType,
272-
payload,
273-
},
274-
{
275-
abort: abortController.signal,
276-
},
277-
);
278-
responses.onMessage((r) => {
279-
runAsync(async () => {
280-
const data = r.data;
281-
switch (data.oneofKind) {
282-
case "oneSuccess": {
283-
if (abortController.signal.aborted) return;
284-
if (data.oneSuccess.account) {
285-
accountsToAdd.push(data.oneSuccess.account);
286-
}
287-
success++;
288-
toast.loading(loadingReport(), {
289-
id: toastId,
290-
...loadingData,
291-
});
292-
break;
293-
}
294-
case "oneFailure": {
295-
if (abortController.signal.aborted) return;
296-
failed++;
297-
toast.loading(loadingReport(), {
298-
id: toastId,
299-
...loadingData,
300-
});
301-
break;
302-
}
303-
case "end": {
304-
if (accountsToAdd.length > 0) {
305-
await addAccountsBatchMutation(accountsToAdd);
306-
}
307-
if (accountsToAdd.length === 0) {
308-
toast.error(t("account.listImportToast.allFailed"), {
309-
id: toastId,
310-
cancel: undefined,
311-
});
312-
} else if (failed > 0) {
313-
toast.warning(
314-
t("account.listImportToast.someFailed", {
315-
count: accountsToAdd.length,
316-
failed,
317-
}),
318-
{ id: toastId, cancel: undefined },
319-
);
320-
} else {
321-
toast.success(
322-
t("account.listImportToast.noneFailed", {
323-
count: accountsToAdd.length,
324-
}),
325-
{ id: toastId, cancel: undefined },
326-
);
327-
}
328-
break;
329-
}
330-
}
331-
});
332-
});
333-
responses.onError((e) => {
334-
console.error(e);
335-
toast.error(t("account.listImportToast.error"), {
336-
id: toastId,
337-
cancel: undefined,
338-
});
339-
});
340-
},
341-
[instanceInfo.id, addAccountsBatchMutation, t, transport, trackEvent],
342-
);
343-
344-
return (
345-
<>
346-
<Button variant="outline" size="sm" onClick={() => setDialogOpen(true)}>
347-
<ShoppingCartIcon />
348-
{t("account.ravealts.button")}
349-
</Button>
350-
<RavealtsDialog
351-
open={dialogOpen}
352-
onOpenChange={setDialogOpen}
353-
onImportAccounts={handleImportAccounts}
354-
/>
355-
</>
356-
);
357-
}
358-
359204
export const Route = createFileRoute("/_dashboard/instance/$instance/accounts")(
360205
{
361206
validateSearch: dataTableValidateSearch,
@@ -607,6 +452,114 @@ function AddButton() {
607452
);
608453
const [pendingDeviceCodeType, setPendingDeviceCodeType] =
609454
useState<AccountTypeDeviceCode | null>(null);
455+
const [ravealtsDialogOpen, setRavealtsDialogOpen] = useState(false);
456+
457+
const handleRavealtsImport = useCallback(
458+
(payload: string[], credentialType: AccountTypeCredentials) => {
459+
if (transport === null) return;
460+
461+
void trackEvent("ravealts_purchase", {
462+
count: payload.length,
463+
type: credentialType,
464+
});
465+
466+
const service = new MCAuthServiceClient(transport);
467+
const abortController = new AbortController();
468+
const loadingData: ExternalToast = {
469+
cancel: {
470+
label: t("common:cancel"),
471+
onClick: () => {
472+
abortController.abort();
473+
},
474+
},
475+
};
476+
const total = payload.length;
477+
let failed = 0;
478+
let success = 0;
479+
const accountsToAdd: ProfileAccount[] = [];
480+
const loadingReport = () =>
481+
t("account.listImportToast.loading", {
482+
checked: success + failed,
483+
total,
484+
success,
485+
failed,
486+
});
487+
const toastId = toast.loading(loadingReport(), loadingData);
488+
const { responses } = service.loginCredentials(
489+
{
490+
instanceId: instanceInfo.id,
491+
service: credentialType,
492+
payload,
493+
},
494+
{
495+
abort: abortController.signal,
496+
},
497+
);
498+
responses.onMessage((r) => {
499+
runAsync(async () => {
500+
const data = r.data;
501+
switch (data.oneofKind) {
502+
case "oneSuccess": {
503+
if (abortController.signal.aborted) return;
504+
if (data.oneSuccess.account) {
505+
accountsToAdd.push(data.oneSuccess.account);
506+
}
507+
success++;
508+
toast.loading(loadingReport(), {
509+
id: toastId,
510+
...loadingData,
511+
});
512+
break;
513+
}
514+
case "oneFailure": {
515+
if (abortController.signal.aborted) return;
516+
failed++;
517+
toast.loading(loadingReport(), {
518+
id: toastId,
519+
...loadingData,
520+
});
521+
break;
522+
}
523+
case "end": {
524+
if (accountsToAdd.length > 0) {
525+
await addAccountsBatchMutation(accountsToAdd);
526+
}
527+
if (accountsToAdd.length === 0) {
528+
toast.error(t("account.listImportToast.allFailed"), {
529+
id: toastId,
530+
cancel: undefined,
531+
});
532+
} else if (failed > 0) {
533+
toast.warning(
534+
t("account.listImportToast.someFailed", {
535+
count: accountsToAdd.length,
536+
failed,
537+
}),
538+
{ id: toastId, cancel: undefined },
539+
);
540+
} else {
541+
toast.success(
542+
t("account.listImportToast.noneFailed", {
543+
count: accountsToAdd.length,
544+
}),
545+
{ id: toastId, cancel: undefined },
546+
);
547+
}
548+
break;
549+
}
550+
}
551+
});
552+
});
553+
responses.onError((e) => {
554+
console.error(e);
555+
toast.error(t("account.listImportToast.error"), {
556+
id: toastId,
557+
cancel: undefined,
558+
});
559+
});
560+
},
561+
[instanceInfo.id, addAccountsBatchMutation, t, transport, trackEvent],
562+
);
610563

611564
const textSelectedCallback = useCallback(
612565
(text: string) => {
@@ -892,6 +845,19 @@ function AddButton() {
892845
{t("account.import.microsoftAccessToken")}
893846
</DropdownMenuItem>
894847
<DropdownMenuSeparator />
848+
<DropdownMenuLabel>
849+
{t("account.import.altProviders")}
850+
</DropdownMenuLabel>
851+
<DropdownMenuSeparator />
852+
<DropdownMenuItem
853+
onClick={() => {
854+
void trackEvent("import_account_ravealts");
855+
setRavealtsDialogOpen(true);
856+
}}
857+
>
858+
{t("account.ravealts.button")}
859+
</DropdownMenuItem>
860+
<DropdownMenuSeparator />
895861
<DropdownMenuLabel>
896862
{t("account.import.bedrockEdition")}
897863
</DropdownMenuLabel>
@@ -1058,6 +1024,11 @@ function AddButton() {
10581024
}
10591025
/>
10601026
)}
1027+
<RavealtsDialog
1028+
open={ravealtsDialogOpen}
1029+
onOpenChange={setRavealtsDialogOpen}
1030+
onImportAccounts={handleRavealtsImport}
1031+
/>
10611032
</>
10621033
);
10631034
}
@@ -1206,7 +1177,6 @@ function Content() {
12061177
<DataTableToolbar table={table}>
12071178
<DataTableSortList table={table} />
12081179
<GetAccountsButton />
1209-
<RavealtsButton />
12101180
<GenerateAccountsButton />
12111181
<AddButton />
12121182
</DataTableToolbar>

0 commit comments

Comments
 (0)