fix: refactor
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// SonicForge Studio API Service
|
||||
window.API_BASE_URL = window.API_BASE_URL || window.location.origin;
|
||||
|
||||
(function() {
|
||||
function getAuthToken() {
|
||||
return localStorage.getItem('sonic_token') || '';
|
||||
}
|
||||
|
||||
function getAuthHeaders() {
|
||||
const token = getAuthToken();
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
...(token ? { 'Authorization': `Bearer ${token}` } : {})
|
||||
};
|
||||
}
|
||||
|
||||
async function apiRequest(endpoint, options = {}) {
|
||||
const url = `${window.API_BASE_URL}${endpoint}`;
|
||||
const headers = { ...getAuthHeaders(), ...options.headers };
|
||||
const response = await fetch(url, { ...options, headers });
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('sonic_token');
|
||||
localStorage.removeItem('sonic_user');
|
||||
}
|
||||
|
||||
const data = await response.json().catch(() => ({}));
|
||||
if (!response.ok) {
|
||||
throw new Error(data.detail || data.message || 'Lỗi kết nối API Server');
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
window.SonicAPI = {
|
||||
login: (username, password) => apiRequest('/api/v1/auth/login', { method: 'POST', body: JSON.stringify({ username, password }) }),
|
||||
register: (username, email, password) => apiRequest('/api/v1/auth/register', { method: 'POST', body: JSON.stringify({ username, email, password }) }),
|
||||
changePassword: (old_password, new_password) => apiRequest('/api/v1/auth/change-password', { method: 'POST', body: JSON.stringify({ old_password, new_password }) }),
|
||||
getProfile: () => apiRequest('/api/v1/auth/profile', { method: 'GET' }),
|
||||
|
||||
listUsers: () => apiRequest('/api/v1/admin/users', { method: 'GET' }),
|
||||
updateUserQuota: (userId, storageLimitMb, maxTracks = 16) => apiRequest(`/api/v1/admin/quotas/${userId}`, { method: 'PUT', body: JSON.stringify({ storage_limit_mb: storageLimitMb, max_tracks: maxTracks }) }),
|
||||
updateUserRole: (userId, role, isActive = true) => apiRequest(`/api/v1/admin/users/${userId}/role`, { method: 'PUT', body: JSON.stringify({ role, is_active: isActive }) }),
|
||||
deleteUser: (userId) => apiRequest(`/api/v1/admin/users/${userId}`, { method: 'DELETE' }),
|
||||
|
||||
saveTempProject: (dataJson) => apiRequest('/api/v1/projects/temp', { method: 'POST', body: JSON.stringify({ data_json: dataJson }) }),
|
||||
getTempProject: () => apiRequest('/api/v1/projects/temp', { method: 'GET' }),
|
||||
saveCloudProject: (name, dataJson) => apiRequest('/api/v1/projects/cloud', { method: 'POST', body: JSON.stringify({ name, data_json: dataJson }) }),
|
||||
listCloudProjects: () => apiRequest('/api/v1/projects/cloud', { method: 'GET' })
|
||||
};
|
||||
})();
|
||||
@@ -0,0 +1,42 @@
|
||||
// SonicForge Studio Audio Engine Service
|
||||
(function() {
|
||||
let audioCtx = null;
|
||||
|
||||
function getAudioContext() {
|
||||
if (!audioCtx) {
|
||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
}
|
||||
if (audioCtx.state === 'suspended') {
|
||||
audioCtx.resume();
|
||||
}
|
||||
return audioCtx;
|
||||
}
|
||||
|
||||
function analyzeAudioBufferChannels(audioBuffer) {
|
||||
if (!audioBuffer) return { channels: 1, isStereo: false, label: 'MONO' };
|
||||
const numChannels = audioBuffer.numberOfChannels;
|
||||
const isStereo = numChannels >= 2;
|
||||
return {
|
||||
channels: numChannels,
|
||||
isStereo: isStereo,
|
||||
label: isStereo ? 'STEREO' : 'MONO',
|
||||
sampleRate: audioBuffer.sampleRate,
|
||||
duration: audioBuffer.duration,
|
||||
length: audioBuffer.length
|
||||
};
|
||||
}
|
||||
|
||||
async function decodeAudioFile(file) {
|
||||
const ctx = getAudioContext();
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
|
||||
const channelInfo = analyzeAudioBufferChannels(audioBuffer);
|
||||
return { audioBuffer, channelInfo };
|
||||
}
|
||||
|
||||
window.SonicAudio = {
|
||||
getAudioContext,
|
||||
analyzeAudioBufferChannels,
|
||||
decodeAudioFile
|
||||
};
|
||||
})();
|
||||
@@ -0,0 +1,73 @@
|
||||
// SonicForge Studio Project Storage & .sfs File Service
|
||||
(function() {
|
||||
const SFS_VERSION = "1.0.0";
|
||||
|
||||
function exportProjectToSFS(projectState) {
|
||||
const sfsBundle = {
|
||||
format: "SONICFORGE_STUDIO_PROJECT",
|
||||
version: SFS_VERSION,
|
||||
timestamp: Date.now(),
|
||||
domain: window.location.origin,
|
||||
project: {
|
||||
id: projectState.id || `proj_${Date.now()}`,
|
||||
name: projectState.name || "Dự án mới",
|
||||
tracks: (projectState.tracks || []).map(t => ({
|
||||
id: t.id,
|
||||
name: t.name,
|
||||
startTime: t.startTime,
|
||||
height: t.height,
|
||||
volumeDb: t.volumeDb,
|
||||
pan: t.pan,
|
||||
muted: t.muted,
|
||||
solo: t.solo,
|
||||
color: t.color,
|
||||
markers: t.markers || [],
|
||||
serverFileId: t.serverFileId || null
|
||||
}))
|
||||
}
|
||||
};
|
||||
|
||||
const jsonStr = JSON.stringify(sfsBundle, null, 2);
|
||||
const blob = new Blob([jsonStr], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `${(projectState.name || 'project').replace(/\s+/g, '_')}.sfs`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
async function importProjectFromSFSFile(file) {
|
||||
const text = await file.text();
|
||||
const sfsBundle = JSON.parse(text);
|
||||
if (sfsBundle.format !== "SONICFORGE_STUDIO_PROJECT") {
|
||||
throw new Error("Tệp tin không đúng định dạng .sfs của SonicForge Studio");
|
||||
}
|
||||
return sfsBundle.project;
|
||||
}
|
||||
|
||||
let autoSaveTimer = null;
|
||||
function scheduleTempAutoSave(getProjectStateCallback) {
|
||||
if (autoSaveTimer) clearTimeout(autoSaveTimer);
|
||||
autoSaveTimer = setTimeout(async () => {
|
||||
try {
|
||||
const state = getProjectStateCallback();
|
||||
if (!state || !state.tracks || state.tracks.length === 0) return;
|
||||
const dataJson = JSON.stringify(state);
|
||||
localStorage.setItem('sonic_temp_project', dataJson);
|
||||
if (window.SonicAPI && localStorage.getItem('sonic_token')) {
|
||||
await window.SonicAPI.saveTempProject(dataJson).catch(() => {});
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Auto-save temp project warning:", e);
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
window.SonicStorage = {
|
||||
exportProjectToSFS,
|
||||
importProjectFromSFSFile,
|
||||
scheduleTempAutoSave
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user