Skip to content

Commit

Permalink
fix: lint error
Browse files Browse the repository at this point in the history
  • Loading branch information
xuzuodong committed Aug 12, 2024
1 parent 4bb151d commit a1fa936
Show file tree
Hide file tree
Showing 8 changed files with 309 additions and 306 deletions.
7 changes: 4 additions & 3 deletions web/app/components/app/create-app-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@remixicon/react'
import { useRouter } from 'next/navigation'
import { useContext, useContextSelector } from 'use-context-selector'
import AppIconPicker from '../../base/app-icon-picker'
import s from './style.module.css'
import cn from '@/utils/classnames'
import AppsContext, { useAppContext } from '@/context/app-context'
Expand All @@ -18,7 +19,6 @@ import { createApp } from '@/service/apps'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import AppIcon from '@/app/components/base/app-icon'
import AppIconPicker from "../../base/app-icon-picker"
import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { AiText, ChatBot, CuteRobote } from '@/app/components/base/icons/src/vender/solid/communication'
import { Route } from '@/app/components/base/icons/src/vender/solid/mapsAndTravel'
Expand Down Expand Up @@ -63,7 +63,8 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
return
isCreatingRef.current = true
try {
if (appIcon.type === 'image') throw new Error('unimplemented')
if (appIcon.type === 'image')
throw new Error('unimplemented')
const app = await createApp({
name,
description,
Expand All @@ -82,7 +83,7 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
}
isCreatingRef.current = false
}, [name, notify, t, appMode, appIcon.icon, appIcon.background, description, onSuccess, onClose, mutateApps, push, isCurrentWorkspaceEditor])
}, [name, notify, t, appMode, appIcon.icon, appIcon.background, appIcon.type, description, onSuccess, onClose, mutateApps, push, isCurrentWorkspaceEditor])

