Skip to content

Commit

Permalink
feat(audio-view): seek circle indicator
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei committed Sep 20, 2024
1 parent 16a6231 commit 94b9535
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 8 deletions.
70 changes: 67 additions & 3 deletions apps/renderer/src/components/ui/markdown/components/TimeStamp.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,92 @@
import { AudioPlayer } from "~/atoms/player"
import { nextFrame } from "~/lib/dom"
import { useEntryContentContext } from "~/modules/entry-content/hooks"
import { useEntry } from "~/store/entry"

import { timeStringToSeconds } from "../utils"

export const TimeStamp = (props: { time: string }) => {
const { entryId, audioSrc: src } = useEntryContentContext()

const entry = useEntry(entryId)
const mediaDuration = entry?.entries.attachments?.[0]?.duration_in_seconds

if (!src) return <span>{props.time}</span>

const seekTo = timeStringToSeconds(props.time)
if (typeof seekTo !== "number") return <span>{props.time}</span>

return (
<span
className="cursor-pointer tabular-nums text-accent dark:text-theme-accent-500"
className="inline-flex cursor-pointer items-center tabular-nums text-accent dark:text-theme-accent-500"
onClick={() => {
AudioPlayer.mount({
type: "audio",
entryId,
src,
currentTime: 0,
})
nextFrame(() => AudioPlayer.seek(timeStringToSeconds(props.time) || 0))
nextFrame(() => AudioPlayer.seek(seekTo))
}}
>
<i className="i-mgc-time-cute-re mr-1 translate-y-0.5" />
{/* <i className="i-mgc-time-cute-re mr-1 translate-y-0.5" /> */}
{!!mediaDuration && (
<CircleProgress
className="mr-1 scale-95"
percent={(seekTo / mediaDuration) * 100}
size={16}
strokeWidth={2}
/>
)}
{props.time}
</span>
)
}

interface CircleProgressProps {
percent: number
size?: number
strokeWidth?: number
strokeColor?: string
backgroundColor?: string
className?: string
}

const CircleProgress: React.FC<CircleProgressProps> = ({
percent,
size = 100,
strokeWidth = 8,
strokeColor = "hsl(var(--fo-a))",
backgroundColor = "hsl(var(--fo-inactive))",
className,
}) => {
const normalizedPercent = Math.min(100, Math.max(0, percent))
const radius = (size - strokeWidth) / 2
const circumference = radius * 2 * Math.PI
const offset = circumference - (normalizedPercent / 100) * circumference

return (
<svg width={size} height={size} className={className}>
<circle
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
stroke={backgroundColor}
strokeWidth={strokeWidth}
/>
<circle
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
stroke={strokeColor}
strokeWidth={strokeWidth}
strokeDasharray={circumference}
strokeDashoffset={offset}
transform={`rotate(-90 ${size / 2} ${size / 2})`}
style={{ transition: "stroke-dashoffset 0.3s" }}
/>
</svg>
)
}
4 changes: 4 additions & 0 deletions apps/renderer/src/styles/colors.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[data-theme="light"] {
--fo-a: 21.6, 100%, 50%;

--fo-vibrancy-background: theme(colors.native.active);
--fo-vibrancy-foreground: 0, 0%, 45%;

Expand All @@ -21,6 +23,8 @@
}

[data-theme="dark"] {
--fo-a: 21.6, 100%, 50%;

--fo-vibrancy-foreground: 0, 0%, 83%;
--fo-vibrancy-background: theme(colors.native.active);

Expand Down
7 changes: 2 additions & 5 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ export default resolveConfig({
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
foreground: "hsl(var(--muted-foreground) / <alpha-value>)",
},
accent: {
DEFAULT: "#ff5c00",
foreground: "hsl(var(--fo-text-primary), <alpha-value>)",
},
accent: "hsl(var(--fo-a) / <alpha-value>)",

popover: {
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
Expand All @@ -61,7 +58,7 @@ export default resolveConfig({
theme: {
// https://uicolors.app/create
accent: {
DEFAULT: "#ff5c00",
DEFAULT: "hsl(var(--fo-a) / <alpha-value>)",
50: "#fff7ec",
100: "#ffeed3",
200: "#ffd9a5",
Expand Down

0 comments on commit 94b9535

Please sign in to comment.