add image output tab in file manager
This commit is contained in:
parent
a7382807be
commit
f1c7f6dc99
@ -172,9 +172,9 @@ export async function postInteractiveSeg(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getMediaFile(filename: string) {
|
export async function getMediaFile(tab: string, filename: string) {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_ENDPOINT}/media/${encodeURIComponent(filename)}`,
|
`${API_ENDPOINT}/media/${tab}/${encodeURIComponent(filename)}`,
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
}
|
}
|
||||||
@ -188,8 +188,8 @@ export async function getMediaFile(filename: string) {
|
|||||||
throw new Error(errMsg)
|
throw new Error(errMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getMedias() {
|
export async function getMedias(tab: string) {
|
||||||
const res = await fetch(`${API_ENDPOINT}/medias`, {
|
const res = await fetch(`${API_ENDPOINT}/medias/${tab}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
})
|
})
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sort-btn-inactive {
|
.sort-btn-inactive {
|
||||||
@ -99,3 +99,66 @@
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reset */
|
||||||
|
button,
|
||||||
|
fieldset,
|
||||||
|
input {
|
||||||
|
all: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TabsRoot {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
background-color: var(--page-bg);
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TabsList {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 6px;
|
||||||
|
justify-content: flex-start;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 12px;
|
||||||
|
background-color: var(--page-bg);
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TabsTrigger {
|
||||||
|
font-family: inherit;
|
||||||
|
background-color: white;
|
||||||
|
padding: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--modal-text-color);
|
||||||
|
user-select: none;
|
||||||
|
background-color: var(--page-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
.TabsTrigger:hover {
|
||||||
|
background-color: var(--tabs-active-color);
|
||||||
|
}
|
||||||
|
.TabsTrigger[data-state='active'] {
|
||||||
|
background-color: var(--tabs-active-color);
|
||||||
|
}
|
||||||
|
.TabsTrigger:focus {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TabsContent {
|
||||||
|
background-color: white;
|
||||||
|
outline: none;
|
||||||
|
background-color: var(--page-bg);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TabsContent[data-state='active'] {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import React, {
|
|||||||
FormEvent,
|
FormEvent,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import * as Tabs from '@radix-ui/react-tabs'
|
||||||
import { useSetRecoilState } from 'recoil'
|
import { useSetRecoilState } from 'recoil'
|
||||||
import PhotoAlbum from 'react-photo-album'
|
import PhotoAlbum from 'react-photo-album'
|
||||||
import { BarsArrowDownIcon, BarsArrowUpIcon } from '@heroicons/react/24/outline'
|
import { BarsArrowDownIcon, BarsArrowUpIcon } from '@heroicons/react/24/outline'
|
||||||
@ -50,6 +51,9 @@ enum SortBy {
|
|||||||
const SORT_BY_NAME = 'Name'
|
const SORT_BY_NAME = 'Name'
|
||||||
const SORT_BY_CREATED_TIME = 'Created time'
|
const SORT_BY_CREATED_TIME = 'Created time'
|
||||||
|
|
||||||
|
const IMAGE_TAB = 'image'
|
||||||
|
const OUTPUT_TAB = 'output'
|
||||||
|
|
||||||
const SortByMap = {
|
const SortByMap = {
|
||||||
[SortBy.NAME]: SORT_BY_NAME,
|
[SortBy.NAME]: SORT_BY_NAME,
|
||||||
[SortBy.CTIME]: SORT_BY_CREATED_TIME,
|
[SortBy.CTIME]: SORT_BY_CREATED_TIME,
|
||||||
@ -58,7 +62,7 @@ const SortByMap = {
|
|||||||
interface Props {
|
interface Props {
|
||||||
show: boolean
|
show: boolean
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
onPhotoClick(filename: string): void
|
onPhotoClick(tab: string, filename: string): void
|
||||||
photoWidth: number
|
photoWidth: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +77,7 @@ export default function FileManager(props: Props) {
|
|||||||
const ref = useRef(null)
|
const ref = useRef(null)
|
||||||
const [searchText, setSearchText] = useState('')
|
const [searchText, setSearchText] = useState('')
|
||||||
const [debouncedSearchText, setDebouncedSearchText] = useState('')
|
const [debouncedSearchText, setDebouncedSearchText] = useState('')
|
||||||
|
const [tab, setTab] = useState(IMAGE_TAB)
|
||||||
|
|
||||||
const [, cancel] = useDebounce(
|
const [, cancel] = useDebounce(
|
||||||
() => {
|
() => {
|
||||||
@ -102,14 +107,10 @@ export default function FileManager(props: Props) {
|
|||||||
[show, closeScrollTop]
|
[show, closeScrollTop]
|
||||||
)
|
)
|
||||||
|
|
||||||
const onClick = ({ index }: { index: number }) => {
|
|
||||||
onPhotoClick(filenames[index].name)
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const newFilenames = await getMedias()
|
const newFilenames = await getMedias(tab)
|
||||||
setFileNames(newFilenames)
|
setFileNames(newFilenames)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
setToastState({
|
setToastState({
|
||||||
@ -123,7 +124,7 @@ export default function FileManager(props: Props) {
|
|||||||
if (show) {
|
if (show) {
|
||||||
fetchData()
|
fetchData()
|
||||||
}
|
}
|
||||||
}, [show, setToastState])
|
}, [show, setToastState, tab])
|
||||||
|
|
||||||
const onScroll = (event: SyntheticEvent) => {
|
const onScroll = (event: SyntheticEvent) => {
|
||||||
setScrollTop(event.currentTarget.scrollTop)
|
setScrollTop(event.currentTarget.scrollTop)
|
||||||
@ -141,19 +142,30 @@ export default function FileManager(props: Props) {
|
|||||||
const results: IndexSearchResult = await index.searchAsync(
|
const results: IndexSearchResult = await index.searchAsync(
|
||||||
debouncedSearchText
|
debouncedSearchText
|
||||||
)
|
)
|
||||||
return results.map((id: Id) => filenames[id as number])
|
return _.orderBy(
|
||||||
}, [filenames, debouncedSearchText])
|
results.map((id: Id) => filenames[id as number]),
|
||||||
|
sortBy,
|
||||||
|
sortOrder
|
||||||
|
)
|
||||||
|
}, [filenames, debouncedSearchText, sortBy, sortOrder])
|
||||||
|
|
||||||
const photos: Photo[] = useMemo(() => {
|
const photos: Photo[] = useMemo(() => {
|
||||||
return _.orderBy(filteredFilenames, sortBy, sortOrder).map(
|
if (!filteredFilenames) {
|
||||||
(filename: Filename) => {
|
return []
|
||||||
const width = photoWidth
|
}
|
||||||
const height = filename.height * (width / filename.width)
|
return filteredFilenames.map((filename: Filename) => {
|
||||||
const src = `/media_thumbnail/${filename.name}?width=${width}&height=${height}`
|
const width = photoWidth
|
||||||
return { src, height, width }
|
const height = filename.height * (width / filename.width)
|
||||||
}
|
const src = `/media_thumbnail/${tab}/${filename.name}?width=${width}&height=${height}`
|
||||||
)
|
return { src, height, width }
|
||||||
}, [filteredFilenames, photoWidth, sortBy, sortOrder])
|
})
|
||||||
|
}, [filteredFilenames, photoWidth, tab])
|
||||||
|
|
||||||
|
const onClick = ({ index }: { index: number }) => {
|
||||||
|
if (filteredFilenames) {
|
||||||
|
onPhotoClick(tab, filteredFilenames[index].name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -162,62 +174,78 @@ export default function FileManager(props: Props) {
|
|||||||
className="file-manager-modal"
|
className="file-manager-modal"
|
||||||
show={show}
|
show={show}
|
||||||
>
|
>
|
||||||
<Flex style={{ justifyContent: 'end', gap: 8 }}>
|
<Flex style={{ justifyContent: 'space-between', gap: 8 }}>
|
||||||
<Flex
|
<Tabs.Root
|
||||||
style={{
|
className="TabsRoot"
|
||||||
position: 'relative',
|
defaultValue={tab}
|
||||||
justifyContent: 'start',
|
onValueChange={val => setTab(val)}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<MagnifyingGlassIcon style={{ position: 'absolute', left: 8 }} />
|
<Tabs.List className="TabsList" aria-label="Manage your account">
|
||||||
<TextInput
|
<Tabs.Trigger className="TabsTrigger" value={IMAGE_TAB}>
|
||||||
ref={ref}
|
Image Directory
|
||||||
value={searchText}
|
</Tabs.Trigger>
|
||||||
className="file-search-input"
|
<Tabs.Trigger className="TabsTrigger" value={OUTPUT_TAB}>
|
||||||
tabIndex={-1}
|
Output Directory
|
||||||
onInput={(evt: FormEvent<HTMLInputElement>) => {
|
</Tabs.Trigger>
|
||||||
evt.preventDefault()
|
</Tabs.List>
|
||||||
evt.stopPropagation()
|
</Tabs.Root>
|
||||||
const target = evt.target as HTMLInputElement
|
|
||||||
setSearchText(target.value)
|
|
||||||
}}
|
|
||||||
placeholder="Search by file name"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
<Flex style={{ gap: 8 }}>
|
<Flex style={{ gap: 8 }}>
|
||||||
<Selector
|
<Flex
|
||||||
width={130}
|
style={{
|
||||||
value={SortByMap[sortBy]}
|
position: 'relative',
|
||||||
options={Object.values(SortByMap)}
|
justifyContent: 'start',
|
||||||
onChange={val => {
|
}}
|
||||||
if (val === SORT_BY_CREATED_TIME) {
|
>
|
||||||
setSortBy(SortBy.CTIME)
|
<MagnifyingGlassIcon style={{ position: 'absolute', left: 8 }} />
|
||||||
} else {
|
<TextInput
|
||||||
setSortBy(SortBy.NAME)
|
ref={ref}
|
||||||
|
value={searchText}
|
||||||
|
className="file-search-input"
|
||||||
|
tabIndex={-1}
|
||||||
|
onInput={(evt: FormEvent<HTMLInputElement>) => {
|
||||||
|
evt.preventDefault()
|
||||||
|
evt.stopPropagation()
|
||||||
|
const target = evt.target as HTMLInputElement
|
||||||
|
setSearchText(target.value)
|
||||||
|
}}
|
||||||
|
placeholder="Search by file name"
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
<Flex style={{ gap: 8 }}>
|
||||||
|
<Selector
|
||||||
|
width={130}
|
||||||
|
value={SortByMap[sortBy]}
|
||||||
|
options={Object.values(SortByMap)}
|
||||||
|
onChange={val => {
|
||||||
|
if (val === SORT_BY_CREATED_TIME) {
|
||||||
|
setSortBy(SortBy.CTIME)
|
||||||
|
} else {
|
||||||
|
setSortBy(SortBy.NAME)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
chevronDirection="down"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
icon={<BarsArrowDownIcon />}
|
||||||
|
toolTip="Descending order"
|
||||||
|
onClick={() => {
|
||||||
|
setSortOrder(SortOrder.DESCENDING)
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
sortOrder !== SortOrder.DESCENDING ? 'sort-btn-inactive' : ''
|
||||||
}
|
}
|
||||||
}}
|
/>
|
||||||
chevronDirection="down"
|
<Button
|
||||||
/>
|
icon={<BarsArrowUpIcon />}
|
||||||
<Button
|
toolTip="Ascending order"
|
||||||
icon={<BarsArrowDownIcon />}
|
onClick={() => {
|
||||||
toolTip="Descending order"
|
setSortOrder(SortOrder.ASCENDING)
|
||||||
onClick={() => {
|
}}
|
||||||
setSortOrder(SortOrder.DESCENDING)
|
className={
|
||||||
}}
|
sortOrder !== SortOrder.ASCENDING ? 'sort-btn-inactive' : ''
|
||||||
className={
|
}
|
||||||
sortOrder !== SortOrder.DESCENDING ? 'sort-btn-inactive' : ''
|
/>
|
||||||
}
|
</Flex>
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
icon={<BarsArrowUpIcon />}
|
|
||||||
toolTip="Ascending order"
|
|
||||||
onClick={() => {
|
|
||||||
setSortOrder(SortOrder.ASCENDING)
|
|
||||||
}}
|
|
||||||
className={
|
|
||||||
sortOrder !== SortOrder.ASCENDING ? 'sort-btn-inactive' : ''
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<ScrollArea.Root className="ScrollAreaRoot">
|
<ScrollArea.Root className="ScrollAreaRoot">
|
||||||
|
@ -18,73 +18,6 @@
|
|||||||
animation: slideDown 0.2s ease-out;
|
animation: slideDown 0.2s ease-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset */
|
|
||||||
button,
|
|
||||||
fieldset,
|
|
||||||
input {
|
|
||||||
all: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.TabsRoot {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 16px;
|
|
||||||
width: 100%;
|
|
||||||
background-color: var(--page-bg);
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.TabsList {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 6px;
|
|
||||||
justify-content: flex-start;
|
|
||||||
border-right: 1px solid var(--border-color);
|
|
||||||
background-color: var(--page-bg);
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.TabsTrigger {
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: white;
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
padding-right: 40px;
|
|
||||||
padding-left: 8px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 1;
|
|
||||||
color: var(--modal-text-color);
|
|
||||||
user-select: none;
|
|
||||||
background-color: var(--page-bg);
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
.TabsTrigger:hover {
|
|
||||||
background-color: var(--tabs-active-color);
|
|
||||||
}
|
|
||||||
.TabsTrigger[data-state='active'] {
|
|
||||||
background-color: var(--tabs-active-color);
|
|
||||||
}
|
|
||||||
.TabsTrigger:focus {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.TabsContent {
|
|
||||||
background-color: white;
|
|
||||||
outline: none;
|
|
||||||
background-color: var(--page-bg);
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.TabsContent[data-state='active'] {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-path-block {
|
.folder-path-block {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -52,7 +52,7 @@ const SidePanel = () => {
|
|||||||
className="btn-primary side-panel-trigger"
|
className="btn-primary side-panel-trigger"
|
||||||
onClick={() => toggleOpen()}
|
onClick={() => toggleOpen()}
|
||||||
>
|
>
|
||||||
Configurations
|
Config
|
||||||
</PopoverPrimitive.Trigger>
|
</PopoverPrimitive.Trigger>
|
||||||
<PopoverPrimitive.Portal>
|
<PopoverPrimitive.Portal>
|
||||||
<PopoverPrimitive.Content className="side-panel-content">
|
<PopoverPrimitive.Content className="side-panel-content">
|
||||||
|
@ -104,8 +104,8 @@ const Workspace = () => {
|
|||||||
onClose={() => {
|
onClose={() => {
|
||||||
setShowFileManager(false)
|
setShowFileManager(false)
|
||||||
}}
|
}}
|
||||||
onPhotoClick={async (filename: string) => {
|
onPhotoClick={async (tab: string, filename: string) => {
|
||||||
const newFile = await getMediaFile(filename)
|
const newFile = await getMediaFile(tab, filename)
|
||||||
setFile(newFile)
|
setFile(newFile)
|
||||||
setShowFileManager(false)
|
setShowFileManager(false)
|
||||||
}}
|
}}
|
||||||
|
@ -82,10 +82,19 @@ class FileManager:
|
|||||||
@property
|
@property
|
||||||
@cached(cache=TTLCache(maxsize=1024, ttl=30))
|
@cached(cache=TTLCache(maxsize=1024, ttl=30))
|
||||||
def media_names(self):
|
def media_names(self):
|
||||||
names = sorted([it.name for it in glob_img(self.root_directory)])
|
return self._media_names(self.root_directory)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@cached(cache=TTLCache(maxsize=1024, ttl=30))
|
||||||
|
def output_media_names(self):
|
||||||
|
return self._media_names(self.output_dir)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _media_names(directory: Path):
|
||||||
|
names = sorted([it.name for it in glob_img(directory)])
|
||||||
res = []
|
res = []
|
||||||
for name in names:
|
for name in names:
|
||||||
path = os.path.join(self.root_directory, name)
|
path = os.path.join(directory, name)
|
||||||
img = Image.open(path)
|
img = Image.open(path)
|
||||||
res.append({"name": name, "height": img.height, "width": img.width, "ctime": os.path.getctime(path)})
|
res.append({"name": name, "height": img.height, "width": img.width, "ctime": os.path.getctime(path)})
|
||||||
return res
|
return res
|
||||||
@ -94,14 +103,14 @@ class FileManager:
|
|||||||
def thumbnail_url(self):
|
def thumbnail_url(self):
|
||||||
return self.app.config["THUMBNAIL_MEDIA_THUMBNAIL_URL"]
|
return self.app.config["THUMBNAIL_MEDIA_THUMBNAIL_URL"]
|
||||||
|
|
||||||
def get_thumbnail(self, original_filename, width, height, **options):
|
def get_thumbnail(self, directory: Path, original_filename: str, width, height, **options):
|
||||||
storage = FilesystemStorageBackend(self.app)
|
storage = FilesystemStorageBackend(self.app)
|
||||||
crop = options.get("crop", "fit")
|
crop = options.get("crop", "fit")
|
||||||
background = options.get("background")
|
background = options.get("background")
|
||||||
quality = options.get("quality", 90)
|
quality = options.get("quality", 90)
|
||||||
|
|
||||||
original_path, original_filename = os.path.split(original_filename)
|
original_path, original_filename = os.path.split(original_filename)
|
||||||
original_filepath = os.path.join(self.root_directory, original_path, original_filename)
|
original_filepath = os.path.join(directory, original_path, original_filename)
|
||||||
image = Image.open(BytesIO(storage.read(original_filepath)))
|
image = Image.open(BytesIO(storage.read(original_filepath)))
|
||||||
|
|
||||||
# keep ratio resize
|
# keep ratio resize
|
||||||
|
@ -102,19 +102,23 @@ def save_image():
|
|||||||
return 'ok', 200
|
return 'ok', 200
|
||||||
|
|
||||||
|
|
||||||
@app.route("/medias")
|
@app.route("/medias/<tab>")
|
||||||
def medias():
|
def medias(tab):
|
||||||
# all images in input folder
|
if tab == 'image':
|
||||||
return jsonify(thumb.media_names), 200
|
# all images in input folder
|
||||||
|
return jsonify(thumb.media_names), 200
|
||||||
|
return jsonify(thumb.output_media_names), 200
|
||||||
|
|
||||||
|
|
||||||
@app.route('/media/<filename>')
|
@app.route('/media/<tab>/<filename>')
|
||||||
def media_file(filename):
|
def media_file(tab, filename):
|
||||||
return send_from_directory(app.config['THUMBNAIL_MEDIA_ROOT'], filename)
|
if tab == 'image':
|
||||||
|
return send_from_directory(thumb.root_directory, filename)
|
||||||
|
return send_from_directory(thumb.output_dir, filename)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/media_thumbnail/<filename>')
|
@app.route('/media_thumbnail/<tab>/<filename>')
|
||||||
def media_thumbnail_file(filename):
|
def media_thumbnail_file(tab, filename):
|
||||||
args = request.args
|
args = request.args
|
||||||
width = args.get('width')
|
width = args.get('width')
|
||||||
height = args.get('height')
|
height = args.get('height')
|
||||||
@ -125,7 +129,10 @@ def media_thumbnail_file(filename):
|
|||||||
if height:
|
if height:
|
||||||
height = int(float(height))
|
height = int(float(height))
|
||||||
|
|
||||||
thumb_filename, (width, height) = thumb.get_thumbnail(filename, width, height)
|
directory = thumb.root_directory
|
||||||
|
if tab == 'output':
|
||||||
|
directory = thumb.output_dir
|
||||||
|
thumb_filename, (width, height) = thumb.get_thumbnail(directory, filename, width, height)
|
||||||
thumb_filepath = f"{app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT']}{thumb_filename}"
|
thumb_filepath = f"{app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT']}{thumb_filename}"
|
||||||
|
|
||||||
response = make_response(send_file(thumb_filepath))
|
response = make_response(send_file(thumb_filepath))
|
||||||
@ -350,7 +357,7 @@ def main(args):
|
|||||||
|
|
||||||
if os.path.isdir(args.input):
|
if os.path.isdir(args.input):
|
||||||
app.config["THUMBNAIL_MEDIA_ROOT"] = args.input
|
app.config["THUMBNAIL_MEDIA_ROOT"] = args.input
|
||||||
app.config["THUMBNAIL_MEDIA_THUMBNAIL_ROOT"] = os.path.join(args.output_dir, 'thumbnails')
|
app.config["THUMBNAIL_MEDIA_THUMBNAIL_ROOT"] = os.path.join(args.output_dir, 'lama_cleaner_thumbnails')
|
||||||
is_enable_file_manager = True
|
is_enable_file_manager = True
|
||||||
thumb.output_dir = Path(args.output_dir)
|
thumb.output_dir = Path(args.output_dir)
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user