Skip to content

Commit 238a71d

Browse files
committed
feat: streamline document creation and opening logic by enhancing event handling and ensuring UI consistency
1 parent ee10a40 commit 238a71d

2 files changed

Lines changed: 67 additions & 103 deletions

File tree

‎lib/document.ts‎

Lines changed: 49 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,9 @@ export const onCreateNew = async (ext: string): Promise<void> => {
3030
// Note: Loading is now shown in the menu button click handler
3131
// This function should not show loading again to avoid double loading indicators
3232
try {
33-
// Hide control panel if it's visible
33+
// Always hide control panel and ensure FAB is visible when creating new document
3434
if (hideControlPanelFn) {
35-
const container = document.querySelector('#control-panel-container') as HTMLElement;
36-
if (container && container.style.display !== 'none') {
37-
hideControlPanelFn();
38-
}
35+
hideControlPanelFn();
3936
}
4037
setDocmentObj({
4138
fileName: 'New_Document' + ext,
@@ -62,88 +59,61 @@ export const onCreateNew = async (ext: string): Promise<void> => {
6259
}
6360
};
6461

65-
export const onOpenDocument = async (): Promise<boolean> => {
66-
return new Promise((resolve) => {
67-
let resolved = false;
68-
let cancelTimeout: NodeJS.Timeout | null = null;
62+
export const onOpenDocument = (): void => {
63+
// Clear previous event handler and value
64+
fileInput.onchange = null;
65+
fileInput.value = '';
6966

70-
// Clear previous event handler and value
71-
fileInput.onchange = null;
72-
fileInput.value = '';
73-
74-
// Set up a longer timeout to detect if user cancelled (no change event)
75-
// This handles the case where user cancels without triggering onchange
76-
// Use a longer timeout (5 seconds) to avoid false positives
77-
cancelTimeout = setTimeout(() => {
78-
if (!resolved) {
79-
resolved = true;
80-
fileInput.value = '';
81-
fileInput.onchange = null;
82-
resolve(false);
83-
}
84-
}, 5000);
85-
86-
// Define the change handler
87-
const handleChange = async (event: Event) => {
88-
if (cancelTimeout) {
89-
clearTimeout(cancelTimeout);
90-
cancelTimeout = null;
91-
}
67+
// Define the change handler
68+
const handleChange = async (event: Event) => {
69+
const file = (event.target as HTMLInputElement).files?.[0];
9270

93-
const file = (event.target as HTMLInputElement).files?.[0];
94-
95-
// Clear the handler to prevent multiple triggers
96-
fileInput.onchange = null;
71+
// Clear the handler to prevent multiple triggers
72+
fileInput.onchange = null;
9773

98-
if (file && !resolved) {
99-
resolved = true;
100-
const { removeLoading } = showLoading();
101-
try {
102-
if (hideControlPanelFn) {
103-
hideControlPanelFn();
104-
}
105-
setDocmentObj({
106-
fileName: file.name,
107-
file: file,
108-
url: await createObjectURL(file),
109-
});
110-
await initX2T();
111-
const { fileName, file: fileBlob } = getDocmentObj();
112-
await handleDocumentOperation({ file: fileBlob, fileName, isNew: !fileBlob });
113-
// Clear file selection so the same file can be selected again
114-
fileInput.value = '';
115-
// Show menu guide after document is loaded
116-
if (showMenuGuideFn) {
117-
setTimeout(() => {
118-
showMenuGuideFn!();
119-
}, 1000);
120-
}
121-
resolve(true);
122-
} catch (error) {
123-
console.error('Error opening document:', error);
124-
// Ensure control panel is shown on error
125-
if (showControlPanelFn) {
126-
showControlPanelFn();
127-
}
128-
resolve(false);
129-
} finally {
130-
// Always remove loading, even if there's an error
131-
removeLoading();
74+
// Only process if a file was actually selected
75+
// If user cancelled, onchange won't fire, nothing happens
76+
if (file) {
77+
const { removeLoading } = showLoading();
78+
try {
79+
if (hideControlPanelFn) {
80+
hideControlPanelFn();
13281
}
133-
} else if (!resolved) {
134-
// onchange fired but no file selected (user cancelled or cleared selection)
135-
resolved = true;
82+
setDocmentObj({
83+
fileName: file.name,
84+
file: file,
85+
url: await createObjectURL(file),
86+
});
87+
await initX2T();
88+
const { fileName, file: fileBlob } = getDocmentObj();
89+
await handleDocumentOperation({ file: fileBlob, fileName, isNew: !fileBlob });
90+
// Clear file selection so the same file can be selected again
13691
fileInput.value = '';
137-
resolve(false);
92+
// Show menu guide after document is loaded
93+
if (showMenuGuideFn) {
94+
setTimeout(() => {
95+
showMenuGuideFn!();
96+
}, 1000);
97+
}
98+
} catch (error) {
99+
console.error('Error opening document:', error);
100+
// Ensure control panel is shown on error
101+
if (showControlPanelFn) {
102+
showControlPanelFn();
103+
}
104+
} finally {
105+
// Always remove loading, even if there's an error
106+
removeLoading();
138107
}
139-
};
108+
}
109+
// If no file selected, nothing happens (user cancelled)
110+
};
140111

141-
// Set the change handler
142-
fileInput.onchange = handleChange;
112+
// Set the change handler
113+
fileInput.onchange = handleChange;
143114

144-
// Trigger file picker click event
145-
fileInput.click();
146-
});
115+
// Trigger file picker click event
116+
fileInput.click();
147117
};
148118

149119
export const openDocumentFromUrl = async (url: string, fileName?: string): Promise<void> => {

‎lib/ui.ts‎

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,20 @@ import { onCreateNew, onOpenDocument } from './document';
66
// Hide control panel and show top floating bar
77
export const hideControlPanel = (): void => {
88
const container = document.querySelector('#control-panel-container') as HTMLElement;
9+
const fabContainer = document.querySelector('#fab-container') as HTMLElement;
10+
11+
// Always ensure FAB is visible when hiding control panel
12+
if (fabContainer) {
13+
fabContainer.style.display = 'block';
14+
}
15+
916
if (container) {
1017
// Immediately disable pointer events to prevent blocking
1118
container.style.pointerEvents = 'none';
1219
container.style.opacity = '0';
1320
// Hide after transition for smooth animation
1421
setTimeout(() => {
1522
container.style.display = 'none';
16-
showTopFloatingBar();
1723
}, 300);
1824
}
1925
};
@@ -28,19 +34,13 @@ export const showControlPanel = (): void => {
2834
container.style.opacity = '1';
2935
}, 10);
3036
}
31-
if (fabContainer) {
37+
// Only hide FAB if editor is not open
38+
// If editor is already open, keep FAB visible so user can access menu
39+
if (fabContainer && !window.editor) {
3240
fabContainer.style.display = 'none';
3341
}
3442
};
3543

36-
// Show fixed action button
37-
const showTopFloatingBar = (): void => {
38-
const fabContainer = document.querySelector('#fab-container') as HTMLElement;
39-
if (fabContainer) {
40-
fabContainer.style.display = 'block';
41-
}
42-
};
43-
4444
// Create fixed action button in bottom right corner
4545
export const createFixedActionButton = (): HTMLElement => {
4646
const fabContainer = document.createElement('div');
@@ -106,13 +106,10 @@ export const createFixedActionButton = (): HTMLElement => {
106106
menuPanel.appendChild(
107107
createMenuButton(
108108
t('uploadDocument'),
109-
async () => {
110-
const result = await onOpenDocument();
111-
// If user cancelled file selection, show control panel again
112-
// (FAB menu will be hidden by hideMenu() call in createMenuButton)
113-
if (!result) {
114-
showControlPanel();
115-
}
109+
() => {
110+
onOpenDocument();
111+
// If user cancelled, nothing happens (onchange won't fire)
112+
// If user selected file, document will be opened in handleChange
116113
},
117114
false, // Don't show loading immediately - wait for file selection
118115
),
@@ -320,13 +317,10 @@ export const createControlPanel = (): void => {
320317
};
321318

322319
// Create four buttons
323-
const uploadButton = createTextButton('upload-button', t('uploadDocument'), async () => {
324-
const result = await onOpenDocument();
325-
// Only hide control panel if file was successfully selected
326-
// If user cancelled, control panel remains visible
327-
if (result) {
328-
hideControlPanel();
329-
}
320+
const uploadButton = createTextButton('upload-button', t('uploadDocument'), () => {
321+
onOpenDocument();
322+
// If user cancelled, nothing happens (onchange won't fire, control panel remains visible)
323+
// If user selected file, document will be opened and control panel will be hidden in handleChange
330324
});
331325
buttonGroup.appendChild(uploadButton);
332326

0 commit comments

Comments
 (0)