Initial release: DictIA v0.8.14-alpha (fork de Speakr, AGPL-3.0)
This commit is contained in:
95
static/js/modules/state/audio.js
Normal file
95
static/js/modules/state/audio.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Audio recording state management
|
||||
*/
|
||||
|
||||
export function createAudioState(ref, computed) {
|
||||
// --- Audio Recording State ---
|
||||
const isRecording = ref(false);
|
||||
const mediaRecorder = ref(null);
|
||||
const audioChunks = ref([]);
|
||||
const audioBlobURL = ref(null);
|
||||
const recordingTime = ref(0);
|
||||
const recordingInterval = ref(null);
|
||||
const canRecordAudio = ref(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
|
||||
const canRecordSystemAudio = computed(() => navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia);
|
||||
const systemAudioSupported = ref(false);
|
||||
const systemAudioError = ref('');
|
||||
const recordingNotes = ref('');
|
||||
const showSystemAudioHelp = ref(false);
|
||||
|
||||
// ASR options for recording view
|
||||
const asrLanguage = ref('');
|
||||
const asrMinSpeakers = ref('');
|
||||
const asrMaxSpeakers = ref('');
|
||||
|
||||
// Audio context and analyzers
|
||||
const audioContext = ref(null);
|
||||
const analyser = ref(null);
|
||||
const micAnalyser = ref(null);
|
||||
const systemAnalyser = ref(null);
|
||||
const visualizer = ref(null);
|
||||
const micVisualizer = ref(null);
|
||||
const systemVisualizer = ref(null);
|
||||
const animationFrameId = ref(null);
|
||||
const recordingMode = ref('microphone');
|
||||
const activeStreams = ref([]);
|
||||
|
||||
// --- Wake Lock and Background Recording ---
|
||||
const wakeLock = ref(null);
|
||||
const recordingNotification = ref(null);
|
||||
const isPageVisible = ref(true);
|
||||
|
||||
// --- Recording Size Monitoring ---
|
||||
const estimatedFileSize = ref(0);
|
||||
const fileSizeWarningShown = ref(false);
|
||||
const recordingQuality = ref('optimized');
|
||||
const actualBitrate = ref(0);
|
||||
const maxRecordingMB = ref(200);
|
||||
const sizeCheckInterval = ref(null);
|
||||
|
||||
return {
|
||||
// Recording state
|
||||
isRecording,
|
||||
mediaRecorder,
|
||||
audioChunks,
|
||||
audioBlobURL,
|
||||
recordingTime,
|
||||
recordingInterval,
|
||||
canRecordAudio,
|
||||
canRecordSystemAudio,
|
||||
systemAudioSupported,
|
||||
systemAudioError,
|
||||
recordingNotes,
|
||||
showSystemAudioHelp,
|
||||
|
||||
// ASR options
|
||||
asrLanguage,
|
||||
asrMinSpeakers,
|
||||
asrMaxSpeakers,
|
||||
|
||||
// Audio context
|
||||
audioContext,
|
||||
analyser,
|
||||
micAnalyser,
|
||||
systemAnalyser,
|
||||
visualizer,
|
||||
micVisualizer,
|
||||
systemVisualizer,
|
||||
animationFrameId,
|
||||
recordingMode,
|
||||
activeStreams,
|
||||
|
||||
// Wake lock
|
||||
wakeLock,
|
||||
recordingNotification,
|
||||
isPageVisible,
|
||||
|
||||
// Size monitoring
|
||||
estimatedFileSize,
|
||||
fileSizeWarningShown,
|
||||
recordingQuality,
|
||||
actualBitrate,
|
||||
maxRecordingMB,
|
||||
sizeCheckInterval
|
||||
};
|
||||
}
|
||||
23
static/js/modules/state/chat.js
Normal file
23
static/js/modules/state/chat.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Chat state management
|
||||
*/
|
||||
|
||||
export function createChatState(ref) {
|
||||
const showChat = ref(false);
|
||||
const isChatMaximized = ref(false);
|
||||
const chatMessages = ref([]);
|
||||
const chatInput = ref('');
|
||||
const isChatLoading = ref(false);
|
||||
const chatMessagesRef = ref(null);
|
||||
const chatInputRef = ref(null);
|
||||
|
||||
return {
|
||||
showChat,
|
||||
isChatMaximized,
|
||||
chatMessages,
|
||||
chatInput,
|
||||
isChatLoading,
|
||||
chatMessagesRef,
|
||||
chatInputRef
|
||||
};
|
||||
}
|
||||
164
static/js/modules/state/core.js
Normal file
164
static/js/modules/state/core.js
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Core application state
|
||||
*/
|
||||
|
||||
export function createCoreState(ref, computed) {
|
||||
// --- Core State ---
|
||||
const currentView = ref('upload');
|
||||
const dragover = ref(false);
|
||||
const recordings = ref([]);
|
||||
const selectedRecording = ref(null);
|
||||
const selectedTab = ref('summary');
|
||||
const searchQuery = ref('');
|
||||
const isLoadingRecordings = ref(true);
|
||||
const globalError = ref(null);
|
||||
|
||||
// --- Pagination State ---
|
||||
const currentPage = ref(1);
|
||||
const perPage = ref(25);
|
||||
const totalRecordings = ref(0);
|
||||
const totalPages = ref(0);
|
||||
const hasNextPage = ref(false);
|
||||
const hasPrevPage = ref(false);
|
||||
const isLoadingMore = ref(false);
|
||||
const searchDebounceTimer = ref(null);
|
||||
|
||||
// --- Enhanced Search & Organization State ---
|
||||
const sortBy = ref('created_at');
|
||||
const selectedTagFilter = ref(null);
|
||||
|
||||
// Advanced filter state
|
||||
const showAdvancedFilters = ref(false);
|
||||
const filterTags = ref([]);
|
||||
const filterSpeakers = ref([]); // Array of speaker names for filtering
|
||||
const filterDateRange = ref({ start: '', end: '' });
|
||||
const filterDatePreset = ref('');
|
||||
const filterTextQuery = ref('');
|
||||
const showArchivedRecordings = ref(false);
|
||||
const showSharedWithMe = ref(false);
|
||||
|
||||
// --- App Configuration ---
|
||||
const useAsrEndpoint = ref(false);
|
||||
const connectorSupportsDiarization = ref(false); // Connector capability for diarization UI
|
||||
const connectorSupportsSpeakerCount = ref(false); // Connector capability for min/max speakers
|
||||
const currentUserName = ref('');
|
||||
const canDeleteRecordings = ref(true);
|
||||
const enableInternalSharing = ref(false);
|
||||
const enableArchiveToggle = ref(false);
|
||||
const showUsernamesInUI = ref(false);
|
||||
|
||||
// --- Incognito Mode State ---
|
||||
const enableIncognitoMode = ref(false); // Server config - whether feature is available
|
||||
const incognitoMode = ref(false); // User toggle - whether to use incognito for current upload
|
||||
const incognitoRecording = ref(null);
|
||||
const incognitoProcessing = ref(false);
|
||||
|
||||
// Tag Selection
|
||||
const availableTags = ref([]);
|
||||
const selectedTagIds = ref([]);
|
||||
const uploadTagSearchFilter = ref('');
|
||||
|
||||
// Folder Selection
|
||||
const availableFolders = ref([]);
|
||||
const selectedFolderId = ref(null);
|
||||
const foldersEnabled = ref(false);
|
||||
const filterFolder = ref(''); // '' = all, 'none' = no folder, or folder id
|
||||
|
||||
// Speaker Selection
|
||||
const availableSpeakers = ref([]);
|
||||
|
||||
const selectedTags = computed(() => {
|
||||
return selectedTagIds.value.map(tagId =>
|
||||
availableTags.value.find(tag => tag.id == tagId)
|
||||
).filter(Boolean);
|
||||
});
|
||||
|
||||
const filteredAvailableTagsForUpload = computed(() => {
|
||||
const availableForSelection = availableTags.value.filter(tag => !selectedTagIds.value.includes(tag.id));
|
||||
if (!uploadTagSearchFilter.value) return availableForSelection;
|
||||
|
||||
const filter = uploadTagSearchFilter.value.toLowerCase();
|
||||
return availableForSelection.filter(tag =>
|
||||
tag.name.toLowerCase().includes(filter)
|
||||
);
|
||||
});
|
||||
|
||||
const filteredRecordings = computed(() => {
|
||||
return recordings.value;
|
||||
});
|
||||
|
||||
const setGlobalError = (message, duration = 7000) => {
|
||||
globalError.value = message;
|
||||
if (duration > 0) {
|
||||
setTimeout(() => { if (globalError.value === message) globalError.value = null; }, duration);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
// Core
|
||||
currentView,
|
||||
dragover,
|
||||
recordings,
|
||||
selectedRecording,
|
||||
selectedTab,
|
||||
searchQuery,
|
||||
isLoadingRecordings,
|
||||
globalError,
|
||||
setGlobalError,
|
||||
|
||||
// Pagination
|
||||
currentPage,
|
||||
perPage,
|
||||
totalRecordings,
|
||||
totalPages,
|
||||
hasNextPage,
|
||||
hasPrevPage,
|
||||
isLoadingMore,
|
||||
searchDebounceTimer,
|
||||
|
||||
// Search & Organization
|
||||
sortBy,
|
||||
selectedTagFilter,
|
||||
showAdvancedFilters,
|
||||
filterTags,
|
||||
filterSpeakers,
|
||||
filterDateRange,
|
||||
filterDatePreset,
|
||||
filterTextQuery,
|
||||
showArchivedRecordings,
|
||||
showSharedWithMe,
|
||||
|
||||
// App Configuration
|
||||
useAsrEndpoint,
|
||||
connectorSupportsDiarization,
|
||||
connectorSupportsSpeakerCount,
|
||||
currentUserName,
|
||||
canDeleteRecordings,
|
||||
enableInternalSharing,
|
||||
enableArchiveToggle,
|
||||
showUsernamesInUI,
|
||||
|
||||
// Tags
|
||||
availableTags,
|
||||
selectedTagIds,
|
||||
uploadTagSearchFilter,
|
||||
selectedTags,
|
||||
filteredAvailableTagsForUpload,
|
||||
filteredRecordings,
|
||||
|
||||
// Folders
|
||||
availableFolders,
|
||||
selectedFolderId,
|
||||
foldersEnabled,
|
||||
filterFolder,
|
||||
|
||||
// Speakers
|
||||
availableSpeakers,
|
||||
|
||||
// Incognito Mode
|
||||
enableIncognitoMode,
|
||||
incognitoMode,
|
||||
incognitoRecording,
|
||||
incognitoProcessing
|
||||
};
|
||||
}
|
||||
11
static/js/modules/state/index.js
Normal file
11
static/js/modules/state/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* State module exports
|
||||
*/
|
||||
|
||||
export { createCoreState } from './core.js';
|
||||
export { createUIState } from './ui.js';
|
||||
export { createUploadState } from './upload.js';
|
||||
export { createAudioState } from './audio.js';
|
||||
export { createModalState } from './modals.js';
|
||||
export { createChatState } from './chat.js';
|
||||
export { createSharingState } from './sharing.js';
|
||||
193
static/js/modules/state/modals.js
Normal file
193
static/js/modules/state/modals.js
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* Modal state management
|
||||
*/
|
||||
|
||||
export function createModalState(ref, reactive) {
|
||||
// --- Modal Visibility State ---
|
||||
const showEditModal = ref(false);
|
||||
const showDeleteModal = ref(false);
|
||||
const showEditTagsModal = ref(false);
|
||||
const showReprocessModal = ref(false);
|
||||
const showResetModal = ref(false);
|
||||
const showSpeakerModal = ref(false);
|
||||
const speakerModalTab = ref('speakers'); // 'speakers' or 'transcript' for mobile view
|
||||
const showShareModal = ref(false);
|
||||
const showSharesListModal = ref(false);
|
||||
const showTextEditorModal = ref(false);
|
||||
const showAsrEditorModal = ref(false);
|
||||
const showEditSpeakersModal = ref(false);
|
||||
const showEditTextModal = ref(false);
|
||||
const showAddSpeakerModal = ref(false);
|
||||
const showShareDeleteModal = ref(false);
|
||||
const showUnifiedShareModal = ref(false);
|
||||
const showDateTimePicker = ref(false);
|
||||
|
||||
// --- DateTime Picker State ---
|
||||
const pickerMonth = ref(new Date().getMonth());
|
||||
const pickerYear = ref(new Date().getFullYear());
|
||||
const pickerHour = ref(12);
|
||||
const pickerMinute = ref(0);
|
||||
const pickerAmPm = ref('PM');
|
||||
const pickerSelectedDate = ref(null);
|
||||
const dateTimePickerTarget = ref(null); // 'meeting_date' or other field name
|
||||
const dateTimePickerCallback = ref(null); // callback function after applying
|
||||
|
||||
// --- Modal Data State ---
|
||||
const selectedNewTagId = ref('');
|
||||
const tagSearchFilter = ref('');
|
||||
const editingRecording = ref(null);
|
||||
const editingTranscriptionContent = ref('');
|
||||
const editingSegments = ref([]);
|
||||
const availableSpeakers = ref([]);
|
||||
const editingSpeakersList = ref([]);
|
||||
const databaseSpeakers = ref([]);
|
||||
const editingSpeakerSuggestions = ref({});
|
||||
const recordingToDelete = ref(null);
|
||||
const recordingToReset = ref(null);
|
||||
const reprocessType = ref(null);
|
||||
const reprocessRecording = ref(null);
|
||||
const isAutoIdentifying = ref(false);
|
||||
|
||||
const asrReprocessOptions = reactive({
|
||||
language: '',
|
||||
min_speakers: null,
|
||||
max_speakers: null
|
||||
});
|
||||
|
||||
const summaryReprocessPromptSource = ref('default');
|
||||
const summaryReprocessSelectedTagId = ref('');
|
||||
const summaryReprocessCustomPrompt = ref('');
|
||||
const speakerMap = ref({});
|
||||
const regenerateSummaryAfterSpeakerUpdate = ref(true);
|
||||
const speakerSuggestions = ref({});
|
||||
const loadingSuggestions = ref({});
|
||||
const activeSpeakerInput = ref(null);
|
||||
const voiceSuggestions = ref({});
|
||||
const loadingVoiceSuggestions = ref(false);
|
||||
|
||||
// --- Transcript Editing State ---
|
||||
const editingSegmentIndex = ref(null);
|
||||
const editingSpeakerIndex = ref(null);
|
||||
const editedText = ref('');
|
||||
const newSpeakerName = ref('');
|
||||
const newSpeakerIsMe = ref(false);
|
||||
const editedTranscriptData = ref(null);
|
||||
|
||||
// --- Inline Editing State ---
|
||||
const editingParticipants = ref(false);
|
||||
const editingMeetingDate = ref(false);
|
||||
const editingSummary = ref(false);
|
||||
const editingNotes = ref(false);
|
||||
const tempNotesContent = ref('');
|
||||
const tempSummaryContent = ref('');
|
||||
const autoSaveTimer = ref(null);
|
||||
const autoSaveDelay = 2000;
|
||||
|
||||
// --- Markdown Editor State ---
|
||||
const notesMarkdownEditor = ref(null);
|
||||
const markdownEditorInstance = ref(null);
|
||||
const summaryMarkdownEditor = ref(null);
|
||||
const summaryMarkdownEditorInstance = ref(null);
|
||||
const recordingNotesEditor = ref(null);
|
||||
const recordingMarkdownEditorInstance = ref(null);
|
||||
|
||||
// --- Dropdown Positions ---
|
||||
const dropdownPositions = ref({});
|
||||
const editSpeakerDropdownPositions = ref({});
|
||||
|
||||
// --- Single-ref dropdown tracking (performance optimization) ---
|
||||
// Instead of each segment having showSuggestions property (O(n) to close all),
|
||||
// track which dropdown is open with a single ref (O(1) operations)
|
||||
const openAsrDropdownIndex = ref(null);
|
||||
|
||||
return {
|
||||
// Modal visibility
|
||||
showEditModal,
|
||||
showDeleteModal,
|
||||
showEditTagsModal,
|
||||
showReprocessModal,
|
||||
showResetModal,
|
||||
showSpeakerModal,
|
||||
speakerModalTab,
|
||||
showShareModal,
|
||||
showSharesListModal,
|
||||
showTextEditorModal,
|
||||
showAsrEditorModal,
|
||||
showEditSpeakersModal,
|
||||
showEditTextModal,
|
||||
showAddSpeakerModal,
|
||||
showShareDeleteModal,
|
||||
showUnifiedShareModal,
|
||||
showDateTimePicker,
|
||||
|
||||
// DateTime picker
|
||||
pickerMonth,
|
||||
pickerYear,
|
||||
pickerHour,
|
||||
pickerMinute,
|
||||
pickerAmPm,
|
||||
pickerSelectedDate,
|
||||
dateTimePickerTarget,
|
||||
dateTimePickerCallback,
|
||||
|
||||
// Modal data
|
||||
selectedNewTagId,
|
||||
tagSearchFilter,
|
||||
editingRecording,
|
||||
editingTranscriptionContent,
|
||||
editingSegments,
|
||||
availableSpeakers,
|
||||
editingSpeakersList,
|
||||
databaseSpeakers,
|
||||
editingSpeakerSuggestions,
|
||||
recordingToDelete,
|
||||
recordingToReset,
|
||||
reprocessType,
|
||||
reprocessRecording,
|
||||
isAutoIdentifying,
|
||||
asrReprocessOptions,
|
||||
summaryReprocessPromptSource,
|
||||
summaryReprocessSelectedTagId,
|
||||
summaryReprocessCustomPrompt,
|
||||
speakerMap,
|
||||
regenerateSummaryAfterSpeakerUpdate,
|
||||
speakerSuggestions,
|
||||
loadingSuggestions,
|
||||
activeSpeakerInput,
|
||||
voiceSuggestions,
|
||||
loadingVoiceSuggestions,
|
||||
|
||||
// Transcript editing
|
||||
editingSegmentIndex,
|
||||
editingSpeakerIndex,
|
||||
editedText,
|
||||
newSpeakerName,
|
||||
newSpeakerIsMe,
|
||||
editedTranscriptData,
|
||||
|
||||
// Inline editing
|
||||
editingParticipants,
|
||||
editingMeetingDate,
|
||||
editingSummary,
|
||||
editingNotes,
|
||||
tempNotesContent,
|
||||
tempSummaryContent,
|
||||
autoSaveTimer,
|
||||
autoSaveDelay,
|
||||
|
||||
// Markdown editors
|
||||
notesMarkdownEditor,
|
||||
markdownEditorInstance,
|
||||
summaryMarkdownEditor,
|
||||
summaryMarkdownEditorInstance,
|
||||
recordingNotesEditor,
|
||||
recordingMarkdownEditorInstance,
|
||||
|
||||
// Dropdown positions
|
||||
dropdownPositions,
|
||||
editSpeakerDropdownPositions,
|
||||
|
||||
// Single-ref dropdown tracking
|
||||
openAsrDropdownIndex
|
||||
};
|
||||
}
|
||||
39
static/js/modules/state/pwa.js
Normal file
39
static/js/modules/state/pwa.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* PWA state management
|
||||
*/
|
||||
|
||||
export function createPWAState(ref) {
|
||||
// --- Install Prompt ---
|
||||
const deferredInstallPrompt = ref(null);
|
||||
const showInstallButton = ref(false);
|
||||
const isPWAInstalled = ref(false);
|
||||
|
||||
// --- Notifications ---
|
||||
const notificationPermission = ref('default');
|
||||
const pushSubscription = ref(null);
|
||||
|
||||
// --- Badging ---
|
||||
const appBadgeCount = ref(0);
|
||||
|
||||
// --- Media Session ---
|
||||
const currentMediaMetadata = ref(null);
|
||||
const isMediaSessionActive = ref(false);
|
||||
|
||||
return {
|
||||
// Install prompt
|
||||
deferredInstallPrompt,
|
||||
showInstallButton,
|
||||
isPWAInstalled,
|
||||
|
||||
// Notifications
|
||||
notificationPermission,
|
||||
pushSubscription,
|
||||
|
||||
// Badging
|
||||
appBadgeCount,
|
||||
|
||||
// Media session
|
||||
currentMediaMetadata,
|
||||
isMediaSessionActive
|
||||
};
|
||||
}
|
||||
66
static/js/modules/state/sharing.js
Normal file
66
static/js/modules/state/sharing.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Sharing state management
|
||||
*/
|
||||
|
||||
export function createSharingState(ref, reactive) {
|
||||
// --- Public Sharing State ---
|
||||
const recordingToShare = ref(null);
|
||||
const shareOptions = reactive({
|
||||
share_summary: true,
|
||||
share_notes: true,
|
||||
});
|
||||
const generatedShareLink = ref('');
|
||||
const existingShareDetected = ref(false);
|
||||
const userShares = ref([]);
|
||||
const isLoadingShares = ref(false);
|
||||
const shareToDelete = ref(null);
|
||||
|
||||
// --- Internal Sharing State ---
|
||||
const internalShareUserSearch = ref('');
|
||||
const internalShareSearchResults = ref([]);
|
||||
const internalShareRecording = ref(null);
|
||||
const internalSharePermissions = ref({ can_edit: false, can_reshare: false });
|
||||
const recordingInternalShares = ref([]);
|
||||
const isLoadingInternalShares = ref(false);
|
||||
const isSearchingUsers = ref(false);
|
||||
const allUsers = ref([]);
|
||||
const isLoadingAllUsers = ref(false);
|
||||
|
||||
// --- Audio Player State ---
|
||||
const playerVolume = ref(1.0);
|
||||
const audioIsPlaying = ref(false);
|
||||
const audioCurrentTime = ref(0);
|
||||
const audioDuration = ref(0);
|
||||
const audioIsMuted = ref(false);
|
||||
const audioIsLoading = ref(false);
|
||||
|
||||
return {
|
||||
// Public sharing
|
||||
recordingToShare,
|
||||
shareOptions,
|
||||
generatedShareLink,
|
||||
existingShareDetected,
|
||||
userShares,
|
||||
isLoadingShares,
|
||||
shareToDelete,
|
||||
|
||||
// Internal sharing
|
||||
internalShareUserSearch,
|
||||
internalShareSearchResults,
|
||||
internalShareRecording,
|
||||
internalSharePermissions,
|
||||
recordingInternalShares,
|
||||
isLoadingInternalShares,
|
||||
isSearchingUsers,
|
||||
allUsers,
|
||||
isLoadingAllUsers,
|
||||
|
||||
// Audio player
|
||||
playerVolume,
|
||||
audioIsPlaying,
|
||||
audioCurrentTime,
|
||||
audioDuration,
|
||||
audioIsMuted,
|
||||
audioIsLoading
|
||||
};
|
||||
}
|
||||
109
static/js/modules/state/ui.js
Normal file
109
static/js/modules/state/ui.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* UI state management
|
||||
*/
|
||||
|
||||
export function createUIState(ref, computed) {
|
||||
// --- UI State ---
|
||||
const browser = ref('unknown');
|
||||
const isSidebarCollapsed = ref(false);
|
||||
const searchTipsExpanded = ref(false);
|
||||
const isUserMenuOpen = ref(false);
|
||||
const isDarkMode = ref(false);
|
||||
const currentColorScheme = ref('blue');
|
||||
const showColorSchemeModal = ref(false);
|
||||
const windowWidth = ref(window.innerWidth);
|
||||
const mobileTab = ref('transcript');
|
||||
const isMetadataExpanded = ref(false);
|
||||
const expandedSection = ref('settings'); // 'notes' or 'settings'
|
||||
|
||||
// --- i18n State ---
|
||||
const currentLanguage = ref('en');
|
||||
const currentLanguageName = ref('English');
|
||||
const availableLanguages = ref([]);
|
||||
const showLanguageMenu = ref(false);
|
||||
|
||||
// --- Column Resizing State ---
|
||||
const leftColumnWidth = ref(60);
|
||||
const rightColumnWidth = ref(40);
|
||||
const isResizing = ref(false);
|
||||
|
||||
// --- Transcription State ---
|
||||
const transcriptionViewMode = ref('simple');
|
||||
const legendExpanded = ref(false);
|
||||
const highlightedSpeaker = ref(null);
|
||||
const processingIndicatorMinimized = ref(false);
|
||||
|
||||
// --- Virtual Scroll State ---
|
||||
// For transcript panel virtual scrolling (performance optimization for long transcriptions)
|
||||
const transcriptScrollTop = ref(0);
|
||||
const transcriptContainerHeight = ref(0);
|
||||
const transcriptItemHeight = 48; // Estimated height per segment in pixels
|
||||
|
||||
// --- Computed Properties ---
|
||||
const isMobileScreen = computed(() => {
|
||||
return windowWidth.value < 1024;
|
||||
});
|
||||
|
||||
// --- Color Scheme Definitions ---
|
||||
const colorSchemes = {
|
||||
light: [
|
||||
{ id: 'blue', name: 'Ocean Blue', description: 'Classic blue theme with professional appeal', class: '' },
|
||||
{ id: 'emerald', name: 'Forest Emerald', description: 'Fresh green theme for a natural feel', class: 'theme-light-emerald' },
|
||||
{ id: 'purple', name: 'Royal Purple', description: 'Elegant purple theme with sophistication', class: 'theme-light-purple' },
|
||||
{ id: 'rose', name: 'Sunset Rose', description: 'Warm pink theme with gentle energy', class: 'theme-light-rose' },
|
||||
{ id: 'amber', name: 'Golden Amber', description: 'Warm yellow theme for brightness', class: 'theme-light-amber' },
|
||||
{ id: 'teal', name: 'Ocean Teal', description: 'Cool teal theme for tranquility', class: 'theme-light-teal' }
|
||||
],
|
||||
dark: [
|
||||
{ id: 'blue', name: 'Midnight Blue', description: 'Deep blue theme for focused work', class: '' },
|
||||
{ id: 'emerald', name: 'Dark Forest', description: 'Rich green theme for comfortable viewing', class: 'theme-dark-emerald' },
|
||||
{ id: 'purple', name: 'Deep Purple', description: 'Mysterious purple theme for creativity', class: 'theme-dark-purple' },
|
||||
{ id: 'rose', name: 'Dark Rose', description: 'Muted pink theme with subtle warmth', class: 'theme-dark-rose' },
|
||||
{ id: 'amber', name: 'Dark Amber', description: 'Warm brown theme for cozy sessions', class: 'theme-dark-amber' },
|
||||
{ id: 'teal', name: 'Deep Teal', description: 'Dark teal theme for calm focus', class: 'theme-dark-teal' }
|
||||
]
|
||||
};
|
||||
|
||||
return {
|
||||
// UI
|
||||
browser,
|
||||
isSidebarCollapsed,
|
||||
searchTipsExpanded,
|
||||
isUserMenuOpen,
|
||||
isDarkMode,
|
||||
currentColorScheme,
|
||||
showColorSchemeModal,
|
||||
windowWidth,
|
||||
mobileTab,
|
||||
isMetadataExpanded,
|
||||
expandedSection,
|
||||
|
||||
// i18n
|
||||
currentLanguage,
|
||||
currentLanguageName,
|
||||
availableLanguages,
|
||||
showLanguageMenu,
|
||||
|
||||
// Column Resizing
|
||||
leftColumnWidth,
|
||||
rightColumnWidth,
|
||||
isResizing,
|
||||
|
||||
// Transcription
|
||||
transcriptionViewMode,
|
||||
legendExpanded,
|
||||
highlightedSpeaker,
|
||||
processingIndicatorMinimized,
|
||||
|
||||
// Virtual Scroll
|
||||
transcriptScrollTop,
|
||||
transcriptContainerHeight,
|
||||
transcriptItemHeight,
|
||||
|
||||
// Computed
|
||||
isMobileScreen,
|
||||
|
||||
// Constants
|
||||
colorSchemes
|
||||
};
|
||||
}
|
||||
77
static/js/modules/state/upload.js
Normal file
77
static/js/modules/state/upload.js
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Upload state management
|
||||
*/
|
||||
|
||||
export function createUploadState(ref, computed) {
|
||||
// --- Upload State ---
|
||||
const uploadQueue = ref([]);
|
||||
const currentlyProcessingFile = ref(null);
|
||||
const processingProgress = ref(0);
|
||||
const processingMessage = ref('');
|
||||
const isProcessingActive = ref(false);
|
||||
const pollInterval = ref(null);
|
||||
const progressPopupMinimized = ref(false);
|
||||
const progressPopupClosed = ref(false);
|
||||
const maxFileSizeMB = ref(250);
|
||||
const chunkingEnabled = ref(true);
|
||||
const chunkingMode = ref('size');
|
||||
const chunkingLimit = ref(20);
|
||||
const chunkingLimitDisplay = ref('20MB');
|
||||
const maxConcurrentUploads = ref(3);
|
||||
const recordingDisclaimer = ref('');
|
||||
const showRecordingDisclaimerModal = ref(false);
|
||||
const pendingRecordingMode = ref(null);
|
||||
|
||||
// Advanced Options for ASR
|
||||
const showAdvancedOptions = ref(false);
|
||||
const uploadLanguage = ref('');
|
||||
const uploadMinSpeakers = ref('');
|
||||
const uploadMaxSpeakers = ref('');
|
||||
const uploadHotwords = ref('');
|
||||
const uploadInitialPrompt = ref('');
|
||||
|
||||
// --- Computed Properties ---
|
||||
const totalInQueue = computed(() => uploadQueue.value.length);
|
||||
const completedInQueue = computed(() => uploadQueue.value.filter(item => item.status === 'completed' || item.status === 'failed').length);
|
||||
const finishedFilesInQueue = computed(() => uploadQueue.value.filter(item => ['completed', 'failed'].includes(item.status)));
|
||||
|
||||
const clearCompletedUploads = () => {
|
||||
uploadQueue.value = uploadQueue.value.filter(item => !['completed', 'failed'].includes(item.status));
|
||||
};
|
||||
|
||||
return {
|
||||
uploadQueue,
|
||||
currentlyProcessingFile,
|
||||
processingProgress,
|
||||
processingMessage,
|
||||
isProcessingActive,
|
||||
pollInterval,
|
||||
progressPopupMinimized,
|
||||
progressPopupClosed,
|
||||
maxFileSizeMB,
|
||||
chunkingEnabled,
|
||||
chunkingMode,
|
||||
chunkingLimit,
|
||||
chunkingLimitDisplay,
|
||||
maxConcurrentUploads,
|
||||
recordingDisclaimer,
|
||||
showRecordingDisclaimerModal,
|
||||
pendingRecordingMode,
|
||||
|
||||
// Advanced Options
|
||||
showAdvancedOptions,
|
||||
uploadLanguage,
|
||||
uploadMinSpeakers,
|
||||
uploadMaxSpeakers,
|
||||
uploadHotwords,
|
||||
uploadInitialPrompt,
|
||||
|
||||
// Computed
|
||||
totalInQueue,
|
||||
completedInQueue,
|
||||
finishedFilesInQueue,
|
||||
|
||||
// Methods
|
||||
clearCompletedUploads
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user