mirror of https://github.com/usememos/memos.git
chore: clean up unused imports and parameters across components
This commit is contained in:
parent
0ad75b8f08
commit
d711d724bb
|
|
@ -4,7 +4,7 @@ import { useCallback } from "react";
|
|||
import toast from "react-hot-toast";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useInstance } from "@/contexts/InstanceContext";
|
||||
import { memoKeys, useDeleteMemo, useUpdateMemo } from "@/hooks/useMemoQueries";
|
||||
import { useDeleteMemo, useUpdateMemo } from "@/hooks/useMemoQueries";
|
||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||
import { userKeys } from "@/hooks/useUserQueries";
|
||||
import { State } from "@/types/proto/api/v1/common_pb";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|||
import { isEqual } from "lodash-es";
|
||||
import { CheckCircleIcon, Code2Icon, HashIcon, LinkIcon } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Memo, Memo_Property, Memo_PropertySchema, MemoRelation_Type } from "@/types/proto/api/v1/memo_service_pb";
|
||||
import { Memo, Memo_PropertySchema, MemoRelation_Type } from "@/types/proto/api/v1/memo_service_pb";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import MemoRelationForceGraph from "../MemoRelationForceGraph";
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export const LocationDialog = ({
|
|||
open,
|
||||
onOpenChange,
|
||||
state,
|
||||
locationInitialized,
|
||||
locationInitialized: _locationInitialized,
|
||||
onPositionChange,
|
||||
onUpdateCoordinate,
|
||||
onPlaceholderChange,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ interface UseKeyboardOptions {
|
|||
onToggleFocusMode?: () => void;
|
||||
}
|
||||
|
||||
export const useKeyboard = (editorRef: React.RefObject<EditorRefActions | null>, options: UseKeyboardOptions) => {
|
||||
export const useKeyboard = (_editorRef: React.RefObject<EditorRefActions | null>, options: UseKeyboardOptions) => {
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
// Cmd/Ctrl + Enter to save
|
||||
|
|
|
|||
|
|
@ -5,14 +5,7 @@ import { memoServiceClient } from "@/connect";
|
|||
import { DEFAULT_LIST_MEMOS_PAGE_SIZE } from "@/helpers/consts";
|
||||
import { extractUserIdFromName } from "@/helpers/resource-names";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import {
|
||||
Memo,
|
||||
MemoRelation,
|
||||
MemoRelation_Memo,
|
||||
MemoRelation_MemoSchema,
|
||||
MemoRelation_Type,
|
||||
MemoRelationSchema,
|
||||
} from "@/types/proto/api/v1/memo_service_pb";
|
||||
import { Memo, MemoRelation, MemoRelation_MemoSchema, MemoRelation_Type, MemoRelationSchema } from "@/types/proto/api/v1/memo_service_pb";
|
||||
|
||||
interface UseLinkMemoParams {
|
||||
isOpen: boolean;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { LocalFile } from "@/components/memo-metadata";
|
||||
import type { Attachment } from "@/types/proto/api/v1/attachment_service_pb";
|
||||
import type { Location, MemoRelation } from "@/types/proto/api/v1/memo_service_pb";
|
||||
import type { MemoRelation } from "@/types/proto/api/v1/memo_service_pb";
|
||||
import type { EditorAction, EditorState, LoadingKey } from "./types";
|
||||
|
||||
export const editorActions = {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { create } from "@bufbuild/protobuf";
|
|||
import { FieldMaskSchema } from "@bufbuild/protobuf/wkt";
|
||||
import { sortBy } from "lodash-es";
|
||||
import { MoreVerticalIcon, PlusIcon } from "lucide-react";
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import ConfirmDialog from "@/components/ConfirmDialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { create } from "@bufbuild/protobuf";
|
||||
import { isEqual } from "lodash-es";
|
||||
import { XIcon } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
|
@ -12,7 +11,6 @@ import { useInstance } from "@/contexts/InstanceContext";
|
|||
import { convertFileToBase64 } from "@/helpers/utils";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import { useUpdateUser } from "@/hooks/useUserQueries";
|
||||
import { User as UserPb, UserSchema } from "@/types/proto/api/v1/user_service_pb";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import UserAvatar from "./UserAvatar";
|
||||
|
||||
|
|
|
|||
|
|
@ -89,8 +89,8 @@ const UserMenu = (props: Props) => {
|
|||
|
||||
try {
|
||||
// Then clear user-specific localStorage items
|
||||
// Preserve app-wide settings like theme
|
||||
const keysToPreserve = ["memos-theme", "tag-view-as-tree", "tag-tree-auto-expand", "viewStore"];
|
||||
// Preserve app-wide settings (theme, locale, view preferences, tag view settings)
|
||||
const keysToPreserve = ["memos-theme", "memos-locale", "memos-view-setting", "tag-view-as-tree", "tag-tree-auto-expand"];
|
||||
const keysToRemove: string[] = [];
|
||||
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
|
|
@ -105,8 +105,8 @@ const UserMenu = (props: Props) => {
|
|||
// Ignore errors from localStorage operations
|
||||
}
|
||||
|
||||
// Always redirect to auth page
|
||||
window.location.href = Routes.AUTH;
|
||||
// Always redirect to auth page (use replace to prevent back navigation)
|
||||
window.location.replace(Routes.AUTH);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|||
import { Code, ConnectError, createClient, type Interceptor } from "@connectrpc/connect";
|
||||
import { createConnectTransport } from "@connectrpc/connect-web";
|
||||
import { getAccessToken, setAccessToken } from "./auth-state";
|
||||
import { getInstanceConfig } from "./instance-config";
|
||||
import { ROUTES } from "./router/routes";
|
||||
import { ActivityService } from "./types/proto/api/v1/activity_service_pb";
|
||||
import { AttachmentService } from "./types/proto/api/v1/attachment_service_pb";
|
||||
import { AuthService } from "./types/proto/api/v1/auth_service_pb";
|
||||
|
|
@ -12,6 +10,7 @@ import { InstanceService } from "./types/proto/api/v1/instance_service_pb";
|
|||
import { MemoService } from "./types/proto/api/v1/memo_service_pb";
|
||||
import { ShortcutService } from "./types/proto/api/v1/shortcut_service_pb";
|
||||
import { UserService } from "./types/proto/api/v1/user_service_pb";
|
||||
import { redirectOnAuthFailure } from "./utils/auth-redirect";
|
||||
|
||||
// ============================================================================
|
||||
// Constants
|
||||
|
|
@ -20,19 +19,6 @@ import { UserService } from "./types/proto/api/v1/user_service_pb";
|
|||
const RETRY_HEADER = "X-Retry";
|
||||
const RETRY_HEADER_VALUE = "true";
|
||||
|
||||
const ROUTE_CONFIG = {
|
||||
// Routes accessible without authentication (uses prefix matching)
|
||||
public: [
|
||||
ROUTES.AUTH, // Authentication pages
|
||||
ROUTES.EXPLORE, // Explore page
|
||||
"/u/", // User profile pages (dynamic)
|
||||
"/memos/", // Individual memo detail pages (dynamic)
|
||||
],
|
||||
|
||||
// Routes that require authentication (uses exact matching)
|
||||
private: [ROUTES.ROOT, ROUTES.ATTACHMENTS, ROUTES.INBOX, ROUTES.ARCHIVED, ROUTES.SETTING],
|
||||
} as const;
|
||||
|
||||
// ============================================================================
|
||||
// Token Refresh State Management
|
||||
// ============================================================================
|
||||
|
|
@ -60,42 +46,6 @@ const createTokenRefreshManager = () => {
|
|||
|
||||
const tokenRefreshManager = createTokenRefreshManager();
|
||||
|
||||
// ============================================================================
|
||||
// Route Access Control
|
||||
// ============================================================================
|
||||
|
||||
function isPublicRoute(path: string): boolean {
|
||||
return ROUTE_CONFIG.public.some((route) => path.startsWith(route));
|
||||
}
|
||||
|
||||
function isPrivateRoute(path: string): boolean {
|
||||
return (ROUTE_CONFIG.private as readonly string[]).includes(path);
|
||||
}
|
||||
|
||||
function getAuthFailureRedirect(currentPath: string): string | null {
|
||||
if (isPublicRoute(currentPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (getInstanceConfig().memoRelatedSetting.disallowPublicVisibility) {
|
||||
return ROUTES.AUTH;
|
||||
}
|
||||
|
||||
if (isPrivateRoute(currentPath)) {
|
||||
return ROUTES.EXPLORE;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function performRedirect(redirectUrl: string | null): void {
|
||||
if (redirectUrl) {
|
||||
// Use replace() instead of href to prevent back button from showing cached sensitive data
|
||||
// This removes the current page from browser history after authentication failure
|
||||
window.location.replace(redirectUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Token Refresh
|
||||
// ============================================================================
|
||||
|
|
@ -165,8 +115,7 @@ const authInterceptor: Interceptor = (next) => async (req) => {
|
|||
req.header.set(RETRY_HEADER, RETRY_HEADER_VALUE);
|
||||
return await next(req);
|
||||
} catch (refreshError) {
|
||||
const redirectUrl = getAuthFailureRedirect(window.location.pathname);
|
||||
performRedirect(redirectUrl);
|
||||
redirectOnAuthFailure();
|
||||
throw refreshError;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,4 +32,3 @@ const useMediaQuery = (breakpoint: Breakpoint): boolean => {
|
|||
};
|
||||
|
||||
export default useMediaQuery;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Suspense, useEffect, useMemo, useState } from "react";
|
||||
import { Suspense, useEffect, useMemo } from "react";
|
||||
import { Outlet, useLocation, useSearchParams } from "react-router-dom";
|
||||
import usePrevious from "react-use/lib/usePrevious";
|
||||
import Navigation from "@/components/Navigation";
|
||||
|
|
@ -8,7 +8,7 @@ import useCurrentUser from "@/hooks/useCurrentUser";
|
|||
import useMediaQuery from "@/hooks/useMediaQuery";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Loading from "@/pages/Loading";
|
||||
import { Routes } from "@/router";
|
||||
import { redirectOnAuthFailure } from "@/utils/auth-redirect";
|
||||
|
||||
const RootLayout = () => {
|
||||
const location = useLocation();
|
||||
|
|
@ -17,25 +17,14 @@ const RootLayout = () => {
|
|||
const currentUser = useCurrentUser();
|
||||
const { memoRelatedSetting } = useInstance();
|
||||
const { removeFilter } = useMemoFilterContext();
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
const pathname = useMemo(() => location.pathname, [location.pathname]);
|
||||
const prevPathname = usePrevious(pathname);
|
||||
|
||||
useEffect(() => {
|
||||
if (!currentUser) {
|
||||
// If disallowPublicVisibility is enabled, redirect to login
|
||||
if (memoRelatedSetting.disallowPublicVisibility) {
|
||||
window.location.replace(Routes.AUTH);
|
||||
return;
|
||||
} else if (
|
||||
([Routes.ROOT, Routes.ATTACHMENTS, Routes.INBOX, Routes.ARCHIVED, Routes.SETTING] as string[]).includes(location.pathname)
|
||||
) {
|
||||
window.location.replace(Routes.EXPLORE);
|
||||
return;
|
||||
}
|
||||
if (!currentUser && memoRelatedSetting.disallowPublicVisibility) {
|
||||
redirectOnAuthFailure();
|
||||
}
|
||||
setInitialized(true);
|
||||
}, [currentUser, memoRelatedSetting.disallowPublicVisibility, location.pathname]);
|
||||
}, [currentUser, memoRelatedSetting.disallowPublicVisibility]);
|
||||
|
||||
useEffect(() => {
|
||||
// When the route changes and there is no filter in the search params, remove all filters
|
||||
|
|
@ -44,9 +33,7 @@ const RootLayout = () => {
|
|||
}
|
||||
}, [prevPathname, pathname, searchParams, removeFilter]);
|
||||
|
||||
return !initialized ? (
|
||||
<Loading />
|
||||
) : (
|
||||
return (
|
||||
<div className="w-full min-h-full flex flex-row justify-center items-start sm:pl-16">
|
||||
{sm && (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ const MemoDetail = () => {
|
|||
setShowCommentEditor(true);
|
||||
};
|
||||
|
||||
const handleCommentCreated = async (memoCommentName: string) => {
|
||||
const handleCommentCreated = async (_memoCommentName: string) => {
|
||||
// React Query will auto-refetch due to invalidation in the mutation
|
||||
setShowCommentEditor(false);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import { getInstanceConfig } from "@/instance-config";
|
||||
import { ROUTES } from "@/router/routes";
|
||||
|
||||
const PUBLIC_ROUTES = [
|
||||
ROUTES.AUTH, // Authentication pages
|
||||
ROUTES.EXPLORE, // Explore page
|
||||
"/u/", // User profile pages (dynamic)
|
||||
"/memos/", // Individual memo detail pages (dynamic)
|
||||
] as const;
|
||||
|
||||
const PRIVATE_ROUTES = [ROUTES.ROOT, ROUTES.ATTACHMENTS, ROUTES.INBOX, ROUTES.ARCHIVED, ROUTES.SETTING] as const;
|
||||
|
||||
function isPublicRoute(path: string): boolean {
|
||||
return PUBLIC_ROUTES.some((route) => path.startsWith(route));
|
||||
}
|
||||
|
||||
function isPrivateRoute(path: string): boolean {
|
||||
return PRIVATE_ROUTES.includes(path as any);
|
||||
}
|
||||
|
||||
export function redirectOnAuthFailure(): void {
|
||||
const currentPath = window.location.pathname;
|
||||
|
||||
// Don't redirect if it's a public route
|
||||
if (isPublicRoute(currentPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const disallowPublicVisibility = getInstanceConfig().memoRelatedSetting.disallowPublicVisibility;
|
||||
const target = disallowPublicVisibility ? ROUTES.AUTH : ROUTES.EXPLORE;
|
||||
|
||||
// Only redirect if it's a private route or disallowPublicVisibility is enabled
|
||||
if (disallowPublicVisibility || isPrivateRoute(currentPath)) {
|
||||
window.location.replace(target);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
|
|
|
|||
Loading…
Reference in New Issue