omnivore/packages/web/components/templates/AddLinkModal.tsx

832 lines
23 KiB
TypeScript
Raw Permalink Normal View History

2024-02-08 07:01:40 +00:00
import { useCallback, useRef, useState } from 'react'
import * as Progress from '@radix-ui/react-progress'
2024-06-10 09:34:38 +00:00
import { File, Info } from '@phosphor-icons/react'
import { locale, timeZone } from '../../lib/dateFormatting'
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
import { Button } from '../elements/Button'
import { FormInput } from '../elements/FormElements'
import { Box, HStack, SpanBox, VStack } from '../elements/LayoutPrimitives'
2023-03-20 09:02:30 +00:00
import {
ModalContent,
ModalOverlay,
ModalRoot,
} from '../elements/ModalPrimitives'
import { CloseButton } from '../elements/CloseButton'
2024-02-08 07:01:40 +00:00
import { styled } from '@stitches/react'
import Dropzone, {
Accept,
DropEvent,
DropzoneRef,
FileRejection,
} from 'react-dropzone'
import { v4 as uuidv4 } from 'uuid'
import { validateCsvFile } from '../../utils/csvValidator'
2024-02-08 07:01:40 +00:00
import {
uploadImportFileRequestMutation,
UploadImportFileType,
} from '../../lib/networking/mutations/uploadImportFileMutation'
import { uploadFileRequestMutation } from '../../lib/networking/mutations/uploadFileMutation'
2024-02-08 07:01:40 +00:00
import axios from 'axios'
import { theme } from '../tokens/stitches.config'
import { formatMessage } from '../../locales/en/messages'
import { subscribeMutation } from '../../lib/networking/mutations/subscribeMutation'
import { SubscriptionType } from '../../lib/networking/queries/useGetSubscriptionsQuery'
2024-02-08 07:01:40 +00:00
type TabName = 'link' | 'feed' | 'opml' | 'pdf' | 'import'
2022-02-11 17:24:33 +00:00
type AddLinkModalProps = {
onOpenChange: (open: boolean) => void
handleLinkSubmission: (
link: string,
timezone: string,
locale: string
) => Promise<void>
2022-02-11 17:24:33 +00:00
}
export function AddLinkModal(props: AddLinkModalProps): JSX.Element {
2024-02-08 07:01:40 +00:00
const [selectedTab, setSelectedTab] = useState('link')
return (
<ModalRoot defaultOpen onOpenChange={props.onOpenChange} css={{}}>
<ModalOverlay />
<ModalContent
css={{
p: '20px',
bg: '$modalBackground',
maxWidth: '600',
maxHeight: '300',
fontFamily: '$inter',
}}
2024-02-29 13:43:56 +00:00
onInteractOutside={(event) => {
event.preventDefault()
2024-02-08 07:01:40 +00:00
}}
>
<VStack distribution="start" css={{ gap: '20px' }}>
Improving Self-Hosting and Removing 3rd Party dependencies. (#4513) * fix: Library Header layout shift * Bump Github Actions versions. * Self-Hosting Changes * Fix Minio Environment Variable * Just make pdfs successful, due to lack of PDFHandler * Fix issue where flag was set wrong * Added an NGINX Example file * Add some documentation for self-hosting via Docker Compose * Make some adjustments to Puppeteer due to failing sites. * adjust timings * Add start of Mail Service * Fix Docker Files * More email service stuff * Add Guide to use Zapier for Email-Importing. * Ensure that if no env is provided it uses the old email settings * Add some instructions for self-hosted email * Add SNS Endpoints for Mail Watcher * Add steps and functionality for using SES and SNS for email * Uncomment a few jobs. * Added option for Firefox for parser. Was having issues with Chromium on Docker. * Add missing space. Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> * Fix some wording on the Guide * update browser extension to handle self-hosted instances * add slight documentation to options page * Fix MV * Do raw handlers for Medium * Fix images in Medium * Update self-hosting/GUIDE.md Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update Guide with other variables * Add The Verge to JS-less handlers * Update regex and image-proxy * Update self-hosting/nginx/nginx.conf Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update regex and image-proxy * Update self-hosting/docker-compose/docker-compose.yml Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Fix Minio for Export * Merge to main * Update GUIDE with newer NGINX * Update nginx config to include api/save route * Enable Native PDF View for PDFS * Enable Native PDF View for PDFS * feat:lover packages test * feat:working build * feat:alpine build * docs:api dockerfile docs * Write a PDF.js wrapper to replace pspdfkit * Revert changes for replication, set settings to have default mode * build folder got removed due to gitignore on pdf * Add Box shadow to pdf pages * Add Toggle for Progress in PDFS, enabled native viewer toggle * Update node version to LTS * Update node version to LTS * Fix Linting issues * Fix Linting issues * Make env variable nullable * Add touchend listener for mobile * Make changes to PDF for mobile * fix(android): change serverUrl to selfhosted first * feat:2 stage alpine content fetch * feat:separated start script * fix:changed to node 22 * Add back youtube functionality and add guide * trigger build * Fix cache issue on YouTube * Allow empty AWS_S3_ENDPOINT * Allow empty AWS_S3_ENDPOINT * Add GCHR for all images * Add GCHR For self hosting. * Add GCHR For self hosting. * Test prebuilt. * Test prebuilt * Test prebuilt... * Fix web image * Remove Web Image (For now) * Move docker-compose to images * Move docker-compose files to correct locations * Remove the need for ARGS * Update packages, and Typescript versions * Fix * Fix issues with build on Web * Correct push * Fix Linting issues * Fix Trace import * Add missing types * Fix Tasks * Add information into guide about self-build * Fix issues with PDF Viewer --------- Co-authored-by: keumky2 <keumky2@woowahan.com> Co-authored-by: William Theaker <wtheaker@nvidia.com> Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> Co-authored-by: David Adams <david@dadams2.com> Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> Co-authored-by: m1xxos <66390094+m1xxos@users.noreply.github.com> Co-authored-by: Adil <mr.adil777@gmail.com>
2025-01-27 12:33:16 +00:00
<TabBar
2024-02-08 07:01:40 +00:00
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
onOpenChange={props.onOpenChange}
Improving Self-Hosting and Removing 3rd Party dependencies. (#4513) * fix: Library Header layout shift * Bump Github Actions versions. * Self-Hosting Changes * Fix Minio Environment Variable * Just make pdfs successful, due to lack of PDFHandler * Fix issue where flag was set wrong * Added an NGINX Example file * Add some documentation for self-hosting via Docker Compose * Make some adjustments to Puppeteer due to failing sites. * adjust timings * Add start of Mail Service * Fix Docker Files * More email service stuff * Add Guide to use Zapier for Email-Importing. * Ensure that if no env is provided it uses the old email settings * Add some instructions for self-hosted email * Add SNS Endpoints for Mail Watcher * Add steps and functionality for using SES and SNS for email * Uncomment a few jobs. * Added option for Firefox for parser. Was having issues with Chromium on Docker. * Add missing space. Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> * Fix some wording on the Guide * update browser extension to handle self-hosted instances * add slight documentation to options page * Fix MV * Do raw handlers for Medium * Fix images in Medium * Update self-hosting/GUIDE.md Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update Guide with other variables * Add The Verge to JS-less handlers * Update regex and image-proxy * Update self-hosting/nginx/nginx.conf Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update regex and image-proxy * Update self-hosting/docker-compose/docker-compose.yml Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Fix Minio for Export * Merge to main * Update GUIDE with newer NGINX * Update nginx config to include api/save route * Enable Native PDF View for PDFS * Enable Native PDF View for PDFS * feat:lover packages test * feat:working build * feat:alpine build * docs:api dockerfile docs * Write a PDF.js wrapper to replace pspdfkit * Revert changes for replication, set settings to have default mode * build folder got removed due to gitignore on pdf * Add Box shadow to pdf pages * Add Toggle for Progress in PDFS, enabled native viewer toggle * Update node version to LTS * Update node version to LTS * Fix Linting issues * Fix Linting issues * Make env variable nullable * Add touchend listener for mobile * Make changes to PDF for mobile * fix(android): change serverUrl to selfhosted first * feat:2 stage alpine content fetch * feat:separated start script * fix:changed to node 22 * Add back youtube functionality and add guide * trigger build * Fix cache issue on YouTube * Allow empty AWS_S3_ENDPOINT * Allow empty AWS_S3_ENDPOINT * Add GCHR for all images * Add GCHR For self hosting. * Add GCHR For self hosting. * Test prebuilt. * Test prebuilt * Test prebuilt... * Fix web image * Remove Web Image (For now) * Move docker-compose to images * Move docker-compose files to correct locations * Remove the need for ARGS * Update packages, and Typescript versions * Fix * Fix issues with build on Web * Correct push * Fix Linting issues * Fix Trace import * Add missing types * Fix Tasks * Add information into guide about self-build * Fix issues with PDF Viewer --------- Co-authored-by: keumky2 <keumky2@woowahan.com> Co-authored-by: William Theaker <wtheaker@nvidia.com> Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> Co-authored-by: David Adams <david@dadams2.com> Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> Co-authored-by: m1xxos <66390094+m1xxos@users.noreply.github.com> Co-authored-by: Adil <mr.adil777@gmail.com>
2025-01-27 12:33:16 +00:00
/>
2024-02-08 07:01:40 +00:00
<Box css={{ width: '100%' }}>
{selectedTab == 'link' && <AddLinkTab {...props} />}
Improving Self-Hosting and Removing 3rd Party dependencies. (#4513) * fix: Library Header layout shift * Bump Github Actions versions. * Self-Hosting Changes * Fix Minio Environment Variable * Just make pdfs successful, due to lack of PDFHandler * Fix issue where flag was set wrong * Added an NGINX Example file * Add some documentation for self-hosting via Docker Compose * Make some adjustments to Puppeteer due to failing sites. * adjust timings * Add start of Mail Service * Fix Docker Files * More email service stuff * Add Guide to use Zapier for Email-Importing. * Ensure that if no env is provided it uses the old email settings * Add some instructions for self-hosted email * Add SNS Endpoints for Mail Watcher * Add steps and functionality for using SES and SNS for email * Uncomment a few jobs. * Added option for Firefox for parser. Was having issues with Chromium on Docker. * Add missing space. Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> * Fix some wording on the Guide * update browser extension to handle self-hosted instances * add slight documentation to options page * Fix MV * Do raw handlers for Medium * Fix images in Medium * Update self-hosting/GUIDE.md Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update Guide with other variables * Add The Verge to JS-less handlers * Update regex and image-proxy * Update self-hosting/nginx/nginx.conf Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update regex and image-proxy * Update self-hosting/docker-compose/docker-compose.yml Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Fix Minio for Export * Merge to main * Update GUIDE with newer NGINX * Update nginx config to include api/save route * Enable Native PDF View for PDFS * Enable Native PDF View for PDFS * feat:lover packages test * feat:working build * feat:alpine build * docs:api dockerfile docs * Write a PDF.js wrapper to replace pspdfkit * Revert changes for replication, set settings to have default mode * build folder got removed due to gitignore on pdf * Add Box shadow to pdf pages * Add Toggle for Progress in PDFS, enabled native viewer toggle * Update node version to LTS * Update node version to LTS * Fix Linting issues * Fix Linting issues * Make env variable nullable * Add touchend listener for mobile * Make changes to PDF for mobile * fix(android): change serverUrl to selfhosted first * feat:2 stage alpine content fetch * feat:separated start script * fix:changed to node 22 * Add back youtube functionality and add guide * trigger build * Fix cache issue on YouTube * Allow empty AWS_S3_ENDPOINT * Allow empty AWS_S3_ENDPOINT * Add GCHR for all images * Add GCHR For self hosting. * Add GCHR For self hosting. * Test prebuilt. * Test prebuilt * Test prebuilt... * Fix web image * Remove Web Image (For now) * Move docker-compose to images * Move docker-compose files to correct locations * Remove the need for ARGS * Update packages, and Typescript versions * Fix * Fix issues with build on Web * Correct push * Fix Linting issues * Fix Trace import * Add missing types * Fix Tasks * Add information into guide about self-build * Fix issues with PDF Viewer --------- Co-authored-by: keumky2 <keumky2@woowahan.com> Co-authored-by: William Theaker <wtheaker@nvidia.com> Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> Co-authored-by: David Adams <david@dadams2.com> Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> Co-authored-by: m1xxos <66390094+m1xxos@users.noreply.github.com> Co-authored-by: Adil <mr.adil777@gmail.com>
2025-01-27 12:33:16 +00:00
{selectedTab == 'feed' && <AddFeedTab {...props} />}
2024-02-16 04:32:22 +00:00
{selectedTab == 'opml' && <UploadOPMLTab />}
{selectedTab == 'pdf' && <UploadPDFTab />}
2024-02-08 07:01:40 +00:00
</Box>
</VStack>
</ModalContent>
</ModalRoot>
)
}
const AddLinkTab = (props: AddLinkModalProps): JSX.Element => {
2024-02-29 13:43:56 +00:00
const [errorMessage, setErrorMessage] = useState<string | undefined>(
undefined
)
2024-02-08 07:01:40 +00:00
const addLink = useCallback(
async (link: string) => {
await props.handleLinkSubmission(link, timeZone, locale)
props.onOpenChange(false)
},
2024-02-16 04:25:45 +00:00
[props, errorMessage, setErrorMessage]
2024-02-08 07:01:40 +00:00
)
return (
<AddFromURL
placeholder="https://example.com/"
errorMessage={errorMessage}
setErrorMessage={setErrorMessage}
onSubmit={addLink}
/>
)
}
const AddFeedTab = (props: AddLinkModalProps): JSX.Element => {
2024-02-29 13:43:56 +00:00
const [errorMessage, setErrorMessage] = useState<string | undefined>(
undefined
)
2024-02-08 07:01:40 +00:00
const subscribe = useCallback(
async (feedUrl: string) => {
if (!feedUrl) {
setErrorMessage('Please enter a valid feed URL')
return
}
let normailizedUrl: string
// normalize the url
try {
normailizedUrl = new URL(feedUrl.trim()).toString()
} catch (e) {
setErrorMessage('Please enter a valid feed URL')
return
}
2022-02-11 17:24:33 +00:00
2024-02-08 07:01:40 +00:00
const result = await subscribeMutation({
url: normailizedUrl,
subscriptionType: SubscriptionType.RSS,
})
if (result.subscribe.errorCodes) {
const errorMessage = formatMessage({
id: `error.${result.subscribe.errorCodes[0]}`,
})
setErrorMessage(`There was an error adding new feed: ${errorMessage}`)
return
}
showSuccessToast('New feed has been added.')
props.onOpenChange(false)
2024-02-08 07:01:40 +00:00
},
2024-02-16 04:25:45 +00:00
[props, errorMessage, setErrorMessage]
2024-02-08 07:01:40 +00:00
)
return (
<AddFromURL
placeholder="https://example.com/feed.atom"
errorMessage={errorMessage}
setErrorMessage={setErrorMessage}
onSubmit={subscribe}
/>
)
}
type AddFromURLProps = {
placeholder: string
errorMessage: string | undefined
setErrorMessage: (message: string) => void
onSubmit: (url: string) => Promise<void>
}
const AddFromURL = (props: AddFromURLProps): JSX.Element => {
const [url, setURL] = useState('')
2024-02-16 04:25:45 +00:00
const validateURL = useCallback((link: string) => {
try {
const url = new URL(link)
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
2022-02-11 17:24:33 +00:00
return false
}
2024-02-16 04:25:45 +00:00
} catch (e) {
return false
}
return true
}, [])
2022-02-11 17:24:33 +00:00
return (
2024-02-08 07:01:40 +00:00
<VStack css={{ width: '100%', height: '180px' }}>
<form
style={{
display: 'flex',
flexDirection: 'column',
width: '100%',
height: '100%',
paddingTop: '5px',
}}
onSubmit={async (event) => {
event.preventDefault()
if (!validateURL(url)) {
props.setErrorMessage('Invalid URL')
2024-02-08 07:01:40 +00:00
return
}
props.onSubmit(url)
2022-02-11 17:24:33 +00:00
}}
>
2024-02-08 07:01:40 +00:00
<FormInput
type="url"
value={url}
autoFocus={true}
placeholder={props.placeholder}
onChange={(event) => setURL(event.target.value)}
css={{
borderRadius: '4px',
width: '100%',
height: '38px',
p: '6px',
mb: '13px',
fontSize: '14px',
color: '$thTextContrast',
2024-02-09 04:06:22 +00:00
bg: '$thFormInput',
2024-02-08 07:01:40 +00:00
}}
/>
{props.errorMessage && (
<HStack
distribution="start"
alignment="start"
css={{
width: '100%',
bg: '#FF000010',
p: '5px',
pl: '10px',
fontSize: '12px',
fontFamily: '$inter',
textAlign: 'center',
color: '$ctaBlue',
borderRadius: '5px',
}}
>
<HStack
distribution="start"
alignment="center"
css={{ gap: '5px', whiteSpace: 'pre-line', color: 'red' }}
>
<Info size={14} color="red" />
{props.errorMessage}
</HStack>
</HStack>
)}
2024-02-08 07:01:40 +00:00
<Button
2024-05-07 04:10:33 +00:00
style="ctaOmnivoreYellow"
2024-02-08 07:01:40 +00:00
type="submit"
2024-05-07 04:10:33 +00:00
css={{
marginLeft: 'auto',
marginTop: 'auto',
}}
2024-02-08 07:01:40 +00:00
>
Add
</Button>
</form>
</VStack>
)
}
2024-02-16 04:25:45 +00:00
const UploadOPMLTab = (): JSX.Element => {
2024-02-08 07:01:40 +00:00
return (
<VStack
alignment="start"
distribution="start"
css={{ height: '180px', width: '100%' }}
>
<UploadPad
description="Drag OPML file to add feeds"
accept={{
'text/csv': ['.csv'],
'application/zip': ['.zip'],
'application/pdf': ['.pdf'],
'application/epub+zip': ['.epub'],
}}
/>
</VStack>
)
}
2024-02-16 04:25:45 +00:00
const UploadPDFTab = (): JSX.Element => {
2024-02-08 07:01:40 +00:00
return (
<VStack
alignment="start"
distribution="start"
css={{ height: '180px', width: '100%' }}
>
<UploadPad
2024-02-09 05:21:59 +00:00
info={
<HStack
distribution="start"
alignment="center"
css={{ gap: '5px', whiteSpace: 'pre-line' }}
>
<Info size={14} color="#007AFF" />
PDFs have a maximum size of 8MB.{' '}
</HStack>
}
2024-02-08 07:01:40 +00:00
description="Drag PDFs here to add to your library"
accept={{
'application/pdf': ['.pdf'],
}}
/>
</VStack>
)
}
const UploadImportTab = (props: AddLinkModalProps): JSX.Element => {
return (
<VStack
alignment="start"
distribution="start"
css={{ height: '180px', width: '100%' }}
>
<UploadPad
2024-02-09 05:21:59 +00:00
info={
<HStack
distribution="start"
alignment="center"
css={{ gap: '5px', whiteSpace: 'pre-line' }}
>
<Info size={14} color="#007AFF" />
Imports must be in a supported format.{' '}
<a
2025-09-24 10:37:39 +00:00
href="https://docs.omnivore.work/using/importing.html"
2024-02-09 05:21:59 +00:00
target="_blank"
rel="noreferrer"
style={{ color: '#007AFF' }}
>
Read more
</a>
</HStack>
}
2024-02-08 07:01:40 +00:00
description="Drop import files here"
accept={{
'text/csv': ['.csv'],
'application/zip': ['.zip'],
}}
/>
</VStack>
)
}
const DragnDropContainer = styled('div', {
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: '1',
alignSelf: 'center',
left: 0,
flexDirection: 'column',
})
const DragnDropStyle = styled('div', {
border: '1px solid $grayBorder',
borderRadius: '5px',
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
color: '$thTextSubtle2',
padding: '10px',
})
const DragnDropIndicator = styled('div', {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
width: '100%',
height: '100%',
borderRadius: '5px',
})
const ProgressIndicator = styled(Progress.Indicator, {
backgroundColor: '$omnivoreCtaYellow',
width: '100%',
height: '100%',
})
const ProgressRoot = styled(Progress.Root, {
position: 'relative',
overflow: 'hidden',
background: '$omnivoreGray',
borderRadius: '99999px',
width: '100%',
height: '5px',
transform: 'translateZ(0)',
})
type UploadingFile = {
id: string
file: any
name: string
progress: number
status: 'inprogress' | 'success' | 'error'
openUrl: string | undefined
contentType: string
message?: string
}
type UploadInfo = {
uploadSignedUrl?: string
requestId?: string
message?: string
}
type UploadPadProps = {
2024-02-09 05:47:38 +00:00
info?: React.ReactNode
2024-02-08 07:01:40 +00:00
description: string
accept: Accept
}
const UploadPad = (props: UploadPadProps): JSX.Element => {
const [uploadFiles, setUploadFiles] = useState<UploadingFile[]>([])
const [inDragOperation, setInDragOperation] = useState(false)
const dropzoneRef = useRef<DropzoneRef | null>(null)
const openDialog = useCallback(
(event: React.MouseEvent) => {
if (dropzoneRef.current) {
dropzoneRef.current.open()
}
event?.preventDefault()
},
[dropzoneRef]
)
const uploadSignedUrlForFile = async (
file: UploadingFile
): Promise<UploadInfo> => {
let { contentType } = file
if (
contentType == 'application/vnd.ms-excel' &&
file.name.endsWith('.csv')
) {
contentType = 'text/csv'
}
switch (contentType) {
case 'text/csv': {
let urlCount = 0
try {
const csvData = await validateCsvFile(file.file)
urlCount = csvData.data.length
if (urlCount > 5000) {
return {
message:
'Due to an increase in traffic we are limiting CSV imports to 5000 items.',
}
}
if (csvData.inValidData.length > 0) {
return {
message: csvData.inValidData[0].message,
}
}
if (urlCount === 0) {
return {
message: 'No URLs found in CSV file.',
}
}
} catch (error) {
return {
message: 'Invalid CSV file.',
}
}
try {
const result = await uploadImportFileRequestMutation(
UploadImportFileType.URL_LIST,
contentType
)
return {
uploadSignedUrl: result?.uploadSignedUrl,
message: `Importing ${urlCount} URLs`,
}
} catch (error) {
console.log('caught error', error)
if (error == 'UPLOAD_DAILY_LIMIT_EXCEEDED') {
return {
message: 'You have exceeded your maximum daily upload limit.',
}
}
}
}
case 'application/zip': {
const result = await uploadImportFileRequestMutation(
UploadImportFileType.MATTER,
contentType
)
return {
uploadSignedUrl: result?.uploadSignedUrl,
}
}
case 'application/pdf':
case 'application/epub+zip': {
const request = await uploadFileRequestMutation({
// This will tell the backend not to save the URL
// and give it the local filename as the title.
url: `file://local/${file.id}/${file.file.path}`,
contentType: contentType,
createPageEntry: true,
})
return {
uploadSignedUrl: request?.uploadSignedUrl,
requestId: request?.createdPageId,
}
}
}
return {
message: `Invalid content type: ${contentType}`,
}
}
const handleAcceptedFiles = useCallback(
(acceptedFiles: any, event: DropEvent) => {
setInDragOperation(false)
const addedFiles = acceptedFiles.map(
(file: { name: any; type: string }) => {
return {
id: uuidv4(),
file: file,
name: file.name,
progress: 0,
status: 'inprogress',
contentType: file.type,
}
}
)
const allFiles = [...uploadFiles, ...addedFiles]
setUploadFiles(allFiles)
;(async () => {
for (const file of addedFiles) {
try {
const uploadInfo = await uploadSignedUrlForFile(file)
if (!uploadInfo.uploadSignedUrl) {
const message = uploadInfo.message || 'No upload URL available'
showErrorToast(message, { duration: 10000 })
2024-02-08 07:01:40 +00:00
file.status = 'error'
setUploadFiles([...allFiles])
return
2024-02-08 07:01:40 +00:00
}
const uploadResult = await axios.request({
method: 'PUT',
url: uploadInfo.uploadSignedUrl,
data: file.file,
withCredentials: false,
headers: {
'Content-Type': file.file.type,
Improving Self-Hosting and Removing 3rd Party dependencies. (#4513) * fix: Library Header layout shift * Bump Github Actions versions. * Self-Hosting Changes * Fix Minio Environment Variable * Just make pdfs successful, due to lack of PDFHandler * Fix issue where flag was set wrong * Added an NGINX Example file * Add some documentation for self-hosting via Docker Compose * Make some adjustments to Puppeteer due to failing sites. * adjust timings * Add start of Mail Service * Fix Docker Files * More email service stuff * Add Guide to use Zapier for Email-Importing. * Ensure that if no env is provided it uses the old email settings * Add some instructions for self-hosted email * Add SNS Endpoints for Mail Watcher * Add steps and functionality for using SES and SNS for email * Uncomment a few jobs. * Added option for Firefox for parser. Was having issues with Chromium on Docker. * Add missing space. Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> * Fix some wording on the Guide * update browser extension to handle self-hosted instances * add slight documentation to options page * Fix MV * Do raw handlers for Medium * Fix images in Medium * Update self-hosting/GUIDE.md Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update Guide with other variables * Add The Verge to JS-less handlers * Update regex and image-proxy * Update self-hosting/nginx/nginx.conf Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Update regex and image-proxy * Update self-hosting/docker-compose/docker-compose.yml Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> * Fix Minio for Export * Merge to main * Update GUIDE with newer NGINX * Update nginx config to include api/save route * Enable Native PDF View for PDFS * Enable Native PDF View for PDFS * feat:lover packages test * feat:working build * feat:alpine build * docs:api dockerfile docs * Write a PDF.js wrapper to replace pspdfkit * Revert changes for replication, set settings to have default mode * build folder got removed due to gitignore on pdf * Add Box shadow to pdf pages * Add Toggle for Progress in PDFS, enabled native viewer toggle * Update node version to LTS * Update node version to LTS * Fix Linting issues * Fix Linting issues * Make env variable nullable * Add touchend listener for mobile * Make changes to PDF for mobile * fix(android): change serverUrl to selfhosted first * feat:2 stage alpine content fetch * feat:separated start script * fix:changed to node 22 * Add back youtube functionality and add guide * trigger build * Fix cache issue on YouTube * Allow empty AWS_S3_ENDPOINT * Allow empty AWS_S3_ENDPOINT * Add GCHR for all images * Add GCHR For self hosting. * Add GCHR For self hosting. * Test prebuilt. * Test prebuilt * Test prebuilt... * Fix web image * Remove Web Image (For now) * Move docker-compose to images * Move docker-compose files to correct locations * Remove the need for ARGS * Update packages, and Typescript versions * Fix * Fix issues with build on Web * Correct push * Fix Linting issues * Fix Trace import * Add missing types * Fix Tasks * Add information into guide about self-build * Fix issues with PDF Viewer --------- Co-authored-by: keumky2 <keumky2@woowahan.com> Co-authored-by: William Theaker <wtheaker@nvidia.com> Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com> Co-authored-by: David Adams <david@dadams2.com> Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com> Co-authored-by: m1xxos <66390094+m1xxos@users.noreply.github.com> Co-authored-by: Adil <mr.adil777@gmail.com>
2025-01-27 12:33:16 +00:00
'origin': 'http://localhost:3000'
},
onUploadProgress: (p) => {
if (!p.total) {
console.warn('No total available for upload progress')
return
}
const progress = (p.loaded / p.total) * 100
file.progress = progress
setUploadFiles([...allFiles])
},
})
file.progress = 100
file.status = 'success'
file.openUrl = uploadInfo.requestId
? `/article/sr/${uploadInfo.requestId}`
: undefined
file.message = uploadInfo.message
setUploadFiles([...allFiles])
} catch (error) {
file.status = 'error'
setUploadFiles([...allFiles])
2024-02-08 07:01:40 +00:00
}
}
})()
2024-02-08 07:01:40 +00:00
},
[uploadFiles]
)
return (
2024-02-09 05:21:59 +00:00
<VStack
distribution="start"
css={{ gap: '10px', width: '100%', height: '100%' }}
>
{props.info && (
<HStack
distribution="start"
alignment="start"
css={{
width: '100%',
bg: '#007AFF10',
p: '5px',
pl: '10px',
fontSize: '12px',
fontFamily: '$inter',
textAlign: 'center',
color: '$ctaBlue',
borderRadius: '5px',
}}
>
{props.info}
</HStack>
)}
2024-02-08 07:01:40 +00:00
<Dropzone
ref={dropzoneRef}
onDragEnter={() => {
setInDragOperation(true)
}}
onDragLeave={() => {
setInDragOperation(false)
}}
onDropAccepted={handleAcceptedFiles}
onDropRejected={(fileRejections: FileRejection[], event: DropEvent) => {
console.log('onDropRejected: ', fileRejections, event)
alert('You can only upload PDF files to your Omnivore Library.')
setInDragOperation(false)
fix(): Add network timeout to all yarn installs Bump image-size from 1.2.0 to 1.2.1 (#4567) Bumps [image-size](https://github.com/image-size/image-size) from 1.2.0 to 1.2.1. - [Release notes](https://github.com/image-size/image-size/releases) - [Commits](https://github.com/image-size/image-size/compare/v1.2.0...v1.2.1) --- updated-dependencies: - dependency-name: image-size dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> fix(): Add network timeout to all yarn installs fix(): remove node-buffer Bump brace-expansion from 1.1.11 to 1.1.12 in /pkg/admin (#4593) Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.12. - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 1.1.12 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump @babel/runtime-corejs3 from 7.26.0 to 7.28.2 (#4592) Bumps [@babel/runtime-corejs3](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs3) from 7.26.0 to 7.28.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.2/packages/babel-runtime-corejs3) --- updated-dependencies: - dependency-name: "@babel/runtime-corejs3" dependency-version: 7.28.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump next from 13.5.8 to 14.2.30 (#4591) Bumps [next](https://github.com/vercel/next.js) from 13.5.8 to 14.2.30. - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](https://github.com/vercel/next.js/compare/v13.5.8...v14.2.30) --- updated-dependencies: - dependency-name: next dependency-version: 14.2.30 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump axios from 0.27.2 to 0.30.0 (#4590) Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 0.30.0. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v0.30.0/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v0.27.2...v0.30.0) --- updated-dependencies: - dependency-name: axios dependency-version: 0.30.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump @babel/runtime from 7.14.6 to 7.28.2 in /pkg/admin (#4589) Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.14.6 to 7.28.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.2/packages/babel-runtime) --- updated-dependencies: - dependency-name: "@babel/runtime" dependency-version: 7.28.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump @radix-ui/react-separator from 0.1.4 to 1.1.6 (#4579) Bumps [@radix-ui/react-separator](https://github.com/radix-ui/primitives) from 0.1.4 to 1.1.6. - [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md) - [Commits](https://github.com/radix-ui/primitives/commits) --- updated-dependencies: - dependency-name: "@radix-ui/react-separator" dependency-version: 1.1.6 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump http-proxy-middleware from 2.0.7 to 2.0.9 (#4574) Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.7 to 2.0.9. - [Release notes](https://github.com/chimurai/http-proxy-middleware/releases) - [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.9/CHANGELOG.md) - [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.7...v2.0.9) --- updated-dependencies: - dependency-name: http-proxy-middleware dependency-version: 2.0.9 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump @babel/helpers from 7.14.6 to 7.28.2 in /pkg/admin (#4594) Bumps [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers) from 7.14.6 to 7.28.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.2/packages/babel-helpers) --- updated-dependencies: - dependency-name: "@babel/helpers" dependency-version: 7.28.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump pg and @types/pg (#4547) Bumps [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) and [@types/pg](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/pg). These dependencies needed to be updated together. Updates `pg` from 8.13.1 to 8.13.3 - [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md) - [Commits](https://github.com/brianc/node-postgres/commits/pg@8.13.3/packages/pg) Updates `@types/pg` from 8.11.10 to 8.11.11 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/pg) --- updated-dependencies: - dependency-name: pg dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: "@types/pg" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump @graphql-tools/utils from 9.2.1 to 10.8.6 (#4560) Bumps [@graphql-tools/utils](https://github.com/ardatan/graphql-tools/tree/HEAD/packages/utils) from 9.2.1 to 10.8.6. - [Release notes](https://github.com/ardatan/graphql-tools/releases) - [Changelog](https://github.com/ardatan/graphql-tools/blob/master/packages/utils/CHANGELOG.md) - [Commits](https://github.com/ardatan/graphql-tools/commits/@graphql-tools/utils@10.8.6/packages/utils) --- updated-dependencies: - dependency-name: "@graphql-tools/utils" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> chore(): update versions chore(): remove unused workload fix(): kbar dependency fix(): kbar dependency chore(): fix packages fix(): dependencies fix(): dependencies fix(): dependencies fix(): dependencies api fix(): dependencies api fix(): dependencies api chore(): fix order of github fix(): fix tsconfig for liqe
2025-07-29 10:11:08 +00:00
if (event instanceof MouseEvent) {
event.preventDefault()
}
2024-02-08 07:01:40 +00:00
}}
preventDropOnDocument={true}
noClick={true}
accept={props.accept}
>
{({ getRootProps, getInputProps, acceptedFiles, fileRejections }) => (
<div
{...getRootProps({ className: 'dropzone' })}
2024-08-15 04:48:10 +00:00
style={{ width: '100%', height: '75%' }}
2024-02-08 07:01:40 +00:00
>
<DragnDropContainer>
<DragnDropStyle>
<DragnDropIndicator
css={{
border: inDragOperation ? '2px dashed blue' : 'unset',
}}
>
<VStack
alignment="center"
css={{ gap: '20px', height: '100%' }}
>
<File
size={40}
2024-02-09 05:21:59 +00:00
color={theme.colors.tabTextUnselected.toString()}
2024-02-08 07:01:40 +00:00
/>
{inDragOperation ? (
<>
<Box
css={{
p: '0px',
2024-02-09 05:21:59 +00:00
fontSize: '12px',
fontFamily: '$inter',
textAlign: 'center',
color: '$tabTextUnselected',
2024-02-08 07:01:40 +00:00
}}
>
Drop to upload your file
</Box>
</>
) : (
<>
{(!uploadFiles || uploadFiles.length == 0) && (
<Box
css={{
fontSize: '12px',
fontFamily: '$inter',
textAlign: 'center',
color: '$tabTextUnselected',
}}
>
{props.description}
<br /> or{' '}
<a href="" onClick={openDialog}>
choose your files
</a>
</Box>
)}
2024-02-08 07:01:40 +00:00
</>
)}
</VStack>
</DragnDropIndicator>
</DragnDropStyle>
<VStack
css={{
width: '100%',
mt: '10px',
gap: '5px',
overflowY: 'auto',
}}
>
2024-02-08 07:01:40 +00:00
{uploadFiles.map((file) => {
return (
<HStack
key={file.id}
css={{
width: '100%',
height: '54px',
border: '1px dashed $grayBorder',
borderRadius: '5px',
padding: '15px',
gap: '10px',
color: '$thTextContrast',
overflow: 'hidden',
2024-02-08 07:01:40 +00:00
}}
alignment="center"
distribution="start"
>
<Box
css={{
width: '280px',
maxLines: '1',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
maxWidth: '200px',
overflow: 'hidden',
fontSize: '14px',
fontWeight: 'bold',
}}
>
{file.name}
</Box>
{file.status != 'inprogress' ? (
<HStack
alignment="center"
css={{ marginLeft: 'auto', fontSize: '14px' }}
>
{file.status == 'success' && file.openUrl && (
<a href={file.openUrl}>Read Now</a>
)}
{file.status == 'success' && !file.openUrl && (
<span>
{file.message || 'Your import has started'}
</span>
)}
{file.status == 'error' && (
<SpanBox css={{ color: 'red' }}>
Error Uploading
</SpanBox>
)}
</HStack>
) : (
<ProgressRoot value={file.progress} max={100}>
<ProgressIndicator
style={{
transform: `translateX(-${100 - file.progress}%)`,
}}
/>{' '}
</ProgressRoot>
)}
</HStack>
)
})}
</VStack>
</DragnDropContainer>
<input {...getInputProps()} />
</div>
)}
</Dropzone>
</VStack>
)
}
type TabBarProps = {
selectedTab: string
setSelectedTab: (selected: TabName) => void
onOpenChange: (open: boolean) => void
}
const TabBar = (props: TabBarProps) => {
return (
<HStack
distribution="between"
alignment="center"
css={{ width: '100%', gap: '4px' }}
>
<Button
style={props.selectedTab == 'link' ? 'tabSelected' : 'tab'}
onClick={(event) => {
props.setSelectedTab('link')
event.preventDefault()
}}
>
Link
</Button>
<Button
style={props.selectedTab == 'pdf' ? 'tabSelected' : 'tab'}
onClick={(event) => {
props.setSelectedTab('pdf')
event.preventDefault()
}}
>
PDF
</Button>
<Button
style={props.selectedTab == 'feed' ? 'tabSelected' : 'tab'}
onClick={(event) => {
props.setSelectedTab('feed')
event.preventDefault()
}}
>
Feed
</Button>
{/* <Button
style={props.selectedTab == 'opml' ? 'tabSelected' : 'tab'}
onClick={(event) => {
props.setSelectedTab('opml')
event.preventDefault()
}}
>
OPML
</Button> */}
<Button
style={props.selectedTab == 'import' ? 'tabSelected' : 'tab'}
onClick={(event) => {
props.setSelectedTab('import')
event.preventDefault()
}}
>
Import
</Button>
<SpanBox css={{ ml: 'auto' }}>
<CloseButton close={() => props.onOpenChange(false)} />
</SpanBox>
</HStack>
2022-02-11 17:24:33 +00:00
)
}