Skip to content

Commit e151145

Browse files
committed
fix: code cleanup
1 parent 70f7094 commit e151145

5 files changed

Lines changed: 71 additions & 41 deletions

File tree

packages/pluggableWidgets/barcode-generator-web/src/components/Barcode.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function BarcodeRenderer({ config }: BarcodeRendererProps): ReactElement
2828

2929
const button = downloadButton && (
3030
<DownloadButton
31-
onClick={() => downloadCode(ref, config.type, downloadButton.fileName)}
31+
onClick={() => downloadCode(ref, config, downloadButton.fileName)}
3232
ariaLabel={downloadButton.label}
3333
caption={downloadButton.caption}
3434
/>

packages/pluggableWidgets/barcode-generator-web/src/components/QRCode.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function QRCodeRenderer({ config }: QRCodeRendererProps): ReactElement {
3939

4040
const button = downloadButton && (
4141
<DownloadButton
42-
onClick={() => downloadCode(ref, config.type, downloadButton.fileName)}
42+
onClick={() => downloadCode(ref, config, downloadButton.fileName)}
4343
ariaLabel={downloadButton.label}
4444
caption={downloadButton.caption}
4545
/>

packages/pluggableWidgets/barcode-generator-web/src/config/Barcode.config.ts

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
interface DownloadButtonConfig {
1010
caption?: string;
1111
label?: string;
12-
fileName: string;
12+
fileName?: string;
1313
buttonPosition: "top" | "bottom";
1414
}
1515

@@ -65,7 +65,7 @@ export function barcodeConfig(props: BarcodeGeneratorContainerProps): BarcodeCon
6565
? {
6666
caption: props.downloadButtonCaption?.value,
6767
label: props.downloadButtonAriaLabel?.value,
68-
fileName: generateFileName(props.downloadFileName?.value, format, codeValue),
68+
fileName: getFileName(props.downloadFileName?.value),
6969
buttonPosition: props.buttonPosition ?? "bottom"
7070
}
7171
: undefined;
@@ -119,34 +119,11 @@ export function barcodeConfig(props: BarcodeGeneratorContainerProps): BarcodeCon
119119
};
120120
}
121121

122-
function generateFileName(customFileName: string | undefined, format: string, codeValue: string): string {
122+
function getFileName(customFileName: string | undefined): string | undefined {
123123
// Use custom filename if provided
124124
if (customFileName && customFileName.trim()) {
125125
return customFileName.trim().endsWith(".png") ? customFileName.trim() : `${customFileName.trim()}.png`;
126126
}
127127

128-
// Auto-generate filename with format and hash
129-
const hash = hashCode(codeValue);
130-
if (format === "QRCode") {
131-
return `qrcode_${hash}.png`;
132-
}
133-
return `barcode_${format}_${hash}.png`;
134-
}
135-
136-
function hashCode(s: string): string {
137-
if (!s) {
138-
return "empty";
139-
}
140-
141-
let hash = 0;
142-
for (let i = 0; i < s.length; i++) {
143-
const char = s.charCodeAt(i);
144-
// eslint-disable-next-line no-bitwise
145-
hash = (hash << 5) - hash + char;
146-
// eslint-disable-next-line no-bitwise
147-
hash = hash & hash; // Convert to 32-bit integer
148-
}
149-
150-
// Convert to base36 and take first 10 characters
151-
return Math.abs(hash).toString(36).substring(0, 10);
128+
return undefined; // Let the download function generate a default filename based on content and timestamp
152129
}
Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import { RefObject } from "react";
2-
import { convertSvgToPng, downloadBlob, prepareSvgForDownload, processQRImages } from "./download-utils";
2+
import {
3+
convertSvgToPng,
4+
downloadBlob,
5+
prepareSvgForDownload,
6+
processQRImages,
7+
generateFileName
8+
} from "./download-utils";
39
import { BarcodeConfig } from "../config/Barcode.config";
410

511
export async function downloadCode(
612
ref: RefObject<SVGSVGElement | null>,
7-
type: BarcodeConfig["type"],
8-
fileName: string
13+
config: BarcodeConfig,
14+
fileName?: string
915
): Promise<void> {
1016
try {
1117
const svgElement = ref.current;
@@ -15,18 +21,22 @@ export async function downloadCode(
1521
}
1622

1723
const clonedSvg = prepareSvgForDownload(svgElement);
18-
24+
let fileNamePrefix: string = config.type;
1925
// Process overlay images for QR codes
20-
if (type === "qrcode") {
26+
if (config.type === "qrcode") {
2127
await processQRImages(clonedSvg);
28+
} else {
29+
fileNamePrefix = `${config.type}_${config.format}`;
2230
}
2331

2432
// Convert SVG to PNG with 2x scale for better quality
2533
const pngBlob = await convertSvgToPng(clonedSvg, 2);
2634

35+
// Generate filename if not provided
36+
const finalFileName = fileName || generateFileName(fileNamePrefix, config.codeValue);
2737
// Trigger download
28-
downloadBlob(pngBlob, fileName);
38+
downloadBlob(pngBlob, finalFileName, ref.current?.ownerDocument || document);
2939
} catch (error) {
30-
console.error(`Error downloading ${type}:`, error);
40+
console.error(`Error downloading ${config.type}:`, error);
3141
}
3242
}

packages/pluggableWidgets/barcode-generator-web/src/utils/download-utils.ts

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,49 @@ const NAMESPACES = {
55
XLINK: "http://www.w3.org/1999/xlink"
66
} as const;
77

8+
export function generateFileName(prefix: string, codeValue: string): string {
9+
// Auto-generate filename with format and hash
10+
const timestamp = generateTimestamp();
11+
const hash = hashCode(codeValue);
12+
return `${prefix}_${hash}_${timestamp}.png`;
13+
}
14+
15+
function generateTimestamp(): string {
16+
// Get current date and time
17+
const now = new Date();
18+
19+
// Format: YYYYMMDD_HHMMSS
20+
const timestamp =
21+
now.getFullYear().toString() +
22+
String(now.getMonth() + 1).padStart(2, "0") +
23+
String(now.getDate()).padStart(2, "0") +
24+
"_" +
25+
String(now.getHours()).padStart(2, "0") +
26+
String(now.getMinutes()).padStart(2, "0") +
27+
String(now.getSeconds()).padStart(2, "0");
28+
29+
// Return formatted filename
30+
return timestamp;
31+
}
32+
33+
function hashCode(s: string): string {
34+
if (!s) {
35+
return "empty";
36+
}
37+
38+
let hash = 0;
39+
for (let i = 0; i < s.length; i++) {
40+
const char = s.charCodeAt(i);
41+
// eslint-disable-next-line no-bitwise
42+
hash = (hash << 5) - hash + char;
43+
// eslint-disable-next-line no-bitwise
44+
hash = hash & hash; // Convert to 32-bit integer
45+
}
46+
47+
// Convert to base36 and take first 10 characters
48+
return Math.abs(hash).toString(36).substring(0, 10);
49+
}
50+
851
// Prepare SVG for download by setting namespaces
952
export const prepareSvgForDownload = (svgElement: SVGSVGElement): SVGSVGElement => {
1053
const clonedSvg = svgElement.cloneNode(true) as SVGSVGElement;
@@ -52,14 +95,14 @@ export const processQRImages = async (clonedSvg: SVGSVGElement): Promise<void> =
5295
}
5396
};
5497

55-
export const downloadBlob = (blob: Blob, filename: string): void => {
98+
export const downloadBlob = (blob: Blob, filename: string, currentDocument: Document = document): void => {
5699
const url = URL.createObjectURL(blob);
57-
const link = document.createElement("a");
100+
const link = currentDocument.createElement("a");
58101
link.href = url;
59102
link.download = filename;
60-
document.body.appendChild(link);
103+
currentDocument.body.appendChild(link);
61104
link.click();
62-
document.body.removeChild(link);
105+
currentDocument.body.removeChild(link);
63106
URL.revokeObjectURL(url);
64107
};
65108

@@ -73,7 +116,7 @@ export const convertSvgToPng = async (svgElement: SVGSVGElement, scale = 2): Pro
73116
const img = new Image();
74117
img.onload = () => {
75118
try {
76-
const canvas = document.createElement("canvas");
119+
const canvas = svgElement.ownerDocument.createElement("canvas");
77120
const ctx = canvas.getContext("2d");
78121

79122
if (!ctx) {

0 commit comments

Comments
 (0)