Refactor to external scraper and update dependencies (#113)
This commit is contained in:
@@ -5,7 +5,7 @@ import theme from "@theme";
|
||||
|
||||
type Props = {
|
||||
customTitle?: string,
|
||||
home?: true
|
||||
home?: boolean
|
||||
};
|
||||
|
||||
const title = "Lingva Translate";
|
||||
|
||||
@@ -19,8 +19,8 @@ const Footer: FC<Props> = (props) => (
|
||||
spacing={[1, null, 2]}
|
||||
{...props}
|
||||
>
|
||||
<Link href="https://github.com/TheDavidDelta/lingva-translate/blob/main/LICENSE" isExternal={true}>
|
||||
<Text as="span">© 2021 TheDavidDelta & contributors</Text>
|
||||
<Link href="https://github.com/thedaviddelta/lingva-translate/blob/main/LICENSE" isExternal={true}>
|
||||
<Text as="span">© 2021 thedaviddelta & contributors</Text>
|
||||
</Link>
|
||||
<Text as="span" display={["none", null, "unset"]}>·</Text>
|
||||
<Link href="https://www.gnu.org/licenses/agpl-3.0.html" isExternal={true}>
|
||||
|
||||
@@ -42,7 +42,7 @@ const Header: FC<Props> = (props) => (
|
||||
/>
|
||||
<IconButton
|
||||
as={Link}
|
||||
href="https://github.com/TheDavidDelta/lingva-translate"
|
||||
href="https://github.com/thedaviddelta/lingva-translate"
|
||||
isExternal={true}
|
||||
aria-label="GitHub"
|
||||
icon={<FaGithub />}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { FC, ChangeEvent } from "react";
|
||||
import { Select } from "@chakra-ui/react";
|
||||
import { LangCode } from "lingva-scraper";
|
||||
|
||||
type Props = {
|
||||
value: string,
|
||||
onChange: (e: ChangeEvent<any>) => void,
|
||||
langs: [string, string][],
|
||||
langs: {
|
||||
[code in LangCode]: string
|
||||
},
|
||||
detectedSource?: LangCode<"source">,
|
||||
[key: string]: any
|
||||
};
|
||||
|
||||
const LangSelect: FC<Props> = ({ value, onChange, langs, ...props }) => (
|
||||
const LangSelect: FC<Props> = ({ value, onChange, langs, detectedSource, ...props }) => (
|
||||
<Select
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
@@ -18,8 +22,10 @@ const LangSelect: FC<Props> = ({ value, onChange, langs, ...props }) => (
|
||||
style={{ textAlignLast: "center" }}
|
||||
{...props}
|
||||
>
|
||||
{langs.map(([code, name]) => (
|
||||
<option value={code} key={code}>{name}</option>
|
||||
{Object.entries(langs).map(([code, name]) => (
|
||||
<option value={code} key={code}>
|
||||
{name}{code === "auto" && !!detectedSource && ` (${langs[detectedSource]})`}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FC } from "react";
|
||||
import { FC, PropsWithChildren } from "react";
|
||||
import { Flex, VStack, Button, Link, useColorModeValue } from "@chakra-ui/react";
|
||||
import { Header, Footer } from ".";
|
||||
|
||||
@@ -6,7 +6,7 @@ type Props = {
|
||||
[key: string]: any
|
||||
};
|
||||
|
||||
const Layout: FC<Props> = ({ children, ...props }) => (
|
||||
const Layout: FC<PropsWithChildren<Props>> = ({ children, ...props }) => (
|
||||
<>
|
||||
<Button
|
||||
as={Link}
|
||||
@@ -22,7 +22,7 @@ const Layout: FC<Props> = ({ children, ...props }) => (
|
||||
Skip to content
|
||||
</Button>
|
||||
|
||||
<VStack minH="100vh" spacing={8}>
|
||||
<VStack minH="100%" spacing={7}>
|
||||
<Header
|
||||
bgColor={useColorModeValue("lingva.100", "lingva.900")}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
import { FC } from "react";
|
||||
import { Box, HStack, Textarea, IconButton, Tooltip, Spinner, TextareaProps, useBreakpointValue, useColorModeValue, useClipboard } from "@chakra-ui/react";
|
||||
import {
|
||||
VStack,
|
||||
HStack,
|
||||
Text,
|
||||
Textarea,
|
||||
IconButton,
|
||||
Tooltip,
|
||||
Spinner,
|
||||
TextareaProps,
|
||||
useBreakpointValue,
|
||||
useColorModeValue,
|
||||
useClipboard
|
||||
} from "@chakra-ui/react";
|
||||
import { FaCopy, FaCheck, FaPlay, FaStop } from "react-icons/fa";
|
||||
import { useAudioFromBuffer } from "@hooks";
|
||||
|
||||
@@ -14,20 +26,32 @@ type Props = {
|
||||
[key: string]: any
|
||||
};
|
||||
|
||||
const TranslationArea: FC<Props> = ({ value, onChange, onSubmit, readOnly, audio, canCopy, isLoading, ...props }) => {
|
||||
const TranslationArea: FC<Props> = ({ value, onChange, onSubmit, readOnly, audio, canCopy, isLoading, pronunciation, ...props }) => {
|
||||
const { hasCopied, onCopy } = useClipboard(value);
|
||||
const { audioExists, isAudioPlaying, onAudioClick } = useAudioFromBuffer(audio);
|
||||
const spinnerProps = {
|
||||
size: useBreakpointValue(["lg", null, "xl"]) ?? undefined,
|
||||
size: useBreakpointValue(["lg", null, "xl"]) ?? "lg",
|
||||
color: useColorModeValue("lingva.500", "lingva.200"),
|
||||
emptyColor: useColorModeValue("gray.300", "gray.600")
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
position="relative"
|
||||
<VStack
|
||||
w="full"
|
||||
h={useBreakpointValue([44, null, 80]) ?? 44}
|
||||
align="stretch"
|
||||
spacing={0}
|
||||
position="relative"
|
||||
isolation="isolate"
|
||||
border="1px solid"
|
||||
borderColor={useColorModeValue("lingva.500", "lingva.200")}
|
||||
borderRadius="md"
|
||||
_hover={{
|
||||
borderColor: useColorModeValue("lingva.800", "lingva.400"),
|
||||
}}
|
||||
_readOnly={{
|
||||
userSelect: "auto"
|
||||
}}
|
||||
>
|
||||
<Textarea
|
||||
value={value}
|
||||
@@ -35,54 +59,66 @@ const TranslationArea: FC<Props> = ({ value, onChange, onSubmit, readOnly, audio
|
||||
readOnly={readOnly}
|
||||
dir="auto"
|
||||
resize="none"
|
||||
rows={useBreakpointValue([6, null, 12]) ?? undefined}
|
||||
size="lg"
|
||||
variant="ghost"
|
||||
boxShadow={`inset 0 0 1px ${useColorModeValue("hsl(146 100% 17% / 25%)", "hsl(142 40% 82% / 25%)")}`}
|
||||
data-gramm_editor={false}
|
||||
onKeyPress={e => (e.ctrlKey || e.metaKey) && e.key === "Enter" && onSubmit?.()}
|
||||
flex={1}
|
||||
bgColor="transparent"
|
||||
_focus={{
|
||||
bgColor: useColorModeValue("hsl(0deg 0% 0% / 2.5%)", "hsl(0deg 0% 100% / 2.5%)")
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
<HStack
|
||||
position="absolute"
|
||||
bottom={4}
|
||||
right={4}
|
||||
// Needed because the textarea stacks over on focus
|
||||
zIndex={3}
|
||||
position={!pronunciation ? "absolute" : undefined}
|
||||
pointerEvents={!pronunciation ? "none" : undefined}
|
||||
bottom={0}
|
||||
left={0}
|
||||
right={0}
|
||||
>
|
||||
{canCopy && (
|
||||
<Tooltip label={hasCopied ? "Copied!" : "Copy to clipboard"}>
|
||||
<IconButton
|
||||
aria-label="Copy to clipboard"
|
||||
icon={hasCopied ? <FaCheck /> : <FaCopy />}
|
||||
onClick={onCopy}
|
||||
colorScheme="lingva"
|
||||
variant="ghost"
|
||||
disabled={!value}
|
||||
/>
|
||||
<HStack justify="space-between" px={5} h={useBreakpointValue([12, null, 14]) ?? 12} w="0px" flex={1}>
|
||||
<Tooltip label={pronunciation}>
|
||||
<Text aria-label="Pronunciation" opacity={0.75} whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis">
|
||||
{pronunciation}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip label={isAudioPlaying ? "Stop audio" : "Play audio"}>
|
||||
<IconButton
|
||||
aria-label={isAudioPlaying ? "Stop audio" : "Play audio"}
|
||||
icon={isAudioPlaying ? <FaStop /> : <FaPlay />}
|
||||
onClick={onAudioClick}
|
||||
colorScheme="lingva"
|
||||
variant="ghost"
|
||||
disabled={!audioExists}
|
||||
/>
|
||||
</Tooltip>
|
||||
<HStack pointerEvents="auto">
|
||||
{canCopy && (
|
||||
<Tooltip label={hasCopied ? "Copied!" : "Copy to clipboard"}>
|
||||
<IconButton
|
||||
aria-label="Copy to clipboard"
|
||||
icon={hasCopied ? <FaCheck /> : <FaCopy />}
|
||||
onClick={onCopy}
|
||||
colorScheme="lingva"
|
||||
variant="ghost"
|
||||
disabled={!value}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip label={isAudioPlaying ? "Stop audio" : "Play audio"}>
|
||||
<IconButton
|
||||
aria-label={isAudioPlaying ? "Stop audio" : "Play audio"}
|
||||
icon={isAudioPlaying ? <FaStop /> : <FaPlay />}
|
||||
onClick={onAudioClick}
|
||||
colorScheme="lingva"
|
||||
variant="ghost"
|
||||
disabled={!audioExists}
|
||||
/>
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
</HStack>
|
||||
</HStack>
|
||||
{isLoading && <Spinner
|
||||
position="absolute"
|
||||
top="0"
|
||||
bottom="0"
|
||||
left="0"
|
||||
right="0"
|
||||
m="auto"
|
||||
inset={0}
|
||||
m="auto !important"
|
||||
thickness="3px"
|
||||
label="Loading translation"
|
||||
{...spinnerProps}
|
||||
/>}
|
||||
</Box>
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user