Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: achievement #512

Merged
merged 8 commits into from
Sep 21, 2024
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,5 @@ Since it is not very convenient to develop in Electron, the first way to develop
Follow is licensed under the GNU General Public License version 3 with the addition of the following special exception:

All content in the `icons/mgc` directory is copyrighted by https://mgc.mingcute.com/ and cannot be redistributed.

All content in the `lottie` directory is distributed under the [Lottie Simple License](https://lottiefiles.com/page/license).
1 change: 1 addition & 0 deletions apps/renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"lethargy": "1.0.9",
"linkedom": "^0.18.5",
"lodash-es": "4.17.21",
"lottie-react": "2.4.0",
"nanoid": "5.0.7",
"ofetch": "1.4.0",
"path-to-regexp": "8.1.0",
Expand Down
4 changes: 2 additions & 2 deletions apps/renderer/src/components/ui/media/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback } from "react"

import { PlainModal } from "../modal/stacked/custom-modal"
import { useModalStack } from "../modal/stacked/hooks"
import { NoopChildren } from "../modal/stacked/utils"
import type { PreviewMediaProps } from "./preview-media"
import { PreviewMediaContent } from "./preview-media"

Expand All @@ -21,7 +21,7 @@ export const usePreviewMedia = () => {
blur: true,
className: "bg-black/80",
},
CustomModalComponent: NoopChildren,
CustomModalComponent: PlainModal,
clickOutsideToDismiss: true,
})
},
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/components/ui/media/preview-media.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export const PreviewMediaContent: FC<{
<div
tabIndex={-1}
onClick={stopPropagation}
className="center fixed bottom-4 left-1/2 -translate-x-1/2 h-6 gap-2 rounded-full bg-neutral-700/90 px-4 duration-200 animate-in fade-in-0 slide-in-from-bottom-6"
className="center fixed bottom-4 left-1/2 h-6 -translate-x-1/2 gap-2 rounded-full bg-neutral-700/90 px-4 duration-200 animate-in fade-in-0 slide-in-from-bottom-6"
>
{Array.from({ length: media.length })
.fill(0)
Expand Down
19 changes: 19 additions & 0 deletions apps/renderer/src/components/ui/modal/stacked/components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useTranslation } from "react-i18next"

import { MotionButtonBase } from "../../button"
import { useCurrentModal } from "./hooks"

export const ModalClose = () => {
const { dismiss } = useCurrentModal()
const { t } = useTranslation("common")

return (
<MotionButtonBase
aria-label={t("close")}
className="absolute right-6 top-6 z-[99] flex size-8 items-center justify-center rounded-md duration-200 hover:bg-theme-button-hover"
onClick={dismiss}
>
<i className="i-mgc-close-cute-re block" />
</MotionButtonBase>
)
}
51 changes: 51 additions & 0 deletions apps/renderer/src/components/ui/modal/stacked/custom-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { PropsWithChildren } from "react"
import { useState } from "react"

import { m } from "~/components/common/Motion"
import { stopPropagation } from "~/lib/dom"
import { cn } from "~/lib/utils"

import { ModalClose } from "./components"
import { useCurrentModal } from "./hooks"

export const PlainModal = ({ children }: PropsWithChildren) => children

export { PlainModal as NoopChildren }

export const SlideUpModal = (props: PropsWithChildren) => {
const winHeight = useState(() => window.innerHeight)[0]
const { dismiss } = useCurrentModal()
return (
<div className={"container center h-full"} onPointerDown={dismiss} onClick={stopPropagation}>
<m.div
onPointerDown={stopPropagation}
tabIndex={-1}
initial={{
y: "100%",
opacity: 0.9,
}}
animate={{
y: 0,
opacity: 1,
}}
exit={{
y: winHeight,
}}
transition={{
type: "spring",
mass: 0.4,
tension: 100,
friction: 1,
}}
className={cn(
"relative flex flex-col items-center overflow-hidden rounded-xl border bg-theme-background p-8 pb-0",
"h-[80vh] w-[600px] max-w-full shadow lg:max-h-[calc(100vh-10rem)]",
)}
>
{props.children}

<ModalClose />
</m.div>
</div>
)
}
22 changes: 12 additions & 10 deletions apps/renderer/src/components/ui/modal/stacked/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,13 @@ export const ModalInternal = memo(

const finalChildren = useMemo(
() => (
<CurrentModalContext.Provider value={ModalContextProps}>
<AppErrorBoundary errorType={ErrorComponentType.Modal}>
<RootPortalProvider value={edgeElementRef.current as HTMLElement}>
{children ?? createElement(content, ModalProps)}
</RootPortalProvider>
</AppErrorBoundary>
</CurrentModalContext.Provider>
<AppErrorBoundary errorType={ErrorComponentType.Modal}>
<RootPortalProvider value={edgeElementRef.current as HTMLElement}>
{children ?? createElement(content, ModalProps)}
</RootPortalProvider>
</AppErrorBoundary>
),
[ModalContextProps, ModalProps, children, content],
[ModalProps, children, content],
)

useEffect(() => {
Expand Down Expand Up @@ -281,7 +279,9 @@ export const ModalInternal = memo(
onSelect={handleSelectStart}
onKeyUp={handleDetectSelectEnd}
>
<CustomModalComponent>{finalChildren}</CustomModalComponent>
<CurrentModalContext.Provider value={ModalContextProps}>
<CustomModalComponent>{finalChildren}</CustomModalComponent>
</CurrentModalContext.Provider>
</div>
</div>
</Dialog.Content>
Expand Down Expand Up @@ -373,7 +373,9 @@ export const ModalInternal = memo(
<Divider className="my-2 shrink-0 border-slate-200 opacity-80 dark:border-neutral-800" />

<div className="min-h-0 shrink grow overflow-auto px-4 py-2">
{finalChildren}
<CurrentModalContext.Provider value={ModalContextProps}>
{finalChildren}
</CurrentModalContext.Provider>
</div>
</ResizeSwitch>
</m.div>
Expand Down
3 changes: 0 additions & 3 deletions apps/renderer/src/components/ui/modal/stacked/utils.ts

This file was deleted.

15 changes: 13 additions & 2 deletions apps/renderer/src/components/user-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { apiClient } from "~/lib/api-fetch"
import { defineQuery } from "~/lib/defineQuery"
import { nextFrame } from "~/lib/dom"
import { cn } from "~/lib/utils"
import { useAchievementModal } from "~/modules/achievement/hooks"
import { LoginModalContent } from "~/modules/auth/LoginModalContent"
import { usePresentUserProfileModal } from "~/modules/profile/hooks"
import { useSettingModal } from "~/modules/settings/modal/hooks"
Expand All @@ -26,8 +27,8 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "./ui/dropdown-menu/dropdown-menu"
import { PlainModal } from "./ui/modal/stacked/custom-modal"
import { useModalStack } from "./ui/modal/stacked/hooks"
import { NoopChildren } from "./ui/modal/stacked/utils"

interface LoginProps {
method?: "redirect" | "modal"
Expand All @@ -43,7 +44,7 @@ export const LoginButton: FC<LoginProps> = (props) => {
method === "modal"
? () => {
modalStack.present({
CustomModalComponent: NoopChildren,
CustomModalComponent: PlainModal,
title: "Login",
id: "login",
content: () => <LoginModalContent runtime={window.electron ? "app" : "browser"} />,
Expand All @@ -65,6 +66,7 @@ export const ProfileButton: FC<LoginProps> = memo((props) => {
const signOut = useSignOut()
const settingModalPresent = useSettingModal()
const presentUserProfile = usePresentUserProfileModal("dialog")
const presentAchievement = useAchievementModal()
const { t } = useTranslation()
if (status !== "authenticated") {
return <LoginButton {...props} />
Expand Down Expand Up @@ -99,6 +101,15 @@ export const ProfileButton: FC<LoginProps> = memo((props) => {
>
{t("user_button.profile")}
</DropdownMenuItem>

<DropdownMenuItem
onClick={() => {
presentAchievement()
}}
icon={<i className="i-mgc-trophy-cute-re" />}
>
{t("user_button.achievement")}
</DropdownMenuItem>
<DropdownMenuSeparator />

<DropdownMenuItem
Expand Down
18 changes: 18 additions & 0 deletions apps/renderer/src/lib/chain.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import { sleep } from "./utils"

export class Chain {
private chain: Promise<void> = Promise.resolve()
private abortController = new AbortController()

next(fn: () => any | Promise<any>) {
const { signal } = this.abortController
this.chain = this.chain.then(() => {
if (signal.aborted) {
throw "Chain aborted"
}
return fn() || Promise.resolve()
})
}

wait(ms: number): this {
this.chain = this.chain.then(() => sleep(ms))
return this
}

abort() {
this.chain = Promise.resolve()
this.abortController.abort()
this.abortController = new AbortController()
}
}
Loading
Loading