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
14 changes: 7 additions & 7 deletions src/app/import-quiz/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ function ImportQuizPageContent(): React.JSX.Element {
// States
uploadType,
fileNameInput,
fileNameOld,
fileNameLegacy,
error,
errorDetail,
loading,
fileInputRef,
fileOldRef,
fileLegacyRef,
directoryInputRef,
directoryName,
quizTitle,
Expand Down Expand Up @@ -329,15 +329,15 @@ function ImportQuizPageContent(): React.JSX.Element {
<Label htmlFor="file-old-input">Plik zip z pytaniami</Label>
<div
className="hover:bg-muted/40 dark:bg-input/30 bg-input border-border dark:hover:bg-input/40 relative cursor-pointer rounded-md border p-4 text-center text-sm shadow-xs transition"
onClick={() => fileOldRef.current?.click()}
onClick={() => fileLegacyRef.current?.click()}
onDrop={handleFileDrop}
onDragOver={handleDragOverFile}
onDragLeave={handleDragLeave}
role="button"
tabIndex={0}
onKeyDown={(event) => {
if (event.key === "Enter" || event.key === " ") {
fileOldRef.current?.click();
fileLegacyRef.current?.click();
event.preventDefault();
}
}}
Expand All @@ -346,19 +346,19 @@ function ImportQuizPageContent(): React.JSX.Element {
id="file-old-input"
type="file"
accept=".zip"
ref={fileOldRef}
ref={fileLegacyRef}
onChange={handleFileSelect}
className="hidden"
/>
{fileNameOld === null ? (
{fileNameLegacy === null ? (
<div className="space-y-1">
<FolderArchiveIcon className="mx-auto size-6" />
<p>Wybierz plik...</p>
</div>
) : (
<div className="space-y-1">
<FolderOpenIcon className="mx-auto size-6" />
<p className="break-all">{fileNameOld}</p>
<p className="break-all">{fileNameLegacy}</p>
</div>
)}
</div>
Expand Down
75 changes: 56 additions & 19 deletions src/hooks/use-sync-auth.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";

import { decodeAccessToken } from "@/lib/auth/jwt-utils";
import type { JWTPayload } from "@/lib/auth/types";
import { AUTH_COOKIE_NAMES, getCookie } from "@/lib/cookies";
import { getQueryClient } from "@/lib/query-client";
import { getUserService } from "@/services";

export function useSyncAuth(initialUser: JWTPayload | null) {
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(
initialUser !== null,
);
const [user, setUser] = useState<JWTPayload | null>(initialUser);
const isAuthenticatedRef = useRef(initialUser !== null);
const userRef = useRef<JWTPayload | null>(initialUser);

useEffect(() => {
isAuthenticatedRef.current = isAuthenticated;
userRef.current = user;
}, [isAuthenticated, user]);

const readToken = useCallback((): {
hasToken: boolean;
Expand All @@ -21,20 +29,23 @@ export function useSyncAuth(initialUser: JWTPayload | null) {
return { hasToken, payload };
}, []);

const syncAuthFromCookies = useCallback(() => {
const { hasToken, payload } = readToken();
const applyAuthenticatedPayload = useCallback((payload: JWTPayload) => {
isAuthenticatedRef.current = true;
userRef.current = payload;

if (hasToken && payload !== null) {
setIsAuthenticated(true);
setUser((previousUser) => {
if (previousUser !== null && previousUser.user_id !== payload.user_id) {
const queryClient = getQueryClient();
void queryClient.resetQueries();
}
return payload;
});
return;
}
setIsAuthenticated(true);
setUser((previousUser) => {
if (previousUser !== null && previousUser.user_id !== payload.user_id) {
const queryClient = getQueryClient();
void queryClient.resetQueries();
}
return payload;
});
}, []);

const clearAuthenticatedPayload = useCallback(() => {
userRef.current = null;
isAuthenticatedRef.current = false;

setUser(null);
setIsAuthenticated((previousIsAuthenticated) => {
Expand All @@ -44,22 +55,48 @@ export function useSyncAuth(initialUser: JWTPayload | null) {
}
return false;
});
}, [readToken]);
}, []);

const syncAuthFromCookies = useCallback(async () => {
const { hasToken, payload } = readToken();

if (hasToken && payload !== null) {
applyAuthenticatedPayload(payload);
return;
}

const hadAuthenticatedSession =
isAuthenticatedRef.current || userRef.current !== null;

if (hadAuthenticatedSession) {
const refreshed = await getUserService().refreshToken();

if (refreshed) {
const latest = readToken();
if (latest.hasToken && latest.payload !== null) {
applyAuthenticatedPayload(latest.payload);
return;
}
}
}

clearAuthenticatedPayload();
}, [applyAuthenticatedPayload, clearAuthenticatedPayload, readToken]);

useEffect(() => {
if (typeof window === "undefined") {
return;
}

syncAuthFromCookies();
void syncAuthFromCookies();

const handleFocus = () => {
syncAuthFromCookies();
void syncAuthFromCookies();
};

const handleVisibilityChange = () => {
if (document.visibilityState === "visible") {
syncAuthFromCookies();
void syncAuthFromCookies();
}
};

Expand All @@ -72,7 +109,7 @@ export function useSyncAuth(initialUser: JWTPayload | null) {
);

if (authCookieChanged) {
syncAuthFromCookies();
void syncAuthFromCookies();
}
};

Expand Down
39 changes: 20 additions & 19 deletions src/lib/import-quiz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ export const extractImagesToUpload = (
export const useImportQuiz = () => {
const [uploadType, setUploadType] = useState<UploadType>("legacy");
const [fileNameInput, setFileNameInput] = useState<string | null>(null);
const [fileNameOld, setFileNameOld] = useState<string | null>(null);
const [fileNameLegacy, setFileNameLegacy] = useState<string | null>(null);
const [directoryName, setDirectoryName] = useState<string | null>(null);
const [directoryFiles, setDirectoryFiles] = useState<File[]>([]);
const [quizTitle, setQuizTitle] = useState<string>("");
Expand All @@ -434,7 +434,7 @@ export const useImportQuiz = () => {
const [errorDetail, setErrorDetail] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const fileInputRef = useRef<HTMLInputElement>(null);
const fileOldRef = useRef<HTMLInputElement>(null);
const fileLegacyRef = useRef<HTMLInputElement>(null);
const directoryInputRef = useRef<HTMLInputElement>(null);
const monacoEditorRef = useRef<JsonCodeEditor | null>(null);
const [legacyContent, setLegacyContent] = useState<string>("");
Expand All @@ -456,10 +456,10 @@ export const useImportQuiz = () => {
const directoryPath = filesArray[0].webkitRelativePath.split("/")[0];
setDirectoryName(directoryPath);
setDirectoryFiles(filesArray);
setFileNameOld(null);
setFileNameLegacy(null);
setFileNameInput(null);
if (fileOldRef.current !== null) {
fileOldRef.current.value = "";
if (fileLegacyRef.current !== null) {
fileLegacyRef.current.value = "";
}
} else {
setDirectoryName(null);
Expand All @@ -477,15 +477,15 @@ export const useImportQuiz = () => {
if (fileInputRef.current !== null) {
fileInputRef.current.files = event.dataTransfer.files;
}
setFileNameOld(null);
setFileNameLegacy(null);
setFileNameInput(file.name);
break;
}
case "legacy": {
if (fileOldRef.current !== null) {
fileOldRef.current.files = event.dataTransfer.files;
if (fileLegacyRef.current !== null) {
fileLegacyRef.current.files = event.dataTransfer.files;
}
setFileNameOld(file.name);
setFileNameLegacy(file.name);
setFileNameInput(null);

break;
Expand Down Expand Up @@ -596,7 +596,7 @@ export const useImportQuiz = () => {
await readDirectoryRecursively(reader);
setDirectoryFiles(files);
setDirectoryName(directory.name);
setFileNameOld(null);
setFileNameLegacy(null);
if (fileInputRef.current !== null) {
fileInputRef.current.value = "";
}
Expand All @@ -616,7 +616,7 @@ export const useImportQuiz = () => {
setFileNameInput(null);
} else {
setFileNameInput(fileInput.name);
setFileNameOld(null);
setFileNameLegacy(null);
setDirectoryName(null);
setError(null);
}
Expand All @@ -625,16 +625,16 @@ export const useImportQuiz = () => {

case "legacy": {
if (files !== null && files.length > 0) {
const fileOld = files[0];
setFileNameOld(fileOld.name);
const fileLegacy = files[0];
setFileNameLegacy(fileLegacy.name);
setFileNameInput(null);
setDirectoryName(null);
setDirectoryFiles([]);
if (directoryInputRef.current !== null) {
directoryInputRef.current.value = "";
}
} else {
setFileNameOld(null);
setFileNameLegacy(null);
}
break;
}
Expand Down Expand Up @@ -736,10 +736,10 @@ export const useImportQuiz = () => {
}> => {
if (directoryFiles.length > 0) {
return processDirectory(directoryFiles);
} else if (fileOldRef.current?.files?.[0] === undefined) {
} else if (fileLegacyRef.current?.files?.[0] === undefined) {
throw new Error("Nie wybrano pliku ani folderu.");
} else {
return processZip(fileOldRef.current.files[0]);
return processZip(fileLegacyRef.current.files[0]);
}
};

Expand Down Expand Up @@ -832,6 +832,7 @@ export const useImportQuiz = () => {
order: a.order ?? aIndex + 1,
};
}),
multiple: q.answers.filter((a) => a.is_correct).length > 1,
};
}),
} as Quiz;
Expand Down Expand Up @@ -911,7 +912,7 @@ export const useImportQuiz = () => {
break;
}
case "legacy": {
if (fileNameOld == null && directoryName == null) {
if (fileNameLegacy == null && directoryName == null) {
setErrorAndNotify("Nie wybrano pliku ani folderu.");
setLoading(false);
return;
Expand Down Expand Up @@ -1055,11 +1056,11 @@ export const useImportQuiz = () => {
// States
uploadType,
fileNameInput,
fileNameOld,
fileNameLegacy,
error,
loading,
fileInputRef,
fileOldRef,
fileLegacyRef,
directoryInputRef,
directoryName,
quizTitle,
Expand Down
4 changes: 4 additions & 0 deletions src/services/base-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ export class BaseApiService {

private async ensureFreshToken(): Promise<void> {
const token = this.getAccessToken();
if (token === null && BaseApiService.refreshPromise !== null) {
await BaseApiService.refreshPromise;
return;
}
if (token !== null && isTokenExpired(token)) {
await this.queueTokenRefresh();
}
Expand Down
Loading