Skip to content

Commit

Permalink
feat(download): add json download
Browse files Browse the repository at this point in the history
  • Loading branch information
zeindevs committed Feb 15, 2024
1 parent f8d90b8 commit ccdb874
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 81 deletions.
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"semi": false,
"singleQuote": true,
"tabWitdh": 2
"tabWitdh": 2,
"printWidth": 100
}
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Image Downloader",
"description": "A browser extension that makes downloading images from the web easier and adds useful features.",
"minimum_chrome_version": "72",
"version": "1.1.1",
"version": "1.1.2",
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunXUF5VVUuiBrJ0Fx3O8mhXzk4wTE00V2i9d1ExsH9FIcBIl2LURELZmUUGcyMoemeWI+nfyFaQFYfaii09g0Bj2dnCmvThMeGOoul22vfmOZov8BixLIJ1FwAN24bIaoGVz681jWLoEOxp5YIbtOEJ+r5nVkE9nZAdRzeuYvXvBouC90yl/xY3INq9P+ogu3VaBIUg4VXvn8zQCO6J/O4lFSMC9BiDjKmBDuYZ3pBm9pV0G1dO84/0SNheENzn8mJNOhNQGsO+OqnoD2qvjCtBElQNFqu/55JScL9AplJFWONEKk+57g4Sq4eYWjSol05I4h13FxQ0ADhSx575TuwIDAQAB",
"background": {
"presistent": true,
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "imagedl-extensions",
"private": true,
"version": "1.1.1",
"version": "1.1.2",
"description": "Image Downloader Extensions",
"main": "src/main.ts",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build:watch": "vite build --watch",
"build:zip": "node --es-module-specifier-resolution=node --no-warnings build.js",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
Expand Down
66 changes: 47 additions & 19 deletions src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type Options = {
new_file_name?: string
}

const unique = (values: any): Array<any> => [...new Set(values)];
const unique = (values: any): Array<any> => [...new Set(values)]

const normalizeSlashes = (filename: string) => filename.replace(/\\/g, '/').replace(/\/{2,}/g, '/')

Expand All @@ -29,6 +29,31 @@ const startDownload = (
_sender: chrome.runtime.MessageSender,
sendResponse: (response?: any) => void,
) => {
if (message.type === 'saveJSON') {
// Create a blob of the data
let data = JSON.stringify(message.images)
var blob = new Blob([data], {
type: 'application/json',
})

chrome.downloads.download(
{
url: `data:${blob.type};base64,${btoa(data)}`,
saveAs: true,
},
(downloadId: number) => {
if (downloadId == null) {
if (chrome.runtime.lastError) {
console.error(`saveJSON:`, chrome.runtime.lastError)
}
}
return true
},
)

sendResponse()
}

if (!(message && message.type === 'downloadImages')) return

downloadImages({
Expand Down Expand Up @@ -113,32 +138,35 @@ chrome.runtime.onInstalled.addListener((details) => {

chrome.tabs.onActivated.addListener((activeInfo) => {
try {
chrome.tabs.query({ active: true, lastFocusedWindow: true, windowId: activeInfo.windowId }, ([tab]) => {
if (tab?.url && !tab?.url?.includes("chrome://")) {
chrome.scripting.executeScript({
target: {
tabId: tab?.id!,
allFrames: true
},
files: ['image-extractor.js'],
})
} else {
chrome.action.setBadgeText({ text: '0' })
}
})
chrome.tabs.query(
{ active: true, lastFocusedWindow: true, windowId: activeInfo.windowId },
([tab]) => {
if (tab?.url && !tab?.url?.includes('chrome://')) {
chrome.scripting.executeScript({
target: {
tabId: tab?.id!,
allFrames: true,
},
files: ['image-extractor.js'],
})
} else {
chrome.action.setBadgeText({ text: '0' })
}
},
)
} catch (err) {
console.error(err)
}
});
})

chrome.tabs.onUpdated.addListener(() => {
try {
chrome.tabs.query({ active: true, lastFocusedWindow: true }, ([tab]) => {
if (tab?.url && !tab?.url?.includes("chrome://")) {
chrome.tabs.query({ active: true, lastFocusedWindow: true }, ([tab]) => {
if (tab?.url && !tab?.url?.includes('chrome://')) {
chrome.scripting.executeScript({
target: {
tabId: tab?.id!,
allFrames: true
allFrames: true,
},
files: ['image-extractor.js'],
})
Expand All @@ -149,7 +177,7 @@ chrome.tabs.onUpdated.addListener(() => {
} catch (err) {
console.error(err)
}
});
})

chrome.runtime.onMessage.addListener((message: Message) => {
if (message.type !== 'sendImages') return
Expand Down
14 changes: 3 additions & 11 deletions src/options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,12 @@ const App = () => {
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://www.typescriptlang.org/" target="_blank">
<img
src={typescriptLogo}
className="logo vanilla"
alt="TypeScript logo"
/>
<img src={typescriptLogo} className="logo vanilla" alt="TypeScript logo" />
</a>
<h1>Vite + TypeScript</h1>
<p className="read-the-docs">
Click on the Vite and TypeScript logos to learn more
</p>
<p className="read-the-docs">Click on the Vite and TypeScript logos to learn more</p>
</div>
)
}

ReactDOM.createRoot(document.querySelector<HTMLDivElement>('#app')!).render(
<App />,
)
ReactDOM.createRoot(document.querySelector<HTMLDivElement>('#app')!).render(<App />)
80 changes: 45 additions & 35 deletions src/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const App = () => {

useEffect(() => {
chrome.storage.sync.get().then((items) => {
setOptions(items as Options || { folder_name: '', active_tab_origin: '' })
setOptions((items as Options) || { folder_name: '', active_tab_origin: '' })
})
}, [])

Expand Down Expand Up @@ -75,21 +75,23 @@ const App = () => {
}, [])

const filterImages = useCallback(() => {

let tmp: Image[] = allImages?.map((url, index) => {
const image: HTMLImageElement = imageRef.current?.querySelector(`img[src="${encodeURI(url)}"]`)!
return { url: url, width: image?.naturalWidth, height: image?.naturalHeight, alt: `Image ${index + 1}` }
const image: HTMLImageElement = imageRef.current?.querySelector(
`img[src="${encodeURI(url)}"]`,
)!
return {
url: url,
width: image?.naturalWidth,
height: image?.naturalHeight,
alt: `Image ${index + 1}`,
}
})

setImages(tmp)
setLoading(false)
}, [allImages])

const onSelected = (
e: FormEvent<HTMLInputElement>,
index: number,
url: string = '',
) => {
const onSelected = (e: FormEvent<HTMLInputElement>, index: number, url: string = '') => {
if (e.currentTarget?.checked || selected.indexOf(url) === -1) {
setSelected((prev) => [...prev, allImages[index]])
} else {
Expand All @@ -114,6 +116,16 @@ const App = () => {
setSelectedAll(!selectedAll)
}

const onSaveJSON = () => {
chrome.runtime.sendMessage<DownloadMessage>(
{
type: 'saveJSON',
images: selected,
options,
},
)
}

const downloadImages = async () => {
setDownloadProgress(true)
chrome.runtime.sendMessage<DownloadMessage>(
Expand Down Expand Up @@ -144,37 +156,26 @@ const App = () => {
<div className="bg-zinc-950 p-3">
<div className="flex items-center gap-2">
<div className="h-18 w-18">
<img
src={viteSvg}
alt="Logo"
className="w-full h-full"
crossOrigin="anonymous"
/>
<img src={viteSvg} alt="Logo" className="w-full h-full" crossOrigin="anonymous" />
</div>
<h1 className="text-lg font-bold">Image Downloader</h1>
</div>
</div>
<div className="bg-zinc-900 p-2">
<button className="flex items-center gap-2" onClick={onSelectedAll}>
<input
type="checkbox"
checked={selectedAll}
onChange={onSelectedAll}
/>
<input type="checkbox" checked={selectedAll} onChange={onSelectedAll} />
<span>
Select All ({selected.length}/{allImages.length})
</span>
</button>
</div>
</header>
<div ref={imageRef} className='w-full grid grid-cols-2 p-2 gap-2 max-h-[460px] h-full overflow-y-auto hidden'>
<div
ref={imageRef}
className="w-full grid grid-cols-2 p-2 gap-2 max-h-[460px] h-full overflow-y-auto hidden"
>
{allImages?.map((url, index) => (
<img
key={index}
src={encodeURI(url)}
alt={`Image ${index + 1}`}
onLoad={filterImages}
/>
<img key={index} src={encodeURI(url)} alt={`Image ${index + 1}`} onLoad={filterImages} />
))}
</div>
{!loading && images.length > 0 ? (
Expand All @@ -191,7 +192,9 @@ const App = () => {
onClick={() => onSelectedImage(index, image.url)}
/>
<div className="flex flex-col text-xs truncate absolute bottom-0 left-0 right-0 z-10 p-1 bg-zinc-800/50 opacity-0 group-hover:opacity-100">
<p>{image.width}x{image.height}</p>
<p>
{image.width}x{image.height}
</p>
<p>{image.url}</p>
</div>
<div className="absolute top-0 left-0 right-0 flex items-center justify-between gap-2 p-1">
Expand Down Expand Up @@ -225,10 +228,7 @@ const App = () => {
) : (
<div className="w-full grid grid-cols-2 p-2 gap-2 max-h-[460px] h-full overflow-y-auto">
{[...Array(10)]?.map((_url, index) => (
<div
key={index}
className="min-w-[150px] h-[160px] bg-zinc-800 animate-pulse"
/>
<div key={index} className="min-w-[150px] h-[160px] bg-zinc-800 animate-pulse" />
))}
</div>
)}
Expand All @@ -245,6 +245,18 @@ const App = () => {
}))
}}
/>
<button
className={cn(
'py-1.5 px-3 text-center border rounded whitespace-nowrap',
selected.length <= 0
? 'bg-zinc-900 text-zinc-500 border-zinc-800'
: 'bg-zinc-800 border-zinc-700 hover:bg-zinc-800/80 focus:border-blue-500',
)}
onClick={onSaveJSON}
disabled={selected.length <= 0}
>
Save as JSON
</button>
<button
className={cn(
'py-1.5 px-3 text-center border rounded ',
Expand All @@ -262,6 +274,4 @@ const App = () => {
)
}

ReactDOM.createRoot(document.querySelector<HTMLDivElement>('#app')!).render(
<App />,
)
ReactDOM.createRoot(document.querySelector<HTMLDivElement>('#app')!).render(<App />)
8 changes: 4 additions & 4 deletions src/rules.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const allResourceTypes = Object.values(chrome.declarativeNetRequest.ResourceType);
const allResourceTypes = Object.values(chrome.declarativeNetRequest.ResourceType)

export const rules = (origin: string): chrome.declarativeNetRequest.Rule[] => [
{
Expand All @@ -12,11 +12,11 @@ export const rules = (origin: string): chrome.declarativeNetRequest.Rule[] => [
header: 'Referer',
value: origin,
},
]
],
},
condition: {
urlFilter: '*',
resourceTypes: allResourceTypes,
}
},
},
];
]
11 changes: 5 additions & 6 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ export type Options = {
new_file_name?: string
}


export type Image = {
url: string,
width: number,
height: number,
export type Image = {
url: string
width: number
height: number
alt: string
}
}
6 changes: 3 additions & 3 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const unique = (values: any): Array<any> => [...new Set(values)];
export const unique = (values: any): Array<any> => [...new Set(values)]

export const removeSpecialCharacters = (value: string) => value.replace(/[<>:"|?*]/g, '');
export const removeSpecialCharacters = (value: string) => value.replace(/[<>:"|?*]/g, '')

export const cn = (...classNames: Array<any>): string => classNames.filter(Boolean).join(' ');
export const cn = (...classNames: Array<any>): string => classNames.filter(Boolean).join(' ')

export const normalizeSlashes = (filename: string) => filename.replace(/\\/g, '/').replace(/\/{2,}/g, '/')

0 comments on commit ccdb874

Please sign in to comment.