/)[1] // Extract start time in ms
+ let dialogueMatch = syncBlock.match(/]*>(.*?)<\/P>/) // Extract text inside
+ let dialogue = dialogueMatch
+ ? dialogueMatch[1].replace(/<[^>]+>/g, '').trim()
+ : '' // Remove HTML tags
+
+ if (!dialogue) return '' // Skip empty captions
+ let startFormatted = formatMillisecondsToVTT(startTime)
+
+ // Use next start time as the end time if available
+ let nextSyncMatch = text.match(
+ new RegExp(``)
+ )
+ let endTime = nextSyncMatch
+ ? nextSyncMatch[1]
+ : parseInt(startTime) + 3000 // Default to +3s
+
+ let endFormatted = formatMillisecondsToVTT(endTime)
+ return `${startFormatted} --> ${endFormatted}\n${dialogue}`
+ })
+ .filter(syncBlock => syncBlock !== '')
+ .join('\n\n')
+ .trim()
+ break
+ case '.sub':
+ // Convert SUB to VTT
+ vttContent += text
+ .replace(/\r\n|\r/g, '\n') // Normalize newlines
+ .split('\n\n') // Split by empty lines (each caption block)
+ .map(block => {
+ let lines = block.split('\n').filter(line => line.trim() !== ''); // Remove empty lines
+ if (lines.length < 2) return ''; // Ensure each block has a timestamp and text
+
+ let [time, ...dialogue] = lines; // First line is time, rest is dialogue
+ let [start, end] = time.split(','); // Split start and end time
+
+ if (!start || !end || dialogue.length === 0) return ''; // Skip invalid blocks
+
+ start = formatSubTime(start.trim());
+ end = formatSubTime(end.trim());
+
+ return `${start} --> ${end}\n${dialogue.join(' ')}`; // Join dialogue lines into one block
+ })
+ .filter(block => block !== '') // Remove empty blocks
+ .join('\n\n')
+ .trim();
+ break;
+
+
+ default:
+ throw new Error('Unsupported subtitle format.')
+ }
+
+ return vttContent
+}
+
+// Helper function to format LRC time (e.g., 00:00.000 -> 00:00:00.000)
+function formatLrcTime (time) {
+ let [minutes, seconds] = time.split(':')
+ let [sec, ms] = seconds.split('.')
+ ms = ms ? ms.padEnd(3, '0') : '000' // Ensure milliseconds are 3 digits
+
+ // Return in the correct format
+ return `00:${minutes}:${sec}.${ms}`
+}
+
+// Helper function to fix ASS/SSA timestamps
+function formatAssTime (time) {
+ let parts = time.split(':')
+ let hours = parts.length === 3 ? parseInt(parts[0]) : 0
+ let minutes = parts.length === 3 ? parts[1] : parts[0]
+ let seconds = parts[parts.length - 1].replace('.', ':')
+
+ // Ensure proper milliseconds formatting (000)
+ const [sec, ms = '000'] = seconds.split(':')
+ return `${hours}:${minutes}:${sec}.${ms.padEnd(3, '0')}`
+}
+
+// Helper function to ensure proper SUB timestamp format (with 3-digit milliseconds)
+function formatSubTime(time) {
+ let parts = time.split(':');
+ if (parts.length < 3) return '00:00:00.000'; // Fallback for invalid input
+
+ let [hours, minutes, secMs] = parts;
+ let [seconds, ms = '000'] = secMs.split('.');
+
+ ms = ms.padEnd(3, '0'); // Ensure milliseconds are 3 digits
+
+ return `${hours}:${minutes}:${seconds}.${ms}`;
+}
+
+
+// Helper function to convert milliseconds to HH:MM:SS.MMM format
+function formatMillisecondsToVTT (ms) {
+ let totalSeconds = Math.floor(ms / 1000)
+ let milliseconds = (ms % 1000).toString().padStart(3, '0')
+ let hours = Math.floor(totalSeconds / 3600)
+ let minutes = Math.floor((totalSeconds % 3600) / 60)
+ let seconds = totalSeconds % 60
+ return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds
+ .toString()
+ .padStart(2, '0')}.${milliseconds}`
+}
diff --git a/frontend/src/utils/upload.js b/frontend/src/utils/upload.js
index 4ef1e0d4..7bf594dd 100644
--- a/frontend/src/utils/upload.js
+++ b/frontend/src/utils/upload.js
@@ -128,7 +128,7 @@ export async function handleFiles(files, base, overwrite = false) {
overwrite,
};
let last = 0;
- notify.showPopup("success",`(${c} of ${count}) Uploading ${file.name}`,false);
+ notify.showPopup("success", `(${c} of ${count}) Uploading ${file.name}`, false);
await filesApi.post(
item.path,
item.file,
@@ -143,23 +143,22 @@ export async function handleFiles(files, base, overwrite = false) {
last = percentComplete;
setTimeout(() => {
blockUpdates = false;
- }, 200);
+ }, 250);
}
- )
- .then(response => {
- let spinner = document.querySelector('.notification-spinner')
+ ).then(response => {
+ let spinner = document.querySelector('.notification-spinner');
if (spinner) {
- spinner.classList.add('hidden')
+ spinner.classList.add('hidden');
}
- console.log("Upload successful!",response);
+ console.log("Upload successful!", response);
notify.showSuccess("Upload successful!");
- })
- .catch(error => {
- let spinner = document.querySelector('.notification-spinner')
+ }).catch(error => {
+ let spinner = document.querySelector('.notification-spinner');
if (spinner) {
- spinner.classList.add('hidden')
+ spinner.classList.add('hidden');
}
- notify.showError("Error uploading file: "+error);
+ notify.showError("Error uploading file: " + error);
+ throw error;
});
}
}
\ No newline at end of file
diff --git a/frontend/src/utils/url.js b/frontend/src/utils/url.js
index c0501e14..aea6efa8 100644
--- a/frontend/src/utils/url.js
+++ b/frontend/src/utils/url.js
@@ -54,15 +54,8 @@ export function removePrefix(path, prefix = "") {
if (prefix != "") {
prefix = "/" + trimSlashes(prefix)
}
- const combined = trimSlashes(baseURL) + prefix
- const combined2 = "/" + combined
// Remove combined (baseURL + prefix) from the start of the path if present
- if (path.startsWith(combined)) {
- path = path.slice(combined.length);
- } else if (path.startsWith(combined2)) {
- path = path.slice(combined2.length);
- } else if (path.startsWith(prefix)) {
- // Fallback: remove only the prefix if the combined string isn't present
+ if (path.startsWith(prefix)) {
path = path.slice(prefix.length);
}
diff --git a/frontend/src/views/Files.vue b/frontend/src/views/Files.vue
index bba18a4b..b31be158 100644
--- a/frontend/src/views/Files.vue
+++ b/frontend/src/views/Files.vue
@@ -70,6 +70,7 @@ export default {
$route: "fetchData",
reload(value) {
if (value) {
+ console.log("Reloading");
this.fetchData();
}
},
@@ -100,15 +101,12 @@ export default {
}
},
async fetchData() {
- if (state.route.path === this.lastPath) return;
this.lastHash = "";
// Set loading to true and reset the error.
mutations.setLoading("files", true);
this.error = null;
// Reset view information using mutations
mutations.setReload(false);
- mutations.setMultiple(false);
- mutations.closeHovers();
let data = {};
try {
@@ -116,13 +114,7 @@ export default {
let res = await filesApi.fetchFiles(getters.routePath());
// If not a directory, fetch content
if (res.type != "directory") {
- let content = false;
- if (
- !res.onlyOfficeId &&
- (res.type.startsWith("application") || res.type.startsWith("text"))
- ) {
- content = true;
- }
+ const content = !getters.onlyOfficeEnabled()
res = await filesApi.fetchFiles(getters.routePath(), content);
}
data = res;
diff --git a/frontend/src/views/bars/EditorBar.vue b/frontend/src/views/bars/EditorBar.vue
index b0762b12..1e020d0f 100644
--- a/frontend/src/views/bars/EditorBar.vue
+++ b/frontend/src/views/bars/EditorBar.vue
@@ -27,7 +27,7 @@
diff --git a/frontend/src/views/files/Preview.vue b/frontend/src/views/files/Preview.vue
index 5566618e..d63dd758 100644
--- a/frontend/src/views/files/Preview.vue
+++ b/frontend/src/views/files/Preview.vue
@@ -1,19 +1,39 @@
-
+
-
-
-