Commit graph

10220 commits

Author SHA1 Message Date
Timothy Jaeryang Baek
7ad0ae4687 refac 2026-09-24 12:34:04 -04:00
G30
893251ed11
fix: show the new share link's own access after the old link is deleted (#31037) 2026-09-24 12:11:24 -04:00
G30
bbfa876afd
fix: stop the token and API key copy buttons from saving the account form (#30956) 2026-09-24 00:15:30 -04:00
Timothy Jaeryang Baek
ff89756b6d refac 2026-09-24 00:14:58 -04:00
Classic298
e6e9fc9721
fix: keep the composer's + and Integrations buttons visible at larger UI Scale on mobile (#30374)
On a phone with UI Scale at 1.2x or higher, the model selector in the chat composer covers the Integrations button, so it cannot be seen or tapped. From 1.3x it covers the + button too, which leaves no way to attach files or open integrations.

The model selector's width cap is rem based, so it grows with UI Scale, and the left button group could shrink to nothing, so the selector took the space first. The + and Integrations buttons now sit in a group that keeps its width, and only the toggled chips stay in the scrolling strip. When space runs out the model name truncates, and chips scroll as before.

Measured in the real app at a 360px mobile viewport: before, Integrations is covered at 1.2x and both buttons at 1.3x and 1.5x; after, both are tappable at every scale, with the model name truncated (114px at 1.3x). Button positions at 1x and on desktop are unchanged to the pixel, with and without chips.

Fixes #29989
2026-09-23 23:08:48 -05:00
G30
5f8d8f0c5e
fix: resume the send queue after a queued message is deleted or edited (#30447) 2026-09-23 23:03:44 -05:00
G30
e67d7f9e40
fix: stop Interface settings save from overwriting the default model (#30953) 2026-09-23 23:00:41 -05:00
Timothy Jaeryang Baek
aea7d34f45 refac 2026-09-24 00:00:19 -04:00
Classic298
e14f245586
fix: keep the M mute shortcut working during voice calls (#30421)
In voice mode, pressing M after a turn typed an "m" into the chat box instead of muting. After each voice message the chat input pulled keyboard focus back to itself, and the call overlay ignores M while focus is in a text field so typing still works.

The chat input now leaves focus alone while a call is open: clearing it after a send, the remount on the first message of a new chat and the editor's autofocus all skip focusing during a call. Clicking into the box and typing during a call still works, and outside a call the input focuses exactly as before.

Checked in a browser with a fake microphone: M mutes after the first, second and third turn, in new and existing chats; "m" typed into a focused input during a call still types.

Fixes #30406
2026-09-23 23:55:21 -04:00
Classic298
7924ce7d79
fix: unhandled play() rejection wedges the Read Aloud button; auto-playback silent on iOS (#30373)
On iOS and iPadOS, auto-playback of a finished reply is never heard and the speaker button stays stuck in "speaking", so the first tap only stops a playback that never started. WebKit rejects play() started from a network event, and the audio queue ignored that rejection, so its state never reset. Call mode on the same devices was silent too.

A rejected play() now resets the queue, returns the button to idle and shows a toast (an aborted play from stop or a message switch is ignored). The first user tap or keypress plays a 10 ms silent clip on the shared audio element, which WebKit then allows to play later without a gesture; if that attempt fails it retries on the next gesture. Call mode plays unmuted: WebKit pauses an element that is unmuted after play() outside a gesture, even once unlocked.

The unlock and call mode change follow the reporter's on-device tests (iPhone iOS 27, iPad iPadOS 26.6.2). Verified in Chromium with autoplay restricted: the base queue wedges and drops later chunks; with the fix it reports the error, recovers, the unlock plays once and never interrupts audio already playing, and chunks queued during the unlock still play.

Fixes #30262
2026-09-23 23:52:09 -04:00
Classic298
1b5a8ac5a7
fix: keep model default features when comparing multiple models (#30383)
Adding a second model to a chat turned off Web Search, Image Generation and Code Interpreter even when every selected model has them as Default Features, so the comparison ran without them. Changing the selection clears the feature toggles and then reapplies the model defaults, but defaults were only reapplied for a single model.

In compare mode a default feature is now turned on when every selected model supports it and has it as a default, since the toggles are shared by all models in the comparison. It only ever turns features on, so flags passed in the URL (?web-search=true) are not overwritten. Single-model defaults are unchanged.

The input reset now waits for the model-selection update to finish before applying defaults. Before, the Web Search value actually sent could disagree with the toggle on screen: a single model with Web Search on by default showed the toggle on but sent it off, and switching to a model without it showed it off but still sent it on (see #29326). The toggle and the request now match.

Fixes #30310
2026-09-23 23:51:57 -04:00
Classic298
4e4b324246
fix: skip the pyodide plt.show patch when matplotlib is not loaded (#30381)
Any Python code that only mentioned "matplotlib" (a comment, a string, or an importlib.util.find_spec("matplotlib") check) failed with ModuleNotFoundError before a single line of it ran. The plt.show() patch was applied on a plain substring match, but matplotlib is only installed when the code actually imports it, so the patch's own import crashed the run. The user's try/except could not catch it, because their code never started. The same thing broke the code editor's Python formatter on any code that imports matplotlib, since that run only installs black.

The patch now also requires matplotlib to be present in the runtime's loaded packages, in both the worker and the sandboxed iframe host. Real matplotlib code still gets inline PNG output from plt.show(), and code that merely mentions matplotlib runs unchanged.

Gating on the callers' import regex instead was also tested and still fails the formatter case, because there the code containing the import sits inside a string while only black is installed.

Fixes #29894
2026-09-23 23:51:39 -04:00
Classic298
e13e523f00
feat: bundle python-pptx and python-docx for the Pyodide code interpreter (#30382)
Asked for a PowerPoint or Word file, the model had no library for it, so it followed the prompt's "use an alternative approach" and wrote the OOXML zip by hand. The sandbox reported success and Office refused to open the result.

python-pptx and python-docx are now vendored the same way as openpyxl: their wheels (plus xlsxwriter) go through the PyPI wheel path, lxml joins the Pyodide distribution list so its wasm wheel is cached, and importing pptx or docx installs them from the bundled wheels. No prompt change is needed, since the app installs on import.

static/pyodide grows by about 3 MB (58 to 61 MB) and verifyBundledWheels() passes.

Verified in headless Chromium with pypi.org, files.pythonhosted.org and the jsDelivr CDN blocked: both packages install from the local wheels only, and a deck and a document built in the sandbox reopen with the native libraries. openpyxl, seaborn, black, pandas, matplotlib and requests still install offline. Without the change both installs fail offline.

Fixes #30361
2026-09-23 23:50:39 -04:00
Classic298
9db68981d8
feat: allow reordering admin models while a search or filter is active (#30390)
On Admin Settings > Models the drag handle was disabled as soon as a search, view or tag filter was active, so on a long list the only way to move a model was to clear everything and hunt for it by eye.

Dragging now works in any filtered list. The move is applied to the full order: the dragged model is placed directly after the visible model it was dropped below (or directly before the one it was dropped above), and every model hidden by the filter keeps its place. That anchoring is what makes reordering a subset safe, which is why the filters previously blocked it.

The tag filter now filters the loaded list client-side like search and view already do. Before, it reloaded the page data and rebuilt the order from only the tagged models, so saving under a tag would have dropped every other model from the order, and switching tags discarded unsaved moves. Export keeps its existing tag-filtered behaviour.

Verified in the browser with search, view (enabled/disabled) and tag filters, dragging up and down, multiple moves before one save and switching tags with unsaved moves; the saved order always contains every model.

Closes #29634
2026-09-23 23:48:05 -04:00
G30
a7d81ebdcf
fix: keep a user's chats listed in the admin chats view after deleting one (#30604) 2026-09-23 23:32:23 -04:00
Classic298
869a5b1035
fix: stop voice mode listening after leaving the chat page (#30405) (#30417)
Leaving the chat with voice mode active (Admin Panel, Workspace, Notes) left a hidden recorder running in the tab. The voice mode flag stays on when the chat page unmounts, so the overlay's teardown restarted recording on the destroyed component, which kept transcribing speech and sending prompts from other pages. Returning to the chat also opened an extra microphone stream that was never closed.

The overlay now marks itself destroyed on teardown and never starts or restarts recording after that, so leaving the chat shuts the microphone down fully.

Resetting the voice mode flag in the chat page cleanup was considered, but it changes behaviour for the controls panel on return and still runs after the overlay's own teardown.

Verified in Chromium with a fake microphone (14s per phase, transcription requests / live mic tracks):

| Phase | before | after |
|---|---|---|
| Call on chat | 3 / 1 | 3 / 1 |
| After moving to Workspace | 3 / 1 | 0 / 0 |
| Voice mode reopened | 3 / 3 | 3 / 1 |

Fixes #30405
2026-09-23 23:30:30 -04:00
CosmicFlavour
53c7ed3370
i18n: add missing french translation in fr_FR (#30403) 2026-09-23 23:30:05 -04:00
Aleix Dorca
c86c46e034
i18n: Update catalan translation.json (#30415)
* Update catalan translation.json

* i18n: Update catalan translation.json and typos
2026-09-23 23:29:51 -04:00
Classic298
d66e5dc403
fix: make the admin analytics tab scrollable inside the settings modal (#30429)
The analytics dashboard renders inside the settings modal, whose tab area clips overflowing content. Unlike the other tabs, analytics had no scroll area of its own, so on any instance with more than a handful of models or users the bottom of the model and user ranking tables was cut off and could not be reached.

The analytics wrapper now scrolls vertically, using the same scroll classes as the other settings tabs. Verified in a browser with 30 models and 45 users at 1400x900, 1280x720 and 700x900: before, wheel scrolling moved nothing; after, both tables scroll to their last row with a single scrollbar and no horizontal overflow.

Fixes #30428
2026-09-23 08:46:22 -05:00
Classic298
24c01bd76d
fix: stop voice call hanging in "speaking" when TTS fails (#30372)
Some checks are pending
Python CI / Ruff Format (3.11) (push) Waiting to run
Python CI / Ruff Format (3.12) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / merge (map[name:cuda suffix:-cuda]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:cuda126 suffix:-cuda126]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (, main) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda126, cuda126) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-ollama, ollama) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-slim, slim) (push) Blocked by required conditions
Frontend Build / Unit Tests (push) Waiting to run
Create and publish Docker images with specific build args / merge (map[name:main suffix:]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:ollama suffix:-ollama]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:slim suffix:-slim]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / notify-helm-charts (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda, cuda) (push) Blocked by required conditions
Frontend Build / Format & Build (push) Waiting to run
When the configured TTS provider fails during a voice call, the text answer arrives but the overlay stays in "speaking" with no audio and no error until the user taps to interrupt. The sentence that failed never reaches the audio cache, so the playback loop re-queues it every 200 ms forever.

A failed sentence now marks its message as failed. The playback loop drops that message's unplayed sentences, the rest of the turn requests no more TTS, and the overlay returns to listening once the text finishes. The OpenAI-compatible path now shows the provider error once per turn, the same way Read Aloud and the Kokoro path already do. The next turn tries TTS again.

Failure is tracked per message so an outage (the report shows 16 parallel requests all failing) costs one toast and no further requests. The trade-off is that a one-off failure mutes the rest of that reply.

Verified with the real fetch/playback code in a harness: base loops forever with no toast; with the fix, one toast, the loop ends, later sentences are not requested, a new turn plays normally, and a late failure from a previous turn does not affect the next one.

Fixes #30052
2026-09-22 16:57:10 -04:00
Classic298
15f350b417
fix: keep an open chat's tools when clicking a folder name (#30376)
Clicking a folder name in the sidebar while a chat was open switched that chat to the folder's default model for a moment before the page changed. That reset its tools and skills to the folder model's set and saved them as the chat's draft, so on returning to the chat the folder model's tools were shown and sent with the next message. The same happened to a chat just started from the home page.

The folder's default model is now only applied while the chat has no messages yet, the same rule new chats already follow when a folder page opens. Folder pages, new chats in a folder and editing a folder's default model behave as before.

Verified in a browser against a mock upstream: on dev the next request after the folder click carried the folder model's tool_ids and skill_ids; with the fix it carries the chat's own model's set, for both an existing chat and one started from the home page.

Fixes #30226
2026-09-22 16:47:09 -04:00
Classic298
d603b57995
fix: FireFox regional setting (#30377)
* fix: keep en-US as the last i18n fallback when a stored locale has no bundle

Settings labels rendered as raw keys such as settings.admin.connections.title
instead of "Connections" from the second page load on, while every other
label looked fine.

On the first visit the language detector saves whatever the browser reports
into localStorage, including bare codes like "en" that have no locale bundle.
The same value is saved by ?lang=en or DEFAULT_LOCALE=en. On the next load
that stored value became the only fallback language, so the missing bundle
left nothing to fall back to. Plain keys still looked right because the key
is the English text; only the settings.* keys have a distinct value.

en-US now stays at the end of the fallback list whenever a stored locale is
passed in. The stored locale keeps precedence, real locales are unaffected,
and the en-US bundle was already loaded for every language for the settings
merge, so there is no extra request.

Fixes #30348

* fix: match browser language codes to a locale bundle

Firefox reports German, Dutch and Polish as bare codes (de, nl, pl), both Chrome and Firefox report Japanese as ja, and Chrome in Latin America reports es-419. No bundle is keyed by any of these. The page layout used to match them on the first visit, but since 67ac1a4e9 (0.11.4) awaits the i18n init, the detector has already cached the raw code by the time that check runs, so it never does. Those users get an English interface, a language dropdown with nothing selected and English date formats, and the cached code keeps them there.

The detector now maps a reported code onto a bundle before anything else sees it. A code we ship stays as it is, matched case-insensitively. Otherwise the language's xx-XX bundle is used when there is one, so de and de-AT become de-DE, es-419 becomes es-ES, and fr becomes fr-FR even though fr-CA comes first in the list. A bare code with no xx-XX bundle takes the first one for its language, so ja becomes ja-JP. Any other regional code passes through untouched, so zh-HK is not sent to Simplified zh-CN, and no locale that works today changes.

Restoring the layout check would leave every browser that cached a raw code under 0.11.4 stuck. Matching in the detector migrates them on their next load, because the matched code is what gets cached. {{USER_LANGUAGE}} reports that matched code too, so es-419 users now send es-ES.

Verified against the real bundles on first and repeat loads, including the untouched cases fr-CA, pt-BR, zh-TW, zh-HK, ar-BH, en-GB and uz-Latn-UZ.
2026-09-22 16:46:58 -04:00
G30
f2702e1f0f
fix: fall back to the user's system prompt when the chat's own is cleared (#30333) 2026-09-22 11:37:59 -04:00
MiRHaDi
845b791609
i18n: translate Persian counters and preserve prompt variable (#30329) 2026-09-22 11:37:48 -04:00
Badar Rahman
69fcad0c04
i18n: complete Indonesian (id-ID) translations (#30328)
Co-authored-by: DarRahman <darrahman@users.noreply.github.com>
2026-09-22 11:36:35 -04:00
Classic298
fecbeac7d1
Merge pull request #30354 from Classic298/i18n-en-us-fallback
fix: keep en-US as the last i18n fallback when a stored locale has no bundle
2026-09-22 11:34:44 -04:00
Nas
9530cc15c1
i18n: restore placeholder names that were translated or lost their braces (#30326)
{{ models }} -> {{ modelli }} etc. in 10 locales, {{name}} -> {{nombre}} in
gl-ES, {{file}} -> {{arxiu}} in ca-ES, and single/unbalanced braces in kab-DZ,
nb-NO and ca-ES. 22 strings in 13 locales, tokens only.
2026-09-21 15:16:04 -04:00
Classic298
46ea826e01
refac: keep rendered diagrams and SVG on same-origin resources (#30271)
Mermaid diagrams and the shared SVG sanitizer now accept only same-origin and data: references. Image URLs, class styles and directive config are checked on the parsed diagram before it renders, and the sanitizer drops attribute values and stylesheet rules that point at another origin. use elements keep local #id references only.

SVGPanZoom and the SVG file preview call the shared sanitizer instead of keeping their own configs, so SVG artifacts and uploaded SVG files follow the same rule. Uploaded SVGs that reference external sprites now render those parts blank, which is the point of the change.

A diagram that references an external resource now reports an error instead of rendering, and an SVG artifact keeps everything except the rules that reference one.
2026-09-21 15:15:28 -04:00
Timothy Jaeryang Baek
ee3ece1e2b refac 2026-09-21 14:43:04 -04:00
Timothy Jaeryang Baek
c07fa08b99 refac 2026-09-21 11:45:49 -04:00
Timothy Jaeryang Baek
bf476452a8 chore: format 2026-09-21 11:35:30 -04:00
G30
b988f06ce0
fix: drop every local reference to a channel message that was deleted (#30314) 2026-09-21 11:32:14 -04:00
G30
4b61b86a83
fix: apply the knowledge File content filter on the first click (#30211) 2026-09-21 11:30:42 -04:00
Timothy Jaeryang Baek
9fba2843b1 refac 2026-09-21 11:24:40 -04:00
Timothy Jaeryang Baek
30881dbcc9 refac 2026-09-21 11:09:09 -04:00
G30
9688d32764
fix: keep the background image chosen while creating a folder from the sidebar (#30218) 2026-09-21 10:36:49 -04:00
G30
bc50026f7b
fix: make the Delete Chat shortcut work whenever a chat is open, not only while its sidebar row is rendered (#30165) 2026-09-21 10:21:19 -04:00
Timothy Jaeryang Baek
a9541c18ca refac 2026-09-21 10:19:59 -04:00
Classic298
488b3c571c
perf: stop note co-editing echoing every remote update back to the server (#28185)
Every client in a note re-broadcasts each update it receives, with a full content snapshot attached, and the server appends each echo to the document log and writes the note again. Traffic and note writes therefore scale with the number of people who have the note open: every extra participant adds one more full echo of every keystroke.

Remote updates are now applied with the `'server'` origin the state path already uses, which the local listener ignores, so the echo stops. The echo did carry one thing worth keeping: the receiving client holds the merged document, which the sender had not seen yet, so each receiver now sends a content-only message once the edits settle, debounced 500ms, and flushes a pending one when the editor is torn down. The backend accepts an update message with no `update` field for that case, where it previously raised and dropped the save.

Replaying keystrokes at 120ms with a real Yjs document, socket messages fall 48.8% with two clients, 65.6% with three and 79.2% with five, with byte counts tracking the same on notes up to 50KB. Server-side update appends drop by a factor of the client count. The cost is one snapshot upload per receiving client per typing pause, which the server's own debounce then collapses into a single extra note write however many people are watching. A snapshot has to come from a client because the server cannot rebuild the markdown, HTML and JSON shape the note record stores. It also moves the merge 500ms later than the echo delivered it, so if two edits cross on the wire and every editor then loses its connection and closes inside that window, the note keeps what it was last sent and one of the two edits is lost. A client still connected at teardown flushes its pending snapshot, and any other editor left in the note closes the gap.
2026-09-21 08:53:27 -04:00
G30
d9ea46f92d
fix: hide Insert into note on a note the viewer may only read (#30223) 2026-09-21 08:32:17 -04:00
G30
440d13e198
fix: refresh the prompt editor after a version is set as production (#30233) 2026-09-21 08:31:51 -04:00
G30
c2f11edb2f
fix: keep a workspace model's base model when cloning it from the admin Models settings and hide Clone for arena models (#30080) 2026-09-21 08:15:12 -04:00
Classic298
f5967aebd7
fix: restore chat input draft after reload in chats started from the home page (#29762)
Typing a message, uploading a file or toggling web search in a chat started from the home page was lost on reload: the input came back empty and the uploaded files were gone for good.

Drafts are kept per chat in sessionStorage, but the key was built from the route prop, which stays empty for these chats because creating the chat only swaps the URL with history.replaceState and never re-runs the route load. Drafts were written under the new-chat key while a reload of /c/<id> read the per-chat key. Falling back to the active chat id lines the two up, the same fallback loadChat already uses for this reason.

The Placeholder submit handler also cleared the bare key rather than the current one, which left a stale draft behind once a chat's messages had all been deleted.

Verified against the base commit on a local instance: on base the draft lands under chat-input and is lost on reload, with the change it lands under chat-input-<id> and both the text and the uploaded file come back. Image attachments stay excluded from drafts by design.

The model selection half of #29760 has a different cause and is not fixed here.

Refs #29760
2026-09-21 08:08:45 -04:00
Classic298
f16e9eabe3
feat: fall back to an available model when a chat's models are gone (#29757)
Retiring a model leaves every chat that used it stuck. The chat still stores the old model id, so it loads with nothing usable selected and refuses to send until the user picks a replacement by hand, in every old conversation. There is no admin-side way to move those chats across.

Loading a chat now drops model ids that no longer exist, and an empty selection falls into the fallback this function already applies to new chats: the user's default model, then the admin-configured default, then the first available model. A chat that still has one live model keeps it. The filter runs before the single-model permission clamp so a restricted user keeps a live model the chat already has instead of losing it to the clamp.

The model list cannot distinguish a retired model from one whose connection is momentarily unreachable, so during such an outage a chat pinned to that connection will open on the fallback model and record it when saved. Models defined in the workspace are unaffected, since they stay in the list while their connection is down.
2026-09-21 08:08:27 -04:00
G30
5399e3977d
fix: enforce the account form's required fields the way the admin user dialog does (#30296) 2026-09-21 08:08:02 -04:00
G30
aa65f55692
fix: insert the whole emoji when its shortcode is a codepoint sequence (#30213) 2026-09-21 08:07:45 -04:00
G30
7eebbbb891
fix: stop the MinerU API key blocking a save in local mode (#30299) 2026-09-21 08:04:19 -04:00
andreadegiovine
e9017c7da4
i18n: update and improve it-IT (#30297)
* i18n: update and improve it-IT

* i18n: update and improve it-IT

---------

Co-authored-by: andreadegiovine <andreadegiovine@gmail.com>
2026-09-21 08:04:08 -04:00
Timothy Jaeryang Baek
85146206f6 refac 2026-09-21 00:59:46 -04:00
G30
14be67348a
fix: open the new group dialog empty after a group is created (#30280) 2026-09-21 00:56:53 -04:00