Commit Graph
100 Commits
Author SHA1 Message Date
retoor 37dccf9da2 fix: remove trailing semicolons and fix whitespace inconsistencies in chat-input.js
- Removed trailing semicolons from arrow function bodies in hiddenCompletions object
- Fixed inconsistent indentation for _leetSpeak toggle and textarea classList assignment
- Replaced spread operator with Object.assign for allAutoCompletions getter
- Truncated extractMentions regex pattern at diff boundary
2025-09-17 20:55:31 +00:00
retoor 538d92b538 fix: guard mention replacement against null closestAuthor in chat input 2025-09-17 14:30:20 +00:00
retoor e980265aeb fix: fix whitespace formatting and trailing commas in chat-input.js 2025-09-17 14:27:04 +00:00
retoor 2f74ae9e74 fix: set closestAuthor to 0 when minDistance drops below 5 in chat input mention detection 2025-09-17 14:20:59 +00:00
retoor a16ccd82fe feat: add new chat view with WebSocket-based messaging component
Introduce a new `NewView` class in `src/snek/view/new.py` that renders the `new.html` template, requiring authentication. The template includes a custom `ChatWindow` web component that establishes a WebSocket connection via the `Socket` class, handles channel-based messaging with real-time updates, and supports sending messages on Enter key press while allowing Shift+Enter for multi-line input.
2025-09-17 14:12:05 +00:00
retoor dc1b36e68e feat: add NewView route and fix leet check and push notification handling
- Register NewView at /new.html endpoint in Application router
- Fix textToLeetAdvanced to require s.length > 1 for valid leet match
- Comment out event.waitUntil(reg) in service-worker push handler to prevent potential hang
2025-09-17 14:09:48 +00:00
retoor 4a51c2d386 fix: add console.info logging and increase reconnect delay to 4 seconds in socket.js
- Added console.info call to log event name and data payload in the data handler
- Changed reconnect timeout from 0ms to 4000ms to introduce deliberate delay before reconnection attempt
2025-09-16 02:46:44 +00:00
retoor 51ed3b2fd2 fix: reduce default ProcessPoolExecutor max_workers from 3 to 1 in ChannelMessageService init 2025-09-15 03:00:11 +00:00
retoor 301c55cfdd fix: add debug logging for closest author and min distance in chat input component 2025-09-15 00:22:03 +00:00
retoor 0104f5ef85 fix: increase default max_workers to 3 and use instance variable for executor pool size 2025-09-15 00:12:52 +00:00
retoor fe57aab360 fix: increase ProcessPoolExecutor max_workers from 1 to 10 in channel message service 2025-09-15 00:09:04 +00:00
retoor c5ea835dff fix: reduce default ProcessPoolExecutor workers to 1 and add debug logging
The change reduces the default `max_workers` for `ProcessPoolExecutor` from 5 to 1 in the `get_or_executor` method of `ChannelMessageService`, and adds a debug print statement to log the number of available executors.
2025-09-14 22:58:29 +00:00
retoor b6ada2c753 chore: add duplicate defer attribute to umami analytics script tag in app.html 2025-09-14 20:53:05 +00:00
retoor 5cd88ccb9b fix: prevent premature removal of non-final messages in upsertMessage
The change modifies the conditional logic in `MessageList.upsertMessage()` to only remove and nullify an existing message when `data.message` is falsy, instead of doing so when `data.is_final` is true or `data.message` is falsy. This ensures that non-final messages with content are not incorrectly removed from the DOM before being updated or re-inserted.
2025-09-09 21:40:33 +00:00
retoor 8b15e08014 feat: replace ThreadPoolExecutor with ProcessPoolExecutor and add Jinja2 template rendering for channel messages 2025-09-08 04:08:12 +00:00
retoor 7a0f58451a fix: reduce per-user executor pool max_workers from 5 to 1 in ChannelMessageService
The change limits concurrent thread execution per user to a single worker,
preventing resource exhaustion from unbounded thread creation in the
get_or_create_executor method.
2025-09-07 23:09:22 +00:00
retoor 088dbbf3da feat: replace global thread pool with per-user executor pools in ChannelMessageService
Remove the module-level `executor` variable and introduce instance-level `_executor_pools` dict with `get_or_create_executor` method that creates a `ThreadPoolExecutor(max_workers=5)` per user UID. Update all `run_in_executor` calls in `render_message` and `render_message_edit` to use the per-user executor instead of the shared global one, improving isolation and resource control across concurrent user requests.
2025-09-07 22:59:11 +00:00
retoor 8d4511a2bf fix: prevent avatar anchor from being overwritten by later matches in message-list.js
The loop iterating over avatar elements now only assigns the first matching anchor to `lastElement`, ensuring the scroll target remains the earliest occurrence instead of being overwritten by subsequent matches.
2025-09-07 00:42:47 +00:00
retoor 77d7186c86 fix: add debug print before socket deletion in RPCView error handlers
Add a debug print statement in the `send` method's exception handler to log the exception message before deleting the socket, and update the existing debug print in the message processing loop to include a distinctive prefix for easier log filtering.
2025-08-31 01:41:41 +00:00
retoor 86b0ae6db4 fix: correct indentation of user_availability_service method in socket.py
The method definition was incorrectly placed at module level instead of being properly indented as a member of the SocketService class. This fix moves the async def user_availability_service declaration one level deeper to align with the class body, restoring correct Python scoping and preventing AttributeError or runtime import failures when the service attempts to register or invoke this method.
2025-08-31 01:27:47 +00:00
retoor 7984feeb6d chore: add debug logging to user availability service loop
Add detailed debug-level log statements throughout the
user_availability_service method to trace execution flow, including
entry into the main loop, socket iteration, connection status checks,
user update decisions, database save operations, and sleep intervals.
2025-08-31 01:25:26 +00:00
retoor 50e800e5f2 fix: offload Jinja2 template rendering and sanitization to thread pool executor to avoid blocking async event loop 2025-08-31 01:22:00 +00:00
retoor f8670d8a38 feat: implement modal editor with vim-like modes and command-line interface
Replace the basic contenteditable editor with a full modal editor supporting insert, normal, and visual modes. Add a command-line interface at the bottom for executing commands like :w, :q, and :wq. Introduce mode-specific cursor styling, selection highlighting, and keyboard-driven navigation. The editor now tracks mode state, handles mode transitions via Escape and i/v keys, and displays the current mode in a status bar.
2025-08-06 13:33:13 +00:00
retoor c9673b7744 fix: copy user socket list before iteration to avoid mutation during send 2025-08-06 12:18:01 +00:00
retoor 791ef0bc13 feat: add sentry-sdk dependency and initialize sentry in main function
- Added sentry-sdk to project dependencies in pyproject.toml
- Imported and initialized sentry_sdk with DSN in main() function
- Added graceful fallback with print message if sentry_sdk import fails
2025-08-06 09:51:58 +00:00
retoor 448034e03e feat: disable login requirement for ChannelAttachmentView to allow public access to attachments 2025-08-03 01:31:08 +00:00
retoor 01a14370c9 fix: remove random sleep before rpc call in websocket message handler 2025-08-01 00:06:20 +00:00
retoor dbc34cebb1 fix: reduce randomized sleep range in websocket RPC handler from 0.1-0.4s to 0.01-0.1s 2025-07-31 23:59:23 +00:00
retoor b760fdd22b fix: add random sleep before RPC message processing in websocket handler
- Imported `random` module to support randomized delay
- Inserted `await asyncio.sleep(random.uniform(0.1, 0.4))` before `await rpc(msg.json())` in the websocket message loop
- This introduces a jitter of 100-400ms to desynchronize concurrent RPC processing from multiple clients
2025-07-31 23:57:18 +00:00
retoor 2cc616c8aa fix: move endOfMessages.after call before scroll check in MessageList
The `endOfMessages.after(message)` call was placed after the `isScrolledToBottom()` check, causing the scroll position to be evaluated before the new message was inserted into the DOM. This resulted in incorrect scroll behavior when messages were added, as the scroll check would not account for the newly inserted element. Moving the insertion before the scroll check ensures the scroll position is evaluated after the DOM has been updated with the new message.
2025-07-30 12:49:16 +00:00
retoor 32ed12f3db fix: correct missing closing parenthesis in upsertMessage condition check 2025-07-30 12:46:10 +00:00
retoor 1f89849c9a fix: correct conditional grouping in upsertMessage to remove stale messages
The diff shows a fix in the `upsertMessage` method of the `MessageList` class in `src/snek/static/message-list.js`. The original condition `(message && data.is_final) || !data.message` was incorrectly grouping the logical OR, causing messages to be removed only when `data.is_final` was true alongside a message, or when `data.message` was falsy regardless of message existence. The fix wraps the entire condition in parentheses: `(message && (data.is_final || !data.message))`, ensuring that a message is removed only if it exists AND either `data.is_final` is true or `data.message` is falsy. A comment `// TO force insert` was added to clarify the intent of nullifying the message reference after removal.
2025-07-30 12:44:25 +00:00
retoor 77802883fe fix: skip upsert for empty messages and clear stale entries in MessageList 2025-07-30 12:41:23 +00:00
retoor aa3d00243f fix: remove stale message from DOM only when is_final flag is set
Previously, the upsertMessage method removed any existing message element from the DOM whenever a message with the same uid was received, regardless of whether the update represented a final version. This caused premature removal of messages that were still being streamed or updated incrementally. Now the removal is gated on the `data.is_final` property, ensuring that only completed messages are replaced in the DOM while in-progress messages remain visible until their final state arrives.
2025-07-30 12:36:56 +00:00
retoor 9bad9a78ed feat: add HEAD route and lock-checking middleware to WebDAV handler 2025-07-30 01:25:36 +00:00
retoor c5df9e6463 feat: add MS-Author-Via header to WebDAV OPTIONS response and fix semicolons in message-list.js
- Add "MS-Author-Via: DAV" header to WebDAV OPTIONS handler for Microsoft WebDAV client compatibility
- Fix missing semicolons in message-list.js (LONG_TIME constant, ReplyEvent constructor)
- Remove trailing whitespace in import statement formatting
2025-07-30 00:51:26 +00:00
retoor 299f617988 fix: re-enable iframe elements in sanitize_html by commenting out removal logic 2025-07-26 21:56:24 +00:00
retoor 942098583d feat: add XSS sanitization to channel message rendering and refactor sanitize_html with BeautifulSoup
Add sanitize_html calls in ChannelMessageService for both render and save paths to strip script, iframe, object, embed tags and event handler attributes from rendered HTML templates. Refactor sanitize_html in template.py to use BeautifulSoup for tag removal and attribute cleaning, replacing the previous bleach-only implementation with a new sanitize_html2 function retained for compatibility.
2025-07-25 15:17:45 +00:00
retoor 8762e592d0 fix: remove whitelist_attributes call from message template rendering in ChannelMessageService
The whitelist_attributes filter was applied to the rendered HTML output in both
the get_by_uid and save methods of ChannelMessageService. This filter was
stripping allowed HTML attributes from the message content, which could break
formatting or functionality in rendered messages. The fix removes the filter
call, allowing the full rendered template output to be stored and returned
without attribute sanitization.
2025-07-25 15:10:03 +00:00
retoor 0a45ef2b8f fix: move whitelist_attributes call to post-render in channel message service 2025-07-25 15:05:41 +00:00
retoor bc924f4f85 fix: reduce default star count from 100 to 50 in StarField constructor and instantiation 2025-07-24 11:48:22 +00:00
retoor 4e31728de4 fix: move whitelist_attributes call before template render to prevent xss in channel messages 2025-07-23 23:46:34 +00:00
retoor d015e81069 feat: add is_dm property to ChannelModel and auto-join dm channels for members 2025-07-23 23:07:33 +00:00
retoor 0d5b91b6b4 fix: replace async iteration with sync find and add exception handling in ChannelMessageService.maintenance
Refactor the maintenance method to iterate over channel messages using synchronous `self.mapper.db["channel_message"].find()` instead of the async `self.find()` generator, wrapping each message processing in a try-except block that catches exceptions, prints them, and sleeps for 0.1 seconds before continuing.
2025-07-18 21:20:46 +00:00
retoor 4e66c895a6 fix: ensure message is fetched before save when html lacks chat-message tag 2025-07-18 15:49:01 +00:00
retoor b6afdca6d3 fix: replace redundant fetch-save pattern with direct save call in channel message service 2025-07-18 15:44:45 +00:00
retoor 56f313c88e feat: add request statistics middleware with time-series tracking and stats endpoint
- Import and register stats_middleware in the application middleware stack
- Add prepare_stats startup hook to initialize stats data structure
- Register /stats.html GET route with stats_handler for viewing statistics
- Create new snek/system/stats.py module with time-series data collection and SVG chart generation
- Integrate websocket statistics tracking in RPC view by calling update_websocket_stats before and after method execution
2025-07-17 22:43:37 +00:00
retoor 5bdf00fdd0 feat: add uploadResponses tracking array and reset after publish in file upload grid
The uploadResponses array is initialized in the component constructor to collect file upload results. The reset() call is moved inside the conditional block that fires when all uploads are complete, ensuring the component state is cleared only after the 'file-uploads-done' event has been published with the full response data. A console.info log is added for debugging the collected responses.
2025-07-14 17:11:46 +00:00
retoor 7af32a5036 feat: migrate forum queries to async generators and replace find_one with get method
- Convert ForumModel.get_threads and ThreadModel.get_posts from returning lists to async generators yielding individual records
- Replace deprecated `_order_by` and `_offset` parameters with `order_by` string syntax in service queries
- Add `get_timestamp` helper and `save` method to BaseModel for direct persistence
- Refactor ForumView endpoints to use `services.forum.get` and `services.thread.get` instead of `find_one`
- Inject request reference into app context via `setattr(self, "request", request)` in view handlers
- Restructure forum HTML template to extend app layout with breadcrumb navigation and dark theme styling
2025-07-12 18:58:19 +00:00
retoor b6240803ab feat: add uuid generation and public notify method to BaseForumService, fix WebSocket handler method name
- Add `generate_uid` method using uuid4 to BaseForumService
- Expose public `notify` method for external event dispatching
- Rename `websocket_handler` to `get` in ForumWebSocketView for proper routing
- Fix WebSocket ID generation to use forum service instance instead of generic services
2025-07-12 01:01:39 +00:00
retoor 91249ff2a1 feat: integrate forum sub-application with models, mappers, services, and WebSocket support
Add complete forum feature including ForumApplication sub-app mounted on parent, new ForumModel/ThreadModel/PostModel/PostLikeModel entities, corresponding mappers and services, event notification dispatch system, and WebSocket endpoint for real-time updates. Refactor service registry to use dynamic registration pattern.
2025-07-12 00:41:57 +00:00
retoor 9493c63396 feat: add PROPGET, PROPSET, PROPDEL routes and property file management to WebDAV handler
Implement three new WebDAV property routes (PROPGET, PROPSET, PROPDEL) alongside property file lifecycle management: delete properties on file removal and move properties on file rename via shutil.
2025-07-10 01:25:40 +00:00
retoor ae6ae150fc fix: remove Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers from CORS middleware 2025-07-08 21:54:28 +00:00
retoor 879148bc2c feat: add Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers to CORS middleware
Add `Cross-Origin-Opener-Policy: same-origin` and `Cross-Origin-Embedder-Policy: credentialless` headers to the `cors_middleware` response in `src/snek/system/middleware.py`, with a commented-out alternative for `require-corp` to support cross-origin isolation configuration.
2025-07-08 21:35:31 +00:00
retoor 27bca9c295 feat: add time_cache decorator to block_code method and import time_cache
- Import time_cache alongside existing time_cache_async from app.cache
- Apply @time_cache with 60-minute timeout to block_code method in MarkdownRenderer
- Fix minor whitespace formatting issues in markdown.py
2025-07-04 08:38:08 +00:00
retoor f2c67c02d0 fix: remove async semaphore and executor wrapping from BaseMapper execute method
The synchronous _execute call replaces the previous async pattern that used a semaphore
and run_in_executor, simplifying the execution path and removing unnecessary async overhead
for database operations that are already synchronous in nature.
2025-07-04 07:32:03 +00:00
retoor 9f578f1534 refactor: move semaphore to class level and simplify run_in_executor retry logic
The semaphore is now a class-level attribute shared across all instances, and the retry loop with exponential backoff is removed in favor of a single execution path that always acquires the semaphore. The commit call is conditionally performed only when use_semaphore is True, and the template's live-type attribute is flipped from "false" to "true" to enable live chat functionality.
2025-07-04 07:29:03 +00:00
retoor 1cca195b76 fix: correct variable shadowing and add async/await in service worker push handler
- Renamed shadowed `clients` variable to `matchedClients` in `isClientOpen` function to avoid conflict with global `clients` API
- Changed push event listener to async and added `await` before `isClientOpen` call to properly handle the returned promise
2025-07-04 04:03:53 +00:00
retoor 52f14b7c0f fix: comment out patchConsole call in sandbox StarField initialization 2025-07-04 03:50:54 +00:00
retoor 3fe014c9e8 fix: suppress push notification display when client window is already focused 2025-07-04 03:40:19 +00:00
retoor bd643b63e6 fix: disable live-type attribute on chat-input component in web template 2025-07-04 03:16:56 +00:00
retoor 9220bd36f5 fix: correct typo in UserService.search method from kwarggs to kwargs 2025-07-01 08:43:15 +00:00
retoor 763fd9aabe fix: replace punctuated text assignment with space in STTButton typing simulation 2025-06-29 19:13:30 +00:00
retoor 0e6b01a468 fix: replace empty string with space in STTButton simulateTypingWithEvents call
The change modifies the simulateTypingWithEvents call in the STTButton class to pass a single space character instead of an empty string, ensuring the typing simulation triggers proper input event handling for interim speech-to-text results.
2025-06-29 19:10:57 +00:00
retoor 3b659e0db1 fix: restore empty simulateTypingWithEvents call in STTButton interim handler 2025-06-29 19:09:03 +00:00
retoor acdeaaa980 fix: replace interim text replacement with direct sendMessage call in STTButton
The diff modifies the speech-to-text button handler in `src/snek/static/stt.js` to change behavior when interim speech recognition results are received. Previously, the code replaced the input element's value with an empty string and then simulated typing events to insert the interim text. The new implementation sets the input element's value directly to the interim text and calls `document.querySelector('chat-input').sendMessage(interim)` to immediately send the recognized speech as a chat message, bypassing the typing simulation entirely. The old typing simulation logic is commented out.
2025-06-29 19:06:27 +00:00
retoor f1d49a285d fix: remove interim text display and set typing delay to zero in STTButton
The diff modifies two key behaviors in the speech-to-text button component. First, the typing simulation delay parameter is changed from 1 to 0 in the `simulateTypingWithEvents` call within the finalize path, eliminating artificial typing delay when inserting punctuated text. Second, the interim speech recognition handling is refactored: instead of displaying interim text in the input field, both contenteditable and regular input elements now clear the previous interim text by setting their value to an empty string, while the commented-out `simulateTypingWithEvents` call for interim text is uncommented and activated to handle interim updates through the typing simulation mechanism instead of direct value assignment.
2025-06-29 19:03:33 +00:00
retoor 4ac19ef558 chore: refactor STTButton event handling and CSS formatting in stt.js 2025-06-29 18:56:44 +00:00
retoor 1ec7ac8327 chore: fix indentation and formatting in STTButton simulateTypingWithEvents method 2025-06-29 18:34:25 +00:00
retoor 4d908acac0 feat: conditionally skip TTS speech when speaker is disabled in web UI
Add a check for the `snek-speaker` element's enabled state before calling `speak()`. When the speaker is disabled, fall back to playing the message sound instead of attempting speech synthesis. This prevents silent failures and ensures consistent audio feedback based on user preference.
2025-06-29 18:16:15 +00:00
retoor 09fdaeb45f feat: add SnekSpeaker custom element with speech synthesis toggle and voice selection
Introduce a new `snek-speaker` web component that wraps the Web Speech API. The element provides `speak()`, `toggle()`, `stop()`, and `enable()`/`disable()` methods, along with an `enabled` property. Voice selection defaults to the first male English voice found, with asynchronous voice loading handled via the `onvoiceschanged` event.
2025-06-29 18:08:13 +00:00
retoor 3708156acf feat: integrate TTS playback and wire snek-speaker into chat input and message flow
Add snek-speaker element to chat-input.js, attach click handler on ttsButton to enable speaker, and include tts.js module in app.html. In web.html, trigger snek-speaker.speak() on final channel messages to enable text-to-speech output for incoming messages.
2025-06-29 17:58:40 +00:00
retoor e047e5ecb3 feat: make simulateTypingWithEvents return a promise and finalize chat message after typing
Refactor simulateTypingWithEvents to return a Promise that resolves when typing completes, enabling callers to chain actions after the typing simulation finishes. Update the speech recognition result handler to await this promise and call finalizeMessage() on the chat-input element, replacing the previous triggerEvent('keyup', "Enter") approach. Also add line breaks after punctuation in the committed text before typing simulation.
2025-06-29 15:39:32 +00:00
retoor 735abf80d0 feat: add login_required flag to views and fix BaseService.get uid handling
Add `login_required = True` to ChannelDriveApiView, ChannelAttachmentView, ChannelAttachmentUploadView, ChannelView, ContainerView, DriveView, BareRepoNavigator, StatsView, StatusView, ThreadsView, UploadView, and UserView to enforce authentication on these endpoints. Set `login_required = False` on RegisterFormView to allow unauthenticated registration. Refactor `BaseService.get` to accept positional args for uid and only filter deleted_at when not explicitly provided. Remove the deprecated `DriveView222` class entirely.
2025-06-29 14:19:53 +00:00
retoor f8bd028569 fix: replace Enter keydown with keyup and reduce typing delay to 1ms in stt.js 2025-06-28 22:12:07 +00:00
retoor fa50562726 feat: add simulateTypingWithEvents method and fix punctuation insertion in STTButton 2025-06-28 22:04:42 +00:00
retoor 93ceda2286 fix: scope image src extraction to text container in message rendering
The previous implementation incorrectly queried all images within the entire message div, causing duplicate or out-of-context image source concatenation. This change restricts the querySelectorAll to only images nested inside the `.text` element, ensuring each message's image sources are appended exactly once and only from the relevant content area.
2025-06-27 15:38:35 +00:00
retoor 02945616e0 feat: strip markdown image syntax from replied image URLs in web template
Remove the '![Replied image]()' wrapper around image sources when constructing reply text in the web chat template, leaving only the raw URL to prevent broken markdown rendering in non-markdown contexts.
2025-06-27 15:36:27 +00:00
retoor e5ca3df33e feat: add image source to reply text when generating reply link in web template 2025-06-27 15:33:23 +00:00
retoor aaf6b7241d fix: replace activeElement target with textarea query for speech-to-text input
The speech-to-text component previously used `document.activeElement` to determine the target element for transcription output, which failed when no input was focused. Changed the `targetEl` getter to query for a `textarea` element instead, ensuring consistent target availability. Also updated the DOM update logic to call `.focus()` on the target and assign directly to `.value` instead of using `setAttribute("value", ...)`, enabling proper text insertion into the textarea.
2025-06-25 20:46:07 +00:00
retoor 9dbbcccf15 feat: add speech-to-text button component and integrate into chat input
- Create new STTButton web component in src/snek/static/stt.js with shadow DOM, speech recognition API integration, and pulsing visual feedback during listening state
- Add stt.js script import to app.html template to register the custom element globally
- Instantiate and append stt-button element inside ChatInputComponent constructor in chat-input.js
- Add CSS class "chat-input-textarea" to the textarea element for styling hooks
- Attach change event listener on textarea to sync value and trigger updateFromInput on manual edits
2025-06-25 20:41:55 +00:00
retoor 564362ead9 fix: remove no_save context and simplify message update validation in RPCView
The update_message_text method in RPCView was refactored to remove the no_save context wrapper and streamline validation logic. The commented-out time-based restriction check was also removed, allowing message updates without the previous 8-second window limitation.
2025-06-25 19:38:26 +00:00
retoor 75e658d310 feat: add unique uid index to channel_message and remove time-limit check in RPC message update
Add a unique index on the `uid` field in the `channel_message` collection to enforce document uniqueness at the database level. In the RPC message update handler, remove the 8-second time-limit check and instead validate that the message is not marked as final or deleted before allowing edits.
2025-06-25 19:23:31 +00:00
retoor 9fdda81fcc feat: add composite and single-field indexes to channel_message collection on save
Add lazy index creation for `['is_final','user_uid','channel_uid']` and `['deleted_at']` fields in `ChannelMessageService.save()` method, guarded by a `_configured_indexes` flag to ensure indexes are created only once per service instance.
2025-06-25 19:17:37 +00:00
retoor 8b8d5ac862 fix: filter out deleted and finalized messages in RPC message retrieval
- Added `deleted_at=None` filter to `check_message` query in `send_message` to exclude soft-deleted messages from finalization queue
- Added `is_final=False` and `deleted_at=None` filters to `get_message` in `update_message` to prevent editing finalized or deleted messages
- Added early return with error response when message is not found after applying new filters
- Added conditional finalization logic: only queue finalization for non-final messages, cancel existing finalization task for already final messages
2025-06-25 18:59:22 +00:00
retoor 9e5fd33927 fix: replace fixed 7-second sleep with cancellable per-second loop in _finalize_message_task
The previous implementation used a single `await asyncio.sleep(7)` which could not be interrupted
mid-wait when the finalize task was cancelled. The new approach loops 7 times with 1-second sleeps,
checking `self._finalize_task` after each second and returning early if the task reference is cleared,
plus catching `CancelledError` to handle explicit cancellation gracefully.
2025-06-25 16:22:16 +00:00
retoor 45d8707fe7 fix: add early return guard for empty message in RPCView message handler
When message is empty after processing check messages, the handler now returns early
instead of proceeding to send an empty message through the chat service. This prevents
unnecessary API calls and potential errors from sending blank content.
2025-06-25 16:11:16 +00:00
retoor 0c3474da05 fix: replace scrollTop assignment with scrollIntoView and fix empty message display logic
- Comment out direct scrollTop assignment in scrollToBottom method and use scrollIntoView on the bottom anchor element instead
- Change display toggle from messageDiv to textElement in updateMessage to correctly hide empty text content while preserving message container layout
2025-06-25 16:07:11 +00:00
retoor dbb219e469 fix: correct empty message hiding logic and improve message finalization flow
- Move display toggle from textElement to messageDiv in message-list.js to properly hide entire message container when text is empty
- Remove is_final=False filter in _finalize_message_task to allow retrieval of already finalized messages
- Add early return when message is already finalized to prevent duplicate finalization attempts
- Strip whitespace from incoming message in send_message to handle empty/whitespace-only inputs
- Remove unused variable assignment for is_final in send_message non-final branch
2025-06-25 15:54:12 +00:00
retoor ee2ede2e2d fix: invert live-type attribute check and remove expiry timer from chat input
Remove the unused `expiryTimer` property and its related clearTimeout calls from ChatInputComponent. Fix the `liveType` boolean assignment by changing the comparison operator from `!==` to `==` so that the attribute value `"true"` correctly enables live typing behavior. Make `finalizeMessage` synchronous by removing the `await` keyword from the RPC call and the method declaration. Remove the early return guard for empty message values in `sendMessage` to allow empty strings to be sent. Add server-side logic for finalizing messages after a 7-second delay via a new `_finalize_message_task` coroutine, with cancellation support through `_queue_finalize_message`. Re-enable the previously commented-out logic in `send_message` that checks for an existing non-final message from the same user and updates it instead of creating a new one.
2025-06-25 15:31:49 +00:00
retoor ca62f75042 feat: add /leet and /l33t commands with text-to-leet conversion in chat input 2025-06-25 07:10:27 +00:00
retoor fe7568336b fix: update signup button link from /register to /register.html
The href attribute of the "Sign Up" anchor element in the index.html template was changed from "/register" to "/register.html" to align with the static HTML routing convention used elsewhere on the site, ensuring consistent URL resolution for the registration page.
2025-06-21 21:48:52 +00:00
retoor 6810b5e998 fix: invert live-type attribute check and force is_final in send_message
- Invert the live-type attribute check from `=== "true"` to `!== "true"` in ChatInputComponent
- Comment out the non-final message lookup logic in RPCView.send_message and force is_final to always be True
2025-06-15 00:30:57 +00:00
retoor fd7fc4220c fix: guard message continuation check behind is_final flag in send_message
Previously, the `send_message` method always queried for an existing non-final
message to update, even when `is_final=True`. This caused unnecessary database
lookups and could incorrectly attempt to update a stale message when sending
a final version. The fix wraps the continuation check inside `if not is_final:`,
so the lookup and update path is only taken when the message is explicitly
marked as non-final.
2025-06-15 00:21:49 +00:00
retoor addb34b6a5 fix: rename shadowed variable in send_message to avoid collision with parameter
The `send_message` method in `RPCView` had a local variable `message` that shadowed the `message` parameter, causing the parameter to be overwritten before being passed to `update_message_text`. Renamed the local variable to `check_message` to preserve the original parameter value for downstream use.
2025-06-15 00:18:45 +00:00
retoor 24c76d980c feat: add event bus for file upload completion and auto-send message with attachment links
- Introduce EventBus class in njet.js with subscribe/publish methods for decoupled component communication
- Replace direct NjetComponent subscription with eventBus.subscribe in chat-input.js for file-uploading events
- Add file-uploads-done event handler that reconstructs message from uploaded files and sends via RPC
- Reset uploadResponses array in FileUploadGrid.reset() to track completed uploads
- Publish file-uploads-done event when all uploads finish, passing array of file metadata
- Send relative_url in WebSocket done message from ChannelAttachmentUploadView for client-side link construction
- Modify RPC send_message to check for existing draft message and update it instead of creating new one
2025-06-15 00:16:08 +00:00
retoor 4b9bb44295 fix: remove debug print statements from BaseMapper retry loop
Removed four debug print calls that were logging function arguments, table name, and
result during the database operation retry loop in the BaseMapper class. These prints
were left over from development and were cluttering the output during normal operation.
2025-06-14 16:36:40 +00:00
retoor 2349e74734 feat: add is_final flag to channel messages and implement finalization loop in maintenance
Add `is_final` field to channel messages with a maintenance loop that toggles messages between final and non-final states. Introduce `send_message` RPC endpoint for creating messages with configurable finality. Remove `_finalize_message_task` and `updated_at` override in chat service, simplifying message finalization logic. Add debug prints to mapper retry loop for database operations.
2025-06-14 15:04:14 +00:00
retoor 47d237e6a7 fix: skip saving non-final channel messages outside no_save context and fix session_get default handling
- In `src/snek/service/chat.py`, wrap non-final channel message saves inside `self.app.no_save()` to prevent persistence of intermediate streaming updates, while final messages save normally.
- In `src/snek/view/rpc.py`, change `session_get` to be async and require a default argument, removing the optional default and fixing the internal lookup to use direct dict access instead of `.get()`.
- Remove unused `datetime` and `time` imports, reorder `_finalize_task` initialization after `_scheduled` list.
2025-06-14 13:42:29 +00:00
retoor f3d18ac1fd fix: replace incorrect app references with self in Application and refactor ChatService message handling 2025-06-14 13:20:04 +00:00