Skip to content

Commit

Permalink
Merge branch 'RSSNext:dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
cuikaipeng authored Sep 24, 2024
2 parents 318b40c + c63862d commit 6700dbf
Show file tree
Hide file tree
Showing 55 changed files with 950 additions and 57 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/pr-title-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: PR Conventional Commit Validation

on:
pull_request:
types: [opened, synchronize, reopened, edited]

jobs:
validate-pr-title:
runs-on: ubuntu-latest
steps:
- name: PR Conventional Commit Validation
uses: ytanikin/[email protected]
with:
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
custom_labels: '{"feat": "feature", "fix": "fix", "docs": "documentation", "test": "test", "ci": "CI/CD", "refactor": "refactor", "perf": "performance", "chore": "chore", "revert": "revert"}'
19 changes: 14 additions & 5 deletions apps/main/src/lib/cleaner.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { callGlobalContextMethod } from "@follow/shared/bridge"
import { callWindowExpose } from "@follow/shared/bridge"
import { dialog } from "electron"

import { getMainWindow } from "~/window"

import { t } from "./i18n"

export const clearAllData = async () => {
export const clearAllDataAndConfirm = async () => {
const win = getMainWindow()
if (!win) return
const ses = win.webContents.session

// Dialog to confirm
const result = await dialog.showMessageBox({
Expand All @@ -21,6 +20,15 @@ export const clearAllData = async () => {
if (result.response === 1) {
return
}
return clearAllData()
}

export const clearAllData = async () => {
const win = getMainWindow()
if (!win) return
const ses = win.webContents.session
const caller = callWindowExpose(win)

try {
await ses.clearCache()

Expand All @@ -36,11 +44,12 @@ export const clearAllData = async () => {
"cookies",
],
})
callGlobalContextMethod(win, "toast.success", ["App data reset successfully"])

caller.toast.success("App data reset successfully")

// reload the app
win.reload()
} catch (error: any) {
callGlobalContextMethod(win, "toast.error", [`Error resetting app data: ${error.message}`])
caller.toast.error(`Error resetting app data: ${error.message}`)
}
}
4 changes: 2 additions & 2 deletions apps/main/src/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { BrowserWindow, MenuItem, MenuItemConstructorOptions } from "electr
import { Menu } from "electron"

import { isDev, isMacOS } from "./env"
import { clearAllData } from "./lib/cleaner"
import { clearAllDataAndConfirm } from "./lib/cleaner"
import { t } from "./lib/i18n"
import { revealLogFile } from "./logger"
import { checkForUpdates, quitAndInstall } from "./updater"
Expand Down Expand Up @@ -38,7 +38,7 @@ export const registerAppMenu = () => {
{ type: "separator" },
{
label: t("menu.clearAllData"),
click: clearAllData,
click: clearAllDataAndConfirm,
},
{ role: "quit", label: t("menu.quit", { name }) },
],
Expand Down
10 changes: 7 additions & 3 deletions apps/main/src/tipc/app.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from "node:path"

import { getRendererHandlers } from "@egoist/tipc/main"
import { callGlobalContextMethod } from "@follow/shared/bridge"
import { callWindowExpose } from "@follow/shared/bridge"
import type { BrowserWindow } from "electron"
import { app, clipboard, dialog, screen } from "electron"

Expand Down Expand Up @@ -199,13 +199,17 @@ export const appRoute = {
await downloadFile(input, result.filePath).catch((err) => {
const senderWindow = (sender as Sender).getOwnerBrowserWindow()
if (!senderWindow) return
callGlobalContextMethod(senderWindow, "toast.error", ["Download failed!"])
callWindowExpose(senderWindow).toast.error("Download failed!", {
duration: 1000,
})
throw err
})

const senderWindow = (sender as Sender).getOwnerBrowserWindow()
if (!senderWindow) return
callGlobalContextMethod(senderWindow, "toast.success", ["Download success!"])
callWindowExpose(senderWindow).toast.success("Download success!", {
duration: 1000,
})
}),

getAppPath: t.procedure.action(async () => app.getAppPath()),
Expand Down
20 changes: 7 additions & 13 deletions apps/main/src/tipc/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from "node:fs"
import { createRequire } from "node:module"
import path from "node:path"

import { callGlobalContextMethod } from "@follow/shared/bridge"
import { callWindowExpose } from "@follow/shared/bridge"
import { app, BrowserWindow } from "electron"
import { MsEdgeTTS, OUTPUT_FORMAT } from "msedge-tts"

Expand Down Expand Up @@ -54,12 +54,9 @@ export const readerRoute = {
if (!window) {
return
}
callGlobalContextMethod(window, "toast.error", [
error.message,
{
duration: 1000,
},
])
callWindowExpose(window).toast.error(error.message, {
duration: 1000,
})
}
}),

Expand All @@ -70,12 +67,9 @@ export const readerRoute = {
}

await tts.setMetadata(input, OUTPUT_FORMAT.WEBM_24KHZ_16BIT_MONO_OPUS).catch((error) => {
callGlobalContextMethod(window, "toast.error", [
error.message,
{
duration: 1000,
},
])
callWindowExpose(window).toast.error(error.message, {
duration: 1000,
})
})
}),

Expand Down
14 changes: 9 additions & 5 deletions apps/main/src/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from "node:path"
import { fileURLToPath } from "node:url"

import { is } from "@electron-toolkit/utils"
import { callGlobalContextMethod } from "@follow/shared/bridge"
import { callWindowExpose } from "@follow/shared/bridge"
import { imageRefererMatches } from "@follow/shared/image"
import type { BrowserWindowConstructorOptions } from "electron"
import { BrowserWindow, screen, shell } from "electron"
Expand Down Expand Up @@ -219,7 +219,8 @@ export const createMainWindow = () => {
window.hide()
}

callGlobalContextMethod(window, "electronClose")
const caller = callWindowExpose(window)
caller.electronClose()
} else {
windows.mainWindow = null
}
Expand All @@ -228,11 +229,13 @@ export const createMainWindow = () => {
window.on("show", () => {
cancelPollingUpdateUnreadCount()

callGlobalContextMethod(window, "electronShow")
const caller = callWindowExpose(window)
caller.electronShow()
})

window.on("hide", async () => {
const settings = await callGlobalContextMethod(window, "getUISettings")
const caller = callWindowExpose(window)
const settings = await caller.getUISettings()

if (settings.showDockBadge) {
pollingUpdateUnreadCount()
Expand All @@ -247,7 +250,8 @@ export const createSettingWindow = (path?: string) => {
// if we open a new window then the state between the two windows will be out of sync.
if (windows.mainWindow && windows.mainWindow.isVisible()) {
windows.mainWindow.show()
callGlobalContextMethod(windows.mainWindow, "showSetting", [path])

callWindowExpose(windows.mainWindow).showSetting(path)
return
}
if (windows.settingWindow) {
Expand Down
7 changes: 7 additions & 0 deletions apps/renderer/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,11 @@ declare global {
platform: NodeJS.Platform
}
}

declare module "react" {
export interface AriaAttributes {
"data-testid"?: string
}
}

export {}
2 changes: 2 additions & 0 deletions apps/renderer/src/@types/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const currentSupportedLanguages = [
"ru",
"es",
"ko",
"tr",
]
export const dayjsLocaleImportMap = {
en: ["en", () => import("dayjs/locale/en")],
Expand All @@ -39,6 +40,7 @@ export const dayjsLocaleImportMap = {
["ar-TN"]: ["ar-tn", () => import("dayjs/locale/ar-tn")],
["zh-HK"]: ["zh-hk", () => import("dayjs/locale/zh-hk")],
["ko"]: ["ko", () => import("dayjs/locale/ko")],
["tr"]: ["tr", () => import("dayjs/locale/tr")],
}
export const ns = ["app", "common", "lang", "settings", "shortcuts", "errors"] as const
export const defaultNS = "app" as const
3 changes: 3 additions & 0 deletions apps/renderer/src/@types/default-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import common_ja from "../../../../locales/common/ja.json"
import common_ko from "../../../../locales/common/ko.json"
import common_pt from "../../../../locales/common/pt.json"
import common_ru from "../../../../locales/common/ru.json"
import common_tr from "../../../../locales/common/tr.json"
import common_zhCN from "../../../../locales/common/zh-CN.json"
import common_zhHK from "../../../../locales/common/zh-HK.json"
import common_zhTW from "../../../../locales/common/zh-TW.json"
Expand All @@ -36,6 +37,7 @@ import lang_ja from "../../../../locales/lang/ja.json"
import lang_ko from "../../../../locales/lang/ko.json"
import lang_pt from "../../../../locales/lang/pt.json"
import lang_ru from "../../../../locales/lang/ru.json"
import lang_tr from "../../../../locales/lang/tr.json"
import lang_zhCN from "../../../../locales/lang/zh-CN.json"
import lang_zhHK from "../../../../locales/lang/zh-HK.json"
import lang_zhTW from "../../../../locales/lang/zh-TW.json"
Expand Down Expand Up @@ -85,4 +87,5 @@ export const defaultResources = {
"ar-KW": { lang: lang_arkw, common: common_arkw },
"ar-TN": { lang: lang_artn, common: common_artn },
ko: { lang: lang_ko, common: common_ko },
tr: { lang: lang_tr, common: common_tr },
}
99 changes: 99 additions & 0 deletions apps/renderer/src/components/ui/lottie-container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import type { DotLottie } from "@lottiefiles/dotlottie-react"
import { DotLottieReact } from "@lottiefiles/dotlottie-react"
import { atom, useAtomValue } from "jotai"
import type { FC, ReactNode, RefCallback } from "react"
import { useEffect, useState } from "react"

import { jotaiStore } from "~/lib/jotai"

import { RootPortal } from "../portal"

const portalElementsAtom = atom([] as ReactNode[])

export function LottieRenderContainer() {
const elements = useAtomValue(portalElementsAtom, { store: jotaiStore })

return (
<RootPortal>
<div className="pointer-events-none fixed z-[999]" data-testid="lottie-render-container">
{elements.map((element) => element)}
</div>
</RootPortal>
)
}

type LottieOptions = {
once?: boolean

x: number
y: number

height?: number
width?: number
className?: string

onComplete?: () => void

speed?: number
}
export const mountLottie = (url: string, options: LottieOptions) => {
const { once = true, height, width, x, y, className, speed } = options

const Lottie: FC = () => {
const [dotLottie, setDotLottie] = useState<DotLottie | null>(null)

useEffect(() => {
function onComplete() {
if (once) {
unmount()
}

options.onComplete?.()
}

if (dotLottie) {
dotLottie.addEventListener("complete", onComplete)
}

return () => {
if (dotLottie) {
dotLottie.removeEventListener("complete", onComplete)
}
}
}, [dotLottie])

const dotLottieRefCallback: RefCallback<DotLottie> = (dotLottie) => {
setDotLottie(dotLottie)
}

return (
<DotLottieReact
speed={speed}
dotLottieRefCallback={dotLottieRefCallback}
src={url}
autoplay
loop={false}
height={height}
width={width}
style={{
height,
width,
position: "fixed",

left: 0,
top: 0,
transform: `translate(${x}px, ${y}px)`,
}}
className={className}
/>
)
}

const element = <Lottie />
const unmount = () => {
jotaiStore.set(portalElementsAtom, (prev) => prev.filter((e) => e !== element))
}

jotaiStore.set(portalElementsAtom, (prev) => [...prev, element])
return unmount
}
16 changes: 14 additions & 2 deletions apps/renderer/src/components/ui/modal/stacked/custom-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ export const PlainModal = ({ children }: PropsWithChildren) => children

export { PlainModal as NoopChildren }

export const SlideUpModal = (props: PropsWithChildren) => {
type ModalTemplateType = {
(props: PropsWithChildren<{ className?: string }>): JSX.Element
class: (className: string) => (props: PropsWithChildren<{ className?: string }>) => JSX.Element
}

export const SlideUpModal: ModalTemplateType = (props) => {
const winHeight = useState(() => window.innerHeight)[0]
const { dismiss } = useCurrentModal()
return (
Expand All @@ -39,7 +44,8 @@ export const SlideUpModal = (props: PropsWithChildren) => {
}}
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)]",
"aspect-[7/9] w-[600px] max-w-full shadow lg:max-h-[calc(100vh-10rem)]",
props.className,
)}
>
{props.children}
Expand All @@ -49,3 +55,9 @@ export const SlideUpModal = (props: PropsWithChildren) => {
</div>
)
}

SlideUpModal.class = (className: string) => {
return (props: ComponentType) => (
<SlideUpModal {...props} className={cn(props.className, className)} />
)
}
Loading

0 comments on commit 6700dbf

Please sign in to comment.