diff --git a/src/App.tsx b/src/App.tsx
index 8f64d5c..2fe4dd2 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -250,9 +250,7 @@ function MainContent(): React.JSX.Element {
}, [])
useEffect(() => {
- const handleOAuthUserUpdated = (
- event: Event
- ) => {
+ const handleOAuthUserUpdated = (event: Event) => {
const customEvent = event as CustomEvent<{
user?: { name?: string } | null
}>
@@ -267,10 +265,7 @@ function MainContent(): React.JSX.Element {
window.addEventListener("ss:oauth-user-updated", handleOAuthUserUpdated as EventListener)
return () => {
- window.removeEventListener(
- "ss:oauth-user-updated",
- handleOAuthUserUpdated as EventListener
- )
+ window.removeEventListener("ss:oauth-user-updated", handleOAuthUserUpdated as EventListener)
}
}, [refreshPermissionFromAuth])
diff --git a/src/components/BoardManager.tsx b/src/components/BoardManager.tsx
index 2b8b021..e36d7d9 100644
--- a/src/components/BoardManager.tsx
+++ b/src/components/BoardManager.tsx
@@ -862,9 +862,9 @@ ORDER BY reward_points DESC, score DESC`,
? "repeat(auto-fill, minmax(102px, 1fr))"
: list.viewMode === "largeAvatar"
? "repeat(auto-fill, minmax(180px, 1fr))"
- : list.viewMode === "list"
- ? "1fr"
- : "repeat(auto-fill, minmax(220px, 1fr))",
+ : list.viewMode === "list"
+ ? "1fr"
+ : "repeat(auto-fill, minmax(220px, 1fr))",
gap: 12,
}}
>
@@ -941,9 +941,9 @@ ORDER BY reward_points DESC, score DESC`,
? "8px"
: list.viewMode === "largeAvatar"
? 0
- : list.viewMode === "list"
- ? "10px 12px"
- : "12px 14px",
+ : list.viewMode === "list"
+ ? "10px 12px"
+ : "12px 14px",
height:
list.viewMode === "grid" || list.viewMode === "largeAvatar"
? "100%"
@@ -1108,9 +1108,7 @@ ORDER BY reward_points DESC, score DESC`,
fontSize: 28,
lineHeight: 1,
color:
- primaryMetric && primaryMetric.value >= 0
- ? "#52c41a"
- : "#ff4d4f",
+ primaryMetric && primaryMetric.value >= 0 ? "#52c41a" : "#ff4d4f",
background: "rgba(255,255,255,0.62)",
border: "1px solid rgba(255,255,255,0.82)",
borderRadius: 8,
diff --git a/src/components/ContentArea.tsx b/src/components/ContentArea.tsx
index 156326e..2f34d36 100644
--- a/src/components/ContentArea.tsx
+++ b/src/components/ContentArea.tsx
@@ -167,7 +167,7 @@ export function ContentArea({
: permission === "points"
? t("permissions.points")
: t("permissions.view")}
-
+
)
const fallbackDisplayName =
permission === "admin"
@@ -371,7 +371,9 @@ export function ContentArea({
}}
>
最近同步时间
- {formattedLastSyncTime}
+
+ {formattedLastSyncTime}
+
云空间用量
{storageUsageLoading ? (
diff --git a/src/components/Home.tsx b/src/components/Home.tsx
index 4146a97..24827a3 100644
--- a/src/components/Home.tsx
+++ b/src/components/Home.tsx
@@ -13,7 +13,13 @@ import {
Divider,
Dropdown,
} from "antd"
-import { SearchOutlined, DeleteOutlined, UndoOutlined, UploadOutlined, CopyOutlined } from "@ant-design/icons"
+import {
+ SearchOutlined,
+ DeleteOutlined,
+ UndoOutlined,
+ UploadOutlined,
+ CopyOutlined,
+} from "@ant-design/icons"
import { useTranslation } from "react-i18next"
import { match, pinyin } from "pinyin-pro"
import { getAvatarFromExtraJson, setAvatarInExtraJson } from "../utils/studentAvatar"
@@ -651,111 +657,114 @@ export const Home: React.FC = ({
setOperationVisible(true)
}
- const playOperationMorph = useCallback((attempt = 0) => {
- if (isPortraitMode || !operationOriginRect) return false
- const modalEl = document.querySelector(`.${operationModalClass}`) as HTMLElement | null
- if (!modalEl) {
- const byClassCount = document.querySelectorAll(`.${operationModalClass}`).length
- const byRootCount = document.querySelectorAll(`.${operationModalRootClass}`).length
- const modalCount = document.querySelectorAll(".ant-modal").length
- const rootExists = Boolean(document.querySelector(`.${operationModalRootClass}`))
- logHome("operation:morph:modal-miss", {
- attempt,
- rootExists,
- byClassCount,
- byRootCount,
- modalCount,
- })
- return false
- }
-
- // Clear any leftover transform from previous close animation before measuring.
- operationMorphAnimationRef.current?.cancel()
- for (const animation of modalEl.getAnimations()) {
- animation.cancel()
- }
- modalEl.style.transform = ""
- modalEl.style.opacity = ""
- modalEl.style.visibility = ""
- const maskEl = document.querySelector(`.${operationModalRootClass} .ant-modal-mask`) as
- | HTMLElement
- | null
- if (maskEl) {
- operationMaskAnimationRef.current?.cancel()
- maskEl.style.opacity = ""
- maskEl.style.visibility = ""
- operationMaskAnimationRef.current = maskEl.animate([{ opacity: 0 }, { opacity: 1 }], {
- duration: 220,
- easing: "cubic-bezier(0.2, 0, 0, 1)",
- fill: "both",
- })
- }
- const modalRect = modalEl.getBoundingClientRect()
- if (modalRect.width <= 0 || modalRect.height <= 0) {
- logHome("operation:morph:modal-rect-invalid", {
- attempt,
- width: modalRect.width,
- height: modalRect.height,
- })
- return false
- }
- const fromX = operationOriginRect.left - modalRect.left
- const fromY = operationOriginRect.top - modalRect.top
- const scaleX = operationOriginRect.width / modalRect.width
- const scaleY = operationOriginRect.height / modalRect.height
-
- logHome("operation:morph:computed", {
- modalRect: {
- left: modalRect.left,
- top: modalRect.top,
- width: modalRect.width,
- height: modalRect.height,
- },
- fromX,
- fromY,
- scaleX,
- scaleY,
- expectedStartRect: {
- left: modalRect.left + fromX,
- top: modalRect.top + fromY,
- width: modalRect.width * scaleX,
- height: modalRect.height * scaleY,
- },
- animateSupported: typeof modalEl.animate === "function",
- })
-
- modalEl.style.transformOrigin = "top left"
- modalEl.style.willChange = "transform, opacity"
- operationMorphAnimationRef.current = modalEl.animate(
- [
- {
- transform: `translate3d(${fromX}px, ${fromY}px, 0) scale(${scaleX}, ${scaleY})`,
- opacity: 0.86,
- },
- {
- transform: "translate3d(0, 0, 0) scale(1, 1)",
- opacity: 1,
- },
- ],
- {
- duration: 480,
- easing: "cubic-bezier(0.16, 1, 0.3, 1)",
- fill: "both",
+ const playOperationMorph = useCallback(
+ (attempt = 0) => {
+ if (isPortraitMode || !operationOriginRect) return false
+ const modalEl = document.querySelector(`.${operationModalClass}`) as HTMLElement | null
+ if (!modalEl) {
+ const byClassCount = document.querySelectorAll(`.${operationModalClass}`).length
+ const byRootCount = document.querySelectorAll(`.${operationModalRootClass}`).length
+ const modalCount = document.querySelectorAll(".ant-modal").length
+ const rootExists = Boolean(document.querySelector(`.${operationModalRootClass}`))
+ logHome("operation:morph:modal-miss", {
+ attempt,
+ rootExists,
+ byClassCount,
+ byRootCount,
+ modalCount,
+ })
+ return false
}
- )
- logHome("operation:morph:animation-start", {
- attempt,
- currentTime: operationMorphAnimationRef.current.currentTime,
- playState: operationMorphAnimationRef.current.playState,
- })
- operationMorphAnimationRef.current.onfinish = () => {
- logHome("operation:morph:animation-finish")
- }
- operationMorphAnimationRef.current.oncancel = () => {
- logHome("operation:morph:animation-cancel")
- }
- return true
- }, [isPortraitMode, operationOriginRect, operationModalClass, operationModalRootClass])
+
+ // Clear any leftover transform from previous close animation before measuring.
+ operationMorphAnimationRef.current?.cancel()
+ for (const animation of modalEl.getAnimations()) {
+ animation.cancel()
+ }
+ modalEl.style.transform = ""
+ modalEl.style.opacity = ""
+ modalEl.style.visibility = ""
+ const maskEl = document.querySelector(
+ `.${operationModalRootClass} .ant-modal-mask`
+ ) as HTMLElement | null
+ if (maskEl) {
+ operationMaskAnimationRef.current?.cancel()
+ maskEl.style.opacity = ""
+ maskEl.style.visibility = ""
+ operationMaskAnimationRef.current = maskEl.animate([{ opacity: 0 }, { opacity: 1 }], {
+ duration: 220,
+ easing: "cubic-bezier(0.2, 0, 0, 1)",
+ fill: "both",
+ })
+ }
+ const modalRect = modalEl.getBoundingClientRect()
+ if (modalRect.width <= 0 || modalRect.height <= 0) {
+ logHome("operation:morph:modal-rect-invalid", {
+ attempt,
+ width: modalRect.width,
+ height: modalRect.height,
+ })
+ return false
+ }
+ const fromX = operationOriginRect.left - modalRect.left
+ const fromY = operationOriginRect.top - modalRect.top
+ const scaleX = operationOriginRect.width / modalRect.width
+ const scaleY = operationOriginRect.height / modalRect.height
+
+ logHome("operation:morph:computed", {
+ modalRect: {
+ left: modalRect.left,
+ top: modalRect.top,
+ width: modalRect.width,
+ height: modalRect.height,
+ },
+ fromX,
+ fromY,
+ scaleX,
+ scaleY,
+ expectedStartRect: {
+ left: modalRect.left + fromX,
+ top: modalRect.top + fromY,
+ width: modalRect.width * scaleX,
+ height: modalRect.height * scaleY,
+ },
+ animateSupported: typeof modalEl.animate === "function",
+ })
+
+ modalEl.style.transformOrigin = "top left"
+ modalEl.style.willChange = "transform, opacity"
+ operationMorphAnimationRef.current = modalEl.animate(
+ [
+ {
+ transform: `translate3d(${fromX}px, ${fromY}px, 0) scale(${scaleX}, ${scaleY})`,
+ opacity: 0.86,
+ },
+ {
+ transform: "translate3d(0, 0, 0) scale(1, 1)",
+ opacity: 1,
+ },
+ ],
+ {
+ duration: 480,
+ easing: "cubic-bezier(0.16, 1, 0.3, 1)",
+ fill: "both",
+ }
+ )
+ logHome("operation:morph:animation-start", {
+ attempt,
+ currentTime: operationMorphAnimationRef.current.currentTime,
+ playState: operationMorphAnimationRef.current.playState,
+ })
+ operationMorphAnimationRef.current.onfinish = () => {
+ logHome("operation:morph:animation-finish")
+ }
+ operationMorphAnimationRef.current.oncancel = () => {
+ logHome("operation:morph:animation-cancel")
+ }
+ return true
+ },
+ [isPortraitMode, operationOriginRect, operationModalClass, operationModalRootClass]
+ )
useLayoutEffect(() => {
if (isPortraitMode || !operationVisible) return
@@ -787,23 +796,26 @@ export const Home: React.FC = ({
}
}, [isPortraitMode, operationVisible, operationOriginRect, playOperationMorph])
- const finishCloseOperationModal = useCallback((skipCancelMorph = false, skipCancelMask = false) => {
- if (!skipCancelMorph) {
- operationMorphAnimationRef.current?.cancel()
- }
- operationMorphAnimationRef.current = null
- if (!skipCancelMask) {
- operationMaskAnimationRef.current?.cancel()
- }
- operationMaskAnimationRef.current = null
- if (operationMorphRafRef.current !== null) {
- window.cancelAnimationFrame(operationMorphRafRef.current)
- operationMorphRafRef.current = null
- }
- operationClosingRef.current = false
- setOperationVisible(false)
- setOperationOriginRect(null)
- }, [])
+ const finishCloseOperationModal = useCallback(
+ (skipCancelMorph = false, skipCancelMask = false) => {
+ if (!skipCancelMorph) {
+ operationMorphAnimationRef.current?.cancel()
+ }
+ operationMorphAnimationRef.current = null
+ if (!skipCancelMask) {
+ operationMaskAnimationRef.current?.cancel()
+ }
+ operationMaskAnimationRef.current = null
+ if (operationMorphRafRef.current !== null) {
+ window.cancelAnimationFrame(operationMorphRafRef.current)
+ operationMorphRafRef.current = null
+ }
+ operationClosingRef.current = false
+ setOperationVisible(false)
+ setOperationOriginRect(null)
+ },
+ []
+ )
const closeOperationModal = useCallback(() => {
logHome("operation:morph:close", {
diff --git a/src/components/RewardExchange.tsx b/src/components/RewardExchange.tsx
index 7423095..f87718c 100644
--- a/src/components/RewardExchange.tsx
+++ b/src/components/RewardExchange.tsx
@@ -120,7 +120,9 @@ export const RewardExchange: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
}
const frame = window.requestAnimationFrame(() => {
- const modalEl = document.querySelector(".ss-reward-morph-modal.ant-modal") as HTMLElement | null
+ const modalEl = document.querySelector(
+ ".ss-reward-morph-modal.ant-modal"
+ ) as HTMLElement | null
if (!modalEl) {
setModalMorphStage("idle")
return
diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx
index 363485c..0e11dba 100644
--- a/src/components/Settings.tsx
+++ b/src/components/Settings.tsx
@@ -416,15 +416,13 @@ export const Settings: React.FC<{
useEffect(() => {
const handleOAuthUserUpdated = (event: Event) => {
const customEvent = event as CustomEvent<{
- user?:
- | {
- user_id?: string
- email?: string
- name?: string
- github_username?: string
- permission?: number
- }
- | null
+ user?: {
+ user_id?: string
+ email?: string
+ name?: string
+ github_username?: string
+ permission?: number
+ } | null
}>
const user = customEvent?.detail?.user
if (user?.user_id && user.email && user.name && typeof user.permission === "number") {
@@ -442,10 +440,7 @@ export const Settings: React.FC<{
window.addEventListener("ss:oauth-user-updated", handleOAuthUserUpdated as EventListener)
return () => {
- window.removeEventListener(
- "ss:oauth-user-updated",
- handleOAuthUserUpdated as EventListener
- )
+ window.removeEventListener("ss:oauth-user-updated", handleOAuthUserUpdated as EventListener)
}
}, [])