return (
<Modal
Expand Down
157 changes: 81 additions & 76 deletions web/app/components/base/app-icon-picker/Uploader.tsx
Original file line number Diff line number Diff line change
@@ -1,92 +1,97 @@
'use client'

import { FC, ChangeEvent, useState, useEffect, createRef } from 'react'
import Cropper, { Area } from 'react-easy-crop'
import classNames from "classnames"
import type { ChangeEvent, FC } from 'react'
import { createRef, useEffect, useState } from 'react'
import type { Area } from 'react-easy-crop'
import Cropper from 'react-easy-crop'
import classNames from 'classnames'

import { useDraggableUploader } from "./hooks"
import { ImagePlus } from "../icons/src/vender/line/images"
import { ALLOW_FILE_EXTENSIONS, ImageFile } from "@/types/app"
import { ImagePlus } from '../icons/src/vender/line/images'
import { useDraggableUploader } from './hooks'
import { ALLOW_FILE_EXTENSIONS } from '@/types/app'

interface UploaderProps {
className?: string
onImageCropped?: (tempUrl: string, croppedAreaPixels: Area, fileName: string) => void
type UploaderProps = {
className?: string
onImageCropped?: (tempUrl: string, croppedAreaPixels: Area, fileName: string) => void
}

const Uploader: FC<UploaderProps> = ({
className,
onImageCropped,
className,
onImageCropped,
}) => {
const [inputImage, setInputImage] = useState<{ file: File, url: string }>()
useEffect(() => {
return () => {
if (inputImage) URL.revokeObjectURL(inputImage.url);
}
}, [inputImage])
const [inputImage, setInputImage] = useState<{ file: File; url: string }>()
useEffect(() => {
return () => {
if (inputImage)
URL.revokeObjectURL(inputImage.url)
}
}, [inputImage])

const [crop, setCrop] = useState({ x: 0, y: 0 })
const [zoom, setZoom] = useState(1)
const [crop, setCrop] = useState({ x: 0, y: 0 })
const [zoom, setZoom] = useState(1)

const onCropComplete = async (_: Area, croppedAreaPixels: Area) => {
if (!inputImage) return
onImageCropped?.(inputImage.url, croppedAreaPixels, inputImage.file.name)
}
const onCropComplete = async (_: Area, croppedAreaPixels: Area) => {
if (!inputImage)
return
onImageCropped?.(inputImage.url, croppedAreaPixels, inputImage.file.name)
}

const handleLocalFileInput = (e: ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0]
if (file) setInputImage({ file, url: URL.createObjectURL(file) })
}
const handleLocalFileInput = (e: ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0]
if (file)
setInputImage({ file, url: URL.createObjectURL(file) })
}

const {
isDragActive,
handleDragEnter,
handleDragOver,
handleDragLeave,
handleDrop
} = useDraggableUploader((file: File) => setInputImage({ file, url: URL.createObjectURL(file) }))
const {
isDragActive,
handleDragEnter,
handleDragOver,
handleDragLeave,
handleDrop,
} = useDraggableUploader((file: File) => setInputImage({ file, url: URL.createObjectURL(file) }))

const inputRef = createRef<HTMLInputElement>()
const inputRef = createRef<HTMLInputElement>()

return (
<div className="w-full px-3 py-1.5">
<div
className={classNames(className,
isDragActive && 'border-primary-600',
'relative aspect-square bg-gray-50 border-[1.5px] border-gray-200 border-dashed rounded-lg flex flex-col justify-center items-center text-gray-500')}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
{
!inputImage
? <>
<ImagePlus className="w-[30px] h-[30px] mb-3 pointer-events-none" />
<div className="text-sm font-medium mb-[2px]">
<span className="pointer-events-none">Drop your image here, or&nbsp;</span>
<button className="text-components-button-primary-bg" onClick={() => inputRef.current?.click()}>browse</button>
<input
ref={inputRef} type="file" className="hidden"
onClick={e => ((e.target as HTMLInputElement).value = '')}
accept={ALLOW_FILE_EXTENSIONS.map(ext => `.${ext}`).join(',')}
onChange={handleLocalFileInput}
/>
</div>
<div className="text-xs pointer-events-none">Supports PNG, JPG, JPEG, WEBP and GIF</div>
</>
: <Cropper
image={inputImage.url}
crop={crop}
zoom={zoom}
aspect={1}
onCropChange={setCrop}
onCropComplete={onCropComplete}
onZoomChange={setZoom}
/>
}
</div>
</div>
)
return (
<div className="w-full px-3 py-1.5">
<div
className={classNames(className,
isDragActive && 'border-primary-600',
'relative aspect-square bg-gray-50 border-[1.5px] border-gray-200 border-dashed rounded-lg flex flex-col justify-center items-center text-gray-500')}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
{
!inputImage
? <>
<ImagePlus className="w-[30px] h-[30px] mb-3 pointer-events-none" />
<div className="text-sm font-medium mb-[2px]">
<span className="pointer-events-none">Drop your image here, or&nbsp;</span>
<button className="text-components-button-primary-bg" onClick={() => inputRef.current?.click()}>browse</button>
<input
ref={inputRef} type="file" className="hidden"
onClick={e => ((e.target as HTMLInputElement).value = '')}
accept={ALLOW_FILE_EXTENSIONS.map(ext => `.${ext}`).join(',')}
onChange={handleLocalFileInput}
/>
</div>
<div className="text-xs pointer-events-none">Supports PNG, JPG, JPEG, WEBP and GIF</div>
</>
: <Cropper
image={inputImage.url}
crop={crop}
zoom={zoom}
aspect={1}
onCropChange={setCrop}
onCropComplete={onCropComplete}
onZoomChange={setZoom}
/>
}
</div>
</div>
)
}

export default Uploader
export default Uploader
80 changes: 40 additions & 40 deletions web/app/components/base/app-icon-picker/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
import { useCallback, useState } from "react"
import { useCallback, useState } from 'react'

export const useDraggableUploader = <T extends HTMLElement>(setImageFn: (file: File) => void) => {
const [isDragActive, setIsDragActive] = useState(false)

const handleDragEnter = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
setIsDragActive(true)
}, [])

const handleDragOver = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
}, [])

const handleDragLeave = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
setIsDragActive(false)
}, [])

const handleDrop = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
setIsDragActive(false)

const file = e.dataTransfer.files[0]

if (!file)
return

setImageFn(file)
}, [])

return {
handleDragEnter,
handleDragOver,
handleDragLeave,
handleDrop,
isDragActive,
}
const [isDragActive, setIsDragActive] = useState(false)

const handleDragEnter = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
setIsDragActive(true)
}, [])

const handleDragOver = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
}, [])

const handleDragLeave = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
setIsDragActive(false)
}, [])

const handleDrop = useCallback((e: React.DragEvent<T>) => {
e.preventDefault()
e.stopPropagation()
setIsDragActive(false)

const file = e.dataTransfer.files[0]

if (!file)
return

setImageFn(file)
}, [setImageFn])

return {
handleDragEnter,
handleDragOver,
handleDragLeave,
handleDrop,
isDragActive,
}
}
Loading

0 comments on commit a1fa936

Please sign in to comment.