@yogiswara/honcho-editor-ui 3.8.3 → 3.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * STEP 2: Web Worker for Image Processing
3
+ *
4
+ * This worker runs the HonchoEditor in a separate thread to prevent
5
+ * UI freezing on iOS Safari. It uses OffscreenCanvas for processing.
6
+ */
7
+ export {};
@@ -0,0 +1,156 @@
1
+ /**
2
+ * STEP 2: Web Worker for Image Processing
3
+ *
4
+ * This worker runs the HonchoEditor in a separate thread to prevent
5
+ * UI freezing on iOS Safari. It uses OffscreenCanvas for processing.
6
+ */
7
+ // Import the HonchoEditor class
8
+ // @ts-ignore - dynamic import for worker context
9
+ import { HonchoEditor } from '../honcho-editor.js';
10
+ // Create a single editor instance that will be reused
11
+ let editor = null;
12
+ let isInitialized = false;
13
+ let envConfig = {};
14
+ // Helper function to log messages from worker (visible in main thread console)
15
+ const log = (message, ...args) => {
16
+ console.log(`[Worker] ${message}`, ...args);
17
+ };
18
+ // Pre-configure Module BEFORE importing the script
19
+ // This ensures the locateFile function is available when the WASM loads
20
+ self.Module = {
21
+ locateFile: (path) => {
22
+ // Resolve WASM file path relative to the public folder
23
+ if (path.endsWith('.wasm')) {
24
+ log('WASM path resolved to:', '/honcho-photo-editor.wasm');
25
+ return '/honcho-photo-editor.wasm';
26
+ }
27
+ return path;
28
+ }
29
+ };
30
+ log('Worker script loaded and ready');
31
+ // Handle incoming messages from the main thread
32
+ self.onmessage = async (event) => {
33
+ const { type, id, path, framePath, adjustments, env } = event.data;
34
+ log(`đŸ“Ĩ Received message: ${type}`, { id, path, framePath });
35
+ try {
36
+ if (type === 'INIT') {
37
+ log('🔧 Starting initialization...');
38
+ // Store environment variables
39
+ if (env) {
40
+ envConfig = env;
41
+ log('✓ Environment variables stored:', envConfig);
42
+ }
43
+ // Initialize the editor
44
+ if (!editor) {
45
+ log('đŸ“Ļ Loading WASM module script...');
46
+ // Load the WASM module script
47
+ // The Module config above will be picked up by the script
48
+ self.importScripts('/honcho-photo-editor.js');
49
+ log('âŗ Waiting for Module to be available...');
50
+ // Wait a moment for Module to be available
51
+ await new Promise(resolve => setTimeout(resolve, 200));
52
+ log('🎨 Creating HonchoEditor instance...');
53
+ editor = new HonchoEditor();
54
+ log('âš™ī¸ Initializing editor...');
55
+ await editor.initialize(false);
56
+ isInitialized = true;
57
+ log('✅ Editor initialized successfully');
58
+ }
59
+ else {
60
+ log('â„šī¸ Editor already initialized, skipping...');
61
+ }
62
+ // Notify main thread that initialization is complete
63
+ log('📤 Sending INIT_SUCCESS to main thread');
64
+ self.postMessage({ type: 'INIT_SUCCESS' });
65
+ }
66
+ else if (type === 'PROCESS') {
67
+ log(`đŸ–ŧī¸ Processing image: ${id}`);
68
+ // Ensure editor is initialized
69
+ if (!isInitialized || !editor) {
70
+ throw new Error('Editor not initialized - call INIT first');
71
+ }
72
+ // Fetch image blobs in the worker
73
+ log(`đŸ“Ļ Fetching image from: ${path}`);
74
+ const imageBlob = await fetchImageAsBlob(path);
75
+ log(`✓ Fetched image blob: ${imageBlob.size} bytes`);
76
+ let frameBlob = null;
77
+ if (framePath) {
78
+ log(`đŸ“Ļ Fetching frame from: ${framePath}`);
79
+ frameBlob = await fetchImageAsBlob(framePath);
80
+ log(`✓ Fetched frame blob: ${frameBlob.size} bytes`);
81
+ }
82
+ log('đŸŽ›ī¸ Adjustments:', adjustments);
83
+ log('⚡ Starting processToBlobFast...');
84
+ const startTime = performance.now();
85
+ // Process the image
86
+ const resultBlob = await editor.processToBlobFast(imageBlob, adjustments || {}, frameBlob);
87
+ const duration = Math.round(performance.now() - startTime);
88
+ log(`✅ Processing complete in ${duration}ms, result size: ${resultBlob.size} bytes`);
89
+ // Send the result back to the main thread
90
+ log(`📤 Sending PROCESS_SUCCESS to main thread for ${id}`);
91
+ self.postMessage({
92
+ type: 'PROCESS_SUCCESS',
93
+ id,
94
+ blob: resultBlob
95
+ });
96
+ }
97
+ else {
98
+ throw new Error(`Unknown message type: ${type}`);
99
+ }
100
+ }
101
+ catch (error) {
102
+ log(`❌ Error processing message type ${type}:`, error);
103
+ // Send error back to main thread
104
+ const errorMessage = error instanceof Error ? error.message : String(error);
105
+ const errorStack = error instanceof Error ? error.stack : undefined;
106
+ log(`📤 Sending ERROR to main thread for ${id}`, { error: errorMessage });
107
+ self.postMessage({
108
+ type: 'ERROR',
109
+ id,
110
+ error: errorMessage,
111
+ stack: errorStack
112
+ });
113
+ }
114
+ };
115
+ // Helper function to fetch image as blob in worker
116
+ async function fetchImageAsBlob(url) {
117
+ const BUCKET_HOST = envConfig.bucketHost;
118
+ const CLOUD_FRONT_HOST = envConfig.cloudFrontHost;
119
+ // Try CloudFront first if available
120
+ if (CLOUD_FRONT_HOST && BUCKET_HOST) {
121
+ try {
122
+ const key = url.replace(BUCKET_HOST, "");
123
+ const response = await fetch(`${CLOUD_FRONT_HOST}${key}`);
124
+ if (response.ok) {
125
+ log(`✓ Fetched from CloudFront: ${key}`);
126
+ return response.blob();
127
+ }
128
+ }
129
+ catch (error) {
130
+ log(`âš ī¸ CloudFront fetch failed for ${url}:`, error);
131
+ }
132
+ }
133
+ // Fallback to direct fetch
134
+ try {
135
+ const response = await fetch(url, {
136
+ mode: 'cors',
137
+ credentials: 'omit'
138
+ });
139
+ if (response.ok) {
140
+ log(`✓ Fetched directly: ${url}`);
141
+ return response.blob();
142
+ }
143
+ }
144
+ catch (error) {
145
+ log(`âš ī¸ Direct fetch failed for ${url}:`, error);
146
+ }
147
+ // Final fallback to proxy
148
+ const proxyUrl = `/api/image?imageUrl=${encodeURIComponent(url)}`;
149
+ log(`âš ī¸ Using proxy fallback: ${proxyUrl}`);
150
+ const response = await fetch(proxyUrl);
151
+ if (!response.ok) {
152
+ throw new Error(`Failed to fetch image: ${response.statusText}`);
153
+ }
154
+ return response.blob();
155
+ }
156
+ log('Worker message handler registered');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yogiswara/honcho-editor-ui",
3
- "version": "3.8.3",
3
+ "version": "3.8.5",
4
4
  "description": "A complete UI component library for the Honcho photo editor.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",