ai_co_discuss 0.3.63 → 0.3.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2319,6 +2319,29 @@ def interrupt_member(connection, room_id, member_id, token):
2319
2319
  return free_view(connection, room_id)
2320
2320
 
2321
2321
 
2322
+ def interrupt_for_message(connection, room_id, message_id):
2323
+ """The owner's "send now" of a queued message: interrupt the busy members it was just given to, so they take it next.
2324
+
2325
+ Members whose software reported it cannot stop are not interrupted: voiding their turn would only discard its answer
2326
+ while the next delivery still waits for it to end. Unlike the owner's stop, the rest of the queue is not paused.
2327
+
2328
+ Raises:
2329
+ FileExistsError: a recipient is busy and cannot be stopped; the caller keeps the message queued.
2330
+ """
2331
+ busy = connection.execute("""SELECT DISTINCT r.member_id, m.name, c.stoppable FROM member_requests r
2332
+ JOIN room_members m ON m.id=r.member_id
2333
+ JOIN member_executions e ON e.member_id=r.member_id AND e.status IN ('dispatched','started')
2334
+ LEFT JOIN execution_capabilities c ON c.execution_id=e.id
2335
+ WHERE r.room_id=? AND r.message_id=? AND r.status='pending'""", (room_id, message_id)).fetchall()
2336
+ blocked = [row["name"] for row in busy if row["stoppable"] == 0]
2337
+ if blocked:
2338
+ raise FileExistsError(f"{'、'.join(blocked)} 正在执行且无法打断,这条消息继续排队,等它答完后发送")
2339
+ for row in busy:
2340
+ stop_member_work(connection, row["member_id"], "用户立即发送", "user_stop", keep_pending=True)
2341
+ if busy:
2342
+ settle_batches(connection, room_id)
2343
+
2344
+
2322
2345
  def withdrawals(connection, room_id):
2323
2346
  """The room's taken-back messages by id, so the page keeps them in place while AI readers skip them."""
2324
2347
  return [dict(row) for row in connection.execute("""SELECT w.message_id,w.kind FROM message_withdrawal_rooms r
@@ -72,18 +72,22 @@ def enqueue(connection, room_id, payload):
72
72
 
73
73
 
74
74
  def post_item(connection, room_id, row, post):
75
- """Post one queued message through the normal path and drop its row; a refused post keeps the row with the reason."""
75
+ """Post one queued message through the normal path and drop its row; a refused post keeps the row with the reason.
76
+
77
+ Returns:
78
+ The post's result (with the saved `message`), or None when it was refused.
79
+ """
76
80
  connection.execute("SAVEPOINT queued_post")
77
81
  try:
78
- post(connection, room_id, json.loads(row["payload"]), "用户")
82
+ result = post(connection, room_id, json.loads(row["payload"]), "用户")
79
83
  except QUEUE_ERRORS as error:
80
84
  connection.execute("ROLLBACK TO queued_post")
81
85
  connection.execute("RELEASE queued_post")
82
86
  connection.execute("UPDATE queued_messages SET failure=? WHERE id=?", (str(error)[:500] or "发送失败", row["id"]))
83
- return False
87
+ return None
84
88
  connection.execute("RELEASE queued_post")
85
89
  connection.execute("DELETE FROM queued_messages WHERE id=?", (row["id"],))
86
- return True
90
+ return result
87
91
 
88
92
 
89
93
  def drain(connection, room_id, post):
@@ -131,10 +135,12 @@ def reorder(connection, room_id, ids):
131
135
  connection.execute("UPDATE queued_messages SET position=? WHERE id=?", (position, item_id))
132
136
 
133
137
 
134
- def queue_action(connection, room_id, token, payload, post, check):
138
+ def queue_action(connection, room_id, token, payload, post, check, interrupt):
135
139
  """The owner acts on the queue: send one now, edit, delete, reorder, resume, or switch queueing for the site.
136
140
 
137
- `post(connection, room_id, payload, actor)` posts a message; `check(payload)` validates an edited one.
141
+ `post(connection, room_id, payload, actor)` posts a message; `check(payload)` validates an edited one;
142
+ `interrupt(connection, room_id, message_id)` stops the busy members a message sent now was given to, so it does not
143
+ wait behind their current turn, and raises when one cannot be stopped, which leaves the whole write undone.
138
144
  """
139
145
  require_owner(connection, room_id, token)
140
146
  begin_write(connection)
@@ -144,8 +150,11 @@ def queue_action(connection, room_id, token, payload, post, check):
144
150
  if action == "send":
145
151
  row = queued_row(connection, room_id, payload.get("id"))
146
152
  connection.execute("UPDATE queued_messages SET failure='' WHERE id=?", (row["id"],))
147
- if not post_item(connection, room_id, row, post):
153
+ result = post_item(connection, room_id, row, post)
154
+ if not result:
148
155
  raise ValueError(connection.execute("SELECT failure FROM queued_messages WHERE id=?", (row["id"],)).fetchone()[0])
156
+ if result.get("message"):
157
+ interrupt(connection, room_id, result["message"]["id"])
149
158
  elif action == "edit":
150
159
  edit_item(connection, queued_row(connection, room_id, payload.get("id")), payload.get("text"), check)
151
160
  elif action == "delete":
package/backend/server.py CHANGED
@@ -28,7 +28,7 @@ from .remote_launch import (COMMAND_WAIT_MAX, claim_machine_commands, finish_mac
28
28
  machine_launch_action, machine_sync, pair_machine, remote_launch_status, submit_machine_command,
29
29
  submit_remote_launch)
30
30
  from .free_room import (add_member, after_free_message, after_proactive, authorize_free_write, check_answer, execution_action, free_view,
31
- inbox, interrupt_member, member_action, member_capability, member_values, migrate_free_tables, reserve_execution,
31
+ inbox, interrupt_for_message, interrupt_member, member_action, member_capability, member_values, migrate_free_tables, reserve_execution,
32
32
  save_room_access, view_execution)
33
33
  from .free_room import convert_suggestion, message_suggestions, save_suggestions, sync_participants
34
34
  from .free_room import adopt_recommendation, recommend_member, register_member, require_member
@@ -2280,7 +2280,7 @@ class DiscussionHandler(BaseHTTPRequestHandler):
2280
2280
  connection.commit()
2281
2281
  return self.respond(result)
2282
2282
  if parts[3:] == ["queue"] and method == "POST":
2283
- result = queue_action(connection, room_id, token, self.read_payload(), post_queued, check_queued)
2283
+ result = queue_action(connection, room_id, token, self.read_payload(), post_queued, check_queued, interrupt_for_message)
2284
2284
  connection.commit()
2285
2285
  return self.respond(result)
2286
2286
  if parts[3:4] in (["inbox"], ["executions"], ["members"], ["suggestions"], ["recommendations"], ["stop"]):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai_co_discuss",
3
- "version": "0.3.63",
3
+ "version": "0.3.64",
4
4
  "bin": {
5
5
  "codiscuss": "runner/codiscuss.mjs"
6
6
  },
package/web/app.js CHANGED
@@ -4544,7 +4544,8 @@ function view_snapshot() {
4544
4544
  archive_pending: [...state.archive_changes.keys()], import_progress: structuredClone(state.import_progress),
4545
4545
  directory_pending: [...state.directory_pending.keys()], folder_pending: [...state.folder_moves.keys()], creating_room: state.creating_room,
4546
4546
  connected: state.connected, reconnecting: state.reconnecting, backup_pending: Boolean(state.backup_pending), page: state.page, pages: state.pages, query: state.query,
4547
- attachment_drafts: state.attachment_drafts.map(item => ({ id: item.id, file_name: item.file.name, size: item.file.size, preview_url: item.preview_url })),
4547
+ attachment_drafts: state.attachment_drafts.map(item => ({ id: item.id, file_name: item.file.name, size: item.file.size, preview_url: item.preview_url,
4548
+ uploading: state.sending_message && !item.uploaded })),
4548
4549
  upload_status: state.upload_status, sending_message: state.sending_message, sending_preview: state.sending_preview,
4549
4550
  mention_only: state.mention_only, host_only: state.host_only, reply_to: state.reply_to, editing_queued: state.editing_queued?.id ?? null,
4550
4551
  access: access_snapshot(), admin: admin_snapshot(),
package/web/markdown.css CHANGED
@@ -1,2 +1,2 @@
1
- .markdown-body{--markdown-line:#c3ced8;--markdown-panel:#edf2f6;--markdown-link:#31647d;white-space:normal;overflow-wrap:anywhere;min-width:0}html[data-theme=channel] .markdown-body{--markdown-line:#454852;--markdown-panel:#202228;--markdown-code:#ffffff14;--markdown-link:#abb8ff}html[data-theme=channel-light] .markdown-body{--markdown-line:#dedede;--markdown-panel:#f6f6f6;--markdown-link:#0969da}.markdown-body>:first-child{margin-top:0}.markdown-body>:last-child{margin-bottom:0}.markdown-body p{margin:0 0 .8em}.markdown-body :is(h1,h2,h3,h4,h5,h6){color:inherit;margin:1.3em 0 .55em;font-weight:650;line-height:1.4}.markdown-body h1{font-size:1.5em}.markdown-body h2{font-size:1.3em}.markdown-body h3{font-size:1.15em}.markdown-body :is(h4,h5,h6){font-size:1em}.markdown-body strong{font-weight:700}.markdown-body em{font-style:italic}.markdown-body :is(ul,ol){margin:.5em 0 .9em;padding-left:1.7em}.markdown-body ul{list-style:outside}.markdown-body ol{list-style:decimal}.markdown-body ul ul{list-style:circle}.markdown-body li{margin:.25em 0;padding-left:.15em}.markdown-body li>:is(ul,ol,p){margin-top:.3em;margin-bottom:.3em}.markdown-body blockquote{border-left:3px solid var(--markdown-line);color:inherit;margin:1em 0;padding:.2em 1em}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body hr{border:0;border-top:1px solid var(--markdown-line);margin:1.3em 0}.markdown-body a{color:var(--markdown-link);text-underline-offset:3px;text-decoration:underline}.markdown-body code{background:var(--markdown-code,var(--markdown-panel));border-radius:4px;padding:.15em .35em;font-family:ui-monospace,Consolas,monospace;font-size:.88em}.markdown-body pre{border:1px solid var(--markdown-line);background:var(--markdown-panel);white-space:pre;overflow-wrap:normal;border-radius:6px;max-width:100%;margin:.8em 0 1em;padding:14px 16px;line-height:1.6;overflow-x:auto}.markdown-body pre code{white-space:inherit;background:0 0;border:0;border-radius:0;padding:0}.markdown-body .markdown-table{max-width:100%;margin:1em 0;overflow-x:auto}.markdown-body table{border-collapse:collapse;width:max-content;min-width:50%;max-width:100%;font-size:.93em}.markdown-body :is(th,td){border:1px solid var(--markdown-line);text-align:left;min-width:6em;padding:.55em .8em}.markdown-body th{background:var(--markdown-panel);font-weight:650}.markdown-body img{max-width:100%;height:auto}.markdown-body .mention{color:var(--markdown-link);background:0 0;border-radius:3px;padding:0 2px}.markdown-body .katex{font-size:1.1em}.markdown-body .katex-display{max-width:100%;padding:.3em 0;overflow:auto hidden}.markdown-body .katex-error{color:inherit;white-space:pre-wrap;font-family:ui-monospace,Consolas,monospace}.message-attachments{flex-direction:column;align-items:flex-start;gap:10px;max-width:100%;margin:10px 0 0;display:flex}.attachment-image{cursor:zoom-in;background:0 0;border:0;border-radius:8px;max-width:100%;padding:0;display:block;overflow:hidden}.attachment-image img{object-fit:contain;border-radius:inherit;width:auto;max-width:min(360px,100%);height:auto;max-height:320px;display:block}.attachment-file,.attachment-draft-file{color:#253044;background:#fff;border:1px solid #dce1e9;border-radius:8px;align-items:center;display:flex}.attachment-file{width:min(400px,100%);min-height:76px;padding-right:12px}.attachment-file-main{text-align:left;min-width:0;color:inherit;border-radius:inherit;cursor:pointer;font:inherit;background:0 0;border:0;flex:1;align-items:center;gap:14px;padding:14px 16px;text-decoration:none;display:flex}.attachment-file-main:hover .attachment-name>span{text-underline-offset:3px;text-decoration:underline}.attachment-file-icon{color:#3973f9;flex:none;width:32px;height:40px;display:block;position:relative}.attachment-file-icon svg{width:100%;height:100%;display:block}.attachment-file-icon>span{text-align:center;color:#fff;letter-spacing:-.2px;width:100%;font:650 9px/1.2 system-ui,sans-serif;position:absolute;top:21px;left:0}.attachment-file-icon[data-tone=red]{color:#e65c58}.attachment-file-icon[data-tone=green]{color:#2aa875}.attachment-file-icon[data-tone=orange]{color:#e58b3b}.attachment-name{flex:1;min-width:0;font-size:13px;line-height:1.5;display:block}.attachment-name>span{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.attachment-name small{color:#808998;margin-top:4px;font-size:11px;font-weight:400;display:block}.attachment-download{color:#707b8c;border-radius:5px;flex-shrink:0;place-items:center;width:32px;height:32px;text-decoration:none;display:grid}.attachment-download svg{width:18px;height:18px}.attachment-download:hover{color:#3868d9;background:#edf2fc}.attachment-drafts{flex-wrap:wrap;align-items:center;gap:10px;margin:0;padding:16px 14px 6px;display:flex}.attachment-drafts:empty{display:none}.attachment-draft-image{background:#edf0f4;border-radius:7px;width:88px;height:88px;position:relative}.attachment-draft-image img{object-fit:contain;border-radius:inherit;width:100%;height:100%;display:block}.attachment-remove{color:#707b8c;cursor:pointer;background:0 0;border:0;border-radius:50%;flex-shrink:0;place-items:center;width:24px;height:24px;padding:0;font-size:14px;display:grid}.attachment-remove:hover{color:#253044;background:#e9edf4}.attachment-remove:disabled{opacity:.4;cursor:default}.attachment-draft-image .attachment-remove{color:#fff;background:#444d60;border:2px solid #fff;position:absolute;top:-5px;right:-5px}.attachment-draft-image .attachment-remove:hover{background:#252d3e}.attachment-draft-file{gap:10px;width:min(280px,100%);padding:10px}.attachment-draft-file>span:first-child{flex-shrink:0}.attachment-draft-file .attachment-file-icon{width:28px;height:34px}.attachment-draft-file .attachment-file-icon>span{font-size:8px;top:18px}.attachment-composer-tools{align-items:center;gap:12px;margin-top:8px;font-size:12px;display:flex}.attachment-status{overflow-wrap:anywhere;margin:8px 0;font-size:12px;line-height:1.5}.attachment-status:empty{display:none}.attachment-status[role=alert]{color:#b44b40}.attachment-dialog{color:#253044;background:#f4f6f9;border:1px solid #cad2df;border-radius:12px;width:min(1100px,100vw - 32px);max-width:none;height:min(850px,100dvh - 48px);max-height:none;margin:auto;padding:0;box-shadow:0 16px 64px #0006}.attachment-dialog[open]{flex-direction:column;display:flex}.attachment-dialog::backdrop{background:#0d142bb3}.attachment-preview-heading{border-bottom:1px solid #cad2df;flex-shrink:0;align-items:center;gap:16px;padding:14px 18px;display:flex}.attachment-preview-heading h2{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;margin:0;font-size:15px;font-weight:600;overflow:hidden}.attachment-preview-heading a{color:inherit;flex-shrink:0;font-size:13px;text-decoration:underline}.attachment-dialog button{color:inherit;cursor:pointer;font:inherit;background:0 0;border:1px solid #b8c4d3;border-radius:5px;padding:5px 9px;font-size:13px}.attachment-dialog button:disabled{opacity:.4;cursor:default}.attachment-pdf-controls{flex-wrap:wrap;flex-shrink:0;justify-content:center;align-items:center;gap:10px;padding:10px;display:flex}.attachment-dialog .attachment-status{padding:0 18px}.attachment-viewer{overscroll-behavior:contain;flex:1;min-height:0;padding:16px;overflow:auto}.attachment-viewer img{object-fit:contain;width:auto;max-width:100%;height:auto;max-height:100%;margin:auto;display:block}.attachment-viewer canvas{background:#fff;margin:0 auto;display:block;box-shadow:0 1px 8px #0002}.attachment-dialog [hidden]{display:none!important}html[data-theme=channel] :is(.attachment-file,.attachment-draft-file,.attachment-dialog){color:#dde1ec;background:#282c36;border-color:#434958}html[data-theme=channel] .attachment-name small{color:#99a1b1}html[data-theme=channel] :is(.attachment-download,.attachment-remove){color:#aeb7c7}html[data-theme=channel] :is(.attachment-download,.attachment-remove):hover{color:#e3e9fb;background:#3b4252}html[data-theme=channel] .attachment-draft-image{background:#1b1f29}html[data-theme=channel] .attachment-draft-image .attachment-remove{color:#fff;border-color:#282c36}html[data-theme=channel] :is(.attachment-preview-heading,.attachment-dialog button){border-color:#4b5366}html[data-theme=channel] .attachment-status[role=alert]{color:#f4a89e}@media (width<=600px){.attachment-dialog{width:calc(100vw - 16px);height:calc(100dvh - 24px)}.attachment-preview-heading{gap:10px;padding:12px}.attachment-composer-tools{flex-wrap:wrap}}
1
+ .markdown-body{--markdown-line:#c3ced8;--markdown-panel:#edf2f6;--markdown-link:#31647d;white-space:normal;overflow-wrap:anywhere;min-width:0}html[data-theme=channel] .markdown-body{--markdown-line:#454852;--markdown-panel:#202228;--markdown-code:#ffffff14;--markdown-link:#abb8ff}html[data-theme=channel-light] .markdown-body{--markdown-line:#dedede;--markdown-panel:#f6f6f6;--markdown-link:#0969da}.markdown-body>:first-child{margin-top:0}.markdown-body>:last-child{margin-bottom:0}.markdown-body p{margin:0 0 .8em}.markdown-body :is(h1,h2,h3,h4,h5,h6){color:inherit;margin:1.3em 0 .55em;font-weight:650;line-height:1.4}.markdown-body h1{font-size:1.5em}.markdown-body h2{font-size:1.3em}.markdown-body h3{font-size:1.15em}.markdown-body :is(h4,h5,h6){font-size:1em}.markdown-body strong{font-weight:700}.markdown-body em{font-style:italic}.markdown-body :is(ul,ol){margin:.5em 0 .9em;padding-left:1.7em}.markdown-body ul{list-style:outside}.markdown-body ol{list-style:decimal}.markdown-body ul ul{list-style:circle}.markdown-body li{margin:.25em 0;padding-left:.15em}.markdown-body li>:is(ul,ol,p){margin-top:.3em;margin-bottom:.3em}.markdown-body blockquote{border-left:3px solid var(--markdown-line);color:inherit;margin:1em 0;padding:.2em 1em}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body hr{border:0;border-top:1px solid var(--markdown-line);margin:1.3em 0}.markdown-body a{color:var(--markdown-link);text-underline-offset:3px;text-decoration:underline}.markdown-body code{background:var(--markdown-code,var(--markdown-panel));border-radius:4px;padding:.15em .35em;font-family:ui-monospace,Consolas,monospace;font-size:.88em}.markdown-body pre{border:1px solid var(--markdown-line);background:var(--markdown-panel);white-space:pre;overflow-wrap:normal;border-radius:6px;max-width:100%;margin:.8em 0 1em;padding:14px 16px;line-height:1.6;overflow-x:auto}.markdown-body pre code{white-space:inherit;background:0 0;border:0;border-radius:0;padding:0}.markdown-body .markdown-table{max-width:100%;margin:1em 0;overflow-x:auto}.markdown-body table{border-collapse:collapse;width:max-content;min-width:50%;max-width:100%;font-size:.93em}.markdown-body :is(th,td){border:1px solid var(--markdown-line);text-align:left;min-width:6em;padding:.55em .8em}.markdown-body th{background:var(--markdown-panel);font-weight:650}.markdown-body img{max-width:100%;height:auto}.markdown-body .mention{color:var(--markdown-link);background:0 0;border-radius:3px;padding:0 2px}.markdown-body .katex{font-size:1.1em}.markdown-body .katex-display{max-width:100%;padding:.3em 0;overflow:auto hidden}.markdown-body .katex-error{color:inherit;white-space:pre-wrap;font-family:ui-monospace,Consolas,monospace}.message-attachments{flex-direction:column;align-items:flex-start;gap:10px;max-width:100%;margin:10px 0 0;display:flex}.attachment-image{cursor:zoom-in;background:0 0;border:0;border-radius:8px;max-width:100%;padding:0;display:block;overflow:hidden}.attachment-image img{object-fit:contain;border-radius:inherit;width:auto;max-width:min(360px,100%);height:auto;max-height:320px;display:block}.attachment-image:has(img[data-relay-src]:not([src])){width:160px;height:120px;color:inherit;background:color-mix(in srgb, currentColor 8%, transparent);place-items:center;display:grid;position:relative}.attachment-image img[data-relay-src]:not([src]){display:none}.attachment-image:has(img[data-relay-src]:not([src]):not([data-relay-failed])):after{content:"";border:2px solid color-mix(in srgb, currentColor 25%, transparent);border-top-color:color-mix(in srgb, currentColor 70%, transparent);border-radius:50%;width:24px;height:24px;animation:.8s linear infinite attachment-spin}.attachment-image:has(img[data-relay-failed]):after{content:"图片加载失败";opacity:.6;font-size:12px}.attachment-file,.attachment-draft-file{color:#253044;background:#fff;border:1px solid #dce1e9;border-radius:8px;align-items:center;display:flex}.attachment-file{width:min(400px,100%);min-height:76px;padding-right:12px}.attachment-file-main{text-align:left;min-width:0;color:inherit;border-radius:inherit;cursor:pointer;font:inherit;background:0 0;border:0;flex:1;align-items:center;gap:14px;padding:14px 16px;text-decoration:none;display:flex}.attachment-file-main:hover .attachment-name>span{text-underline-offset:3px;text-decoration:underline}.attachment-file-icon{color:#3973f9;flex:none;width:32px;height:40px;display:block;position:relative}.attachment-file-icon svg{width:100%;height:100%;display:block}.attachment-file-icon>span{text-align:center;color:#fff;letter-spacing:-.2px;width:100%;font:650 9px/1.2 system-ui,sans-serif;position:absolute;top:21px;left:0}.attachment-file-icon[data-tone=red]{color:#e65c58}.attachment-file-icon[data-tone=green]{color:#2aa875}.attachment-file-icon[data-tone=orange]{color:#e58b3b}.attachment-name{flex:1;min-width:0;font-size:13px;line-height:1.5;display:block}.attachment-name>span{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.attachment-name small{color:#808998;margin-top:4px;font-size:11px;font-weight:400;display:block}.attachment-download{color:#707b8c;border-radius:5px;flex-shrink:0;place-items:center;width:32px;height:32px;text-decoration:none;display:grid}.attachment-download svg{width:18px;height:18px}.attachment-download:hover{color:#3868d9;background:#edf2fc}.attachment-drafts{flex-wrap:wrap;align-items:center;gap:10px;margin:0;padding:16px 14px 6px;display:flex}.attachment-drafts:empty{display:none}.attachment-draft-image{background:#edf0f4;border-radius:7px;width:88px;height:88px;position:relative}.attachment-draft-image img{object-fit:contain;border-radius:inherit;width:100%;height:100%;display:block}.attachment-remove{color:#707b8c;cursor:pointer;background:0 0;border:0;border-radius:50%;flex-shrink:0;place-items:center;width:24px;height:24px;padding:0;font-size:14px;display:grid}.attachment-remove:hover{color:#253044;background:#e9edf4}.attachment-remove:disabled{opacity:.4;cursor:default}.attachment-draft-image .attachment-remove{color:#fff;background:#444d60;border:2px solid #fff;position:absolute;top:-5px;right:-5px}.attachment-draft-image .attachment-remove:hover{background:#252d3e}.attachment-draft-file{gap:10px;width:min(280px,100%);padding:10px;position:relative}.attachment-uploading{z-index:1;border-radius:inherit;color:#fff;background:#0008;place-items:center;display:grid;position:absolute;inset:0}.attachment-uploading>span{width:26px;height:26px;animation:.8s linear infinite attachment-spin}@keyframes attachment-spin{to{transform:rotate(360deg)}}.attachment-draft-file>span:first-child{flex-shrink:0}.attachment-draft-file .attachment-file-icon{width:28px;height:34px}.attachment-draft-file .attachment-file-icon>span{font-size:8px;top:18px}.attachment-composer-tools{align-items:center;gap:12px;margin-top:8px;font-size:12px;display:flex}.attachment-status{overflow-wrap:anywhere;margin:8px 0;font-size:12px;line-height:1.5}.attachment-status:empty{display:none}.attachment-status[role=alert]{color:#b44b40}.attachment-dialog{color:#253044;background:#f4f6f9;border:1px solid #cad2df;border-radius:12px;width:min(1100px,100vw - 32px);max-width:none;height:min(850px,100dvh - 48px);max-height:none;margin:auto;padding:0;box-shadow:0 16px 64px #0006}.attachment-dialog[open]{flex-direction:column;display:flex}.attachment-dialog::backdrop{background:#0d142bb3}.attachment-preview-heading{border-bottom:1px solid #cad2df;flex-shrink:0;align-items:center;gap:16px;padding:14px 18px;display:flex}.attachment-preview-heading h2{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;margin:0;font-size:15px;font-weight:600;overflow:hidden}.attachment-preview-heading a{color:inherit;flex-shrink:0;font-size:13px;text-decoration:underline}.attachment-dialog button{color:inherit;cursor:pointer;font:inherit;background:0 0;border:1px solid #b8c4d3;border-radius:5px;padding:5px 9px;font-size:13px}.attachment-dialog button:disabled{opacity:.4;cursor:default}.attachment-pdf-controls{flex-wrap:wrap;flex-shrink:0;justify-content:center;align-items:center;gap:10px;padding:10px;display:flex}.attachment-dialog .attachment-status{padding:0 18px}.attachment-viewer{overscroll-behavior:contain;flex:1;min-height:0;padding:16px;overflow:auto}.attachment-viewer img{object-fit:contain;width:auto;max-width:100%;height:auto;max-height:100%;margin:auto;display:block}.attachment-viewer canvas{background:#fff;margin:0 auto;display:block;box-shadow:0 1px 8px #0002}.attachment-dialog [hidden]{display:none!important}html[data-theme=channel] :is(.attachment-file,.attachment-draft-file,.attachment-dialog){color:#dde1ec;background:#282c36;border-color:#434958}html[data-theme=channel] .attachment-name small{color:#99a1b1}html[data-theme=channel] :is(.attachment-download,.attachment-remove){color:#aeb7c7}html[data-theme=channel] :is(.attachment-download,.attachment-remove):hover{color:#e3e9fb;background:#3b4252}html[data-theme=channel] .attachment-draft-image{background:#1b1f29}html[data-theme=channel] .attachment-draft-image .attachment-remove{color:#fff;border-color:#282c36}html[data-theme=channel] :is(.attachment-preview-heading,.attachment-dialog button){border-color:#4b5366}html[data-theme=channel] .attachment-status[role=alert]{color:#f4a89e}@media (width<=600px){.attachment-dialog{width:calc(100vw - 16px);height:calc(100dvh - 24px)}.attachment-preview-heading{gap:10px;padding:12px}.attachment-composer-tools{flex-wrap:wrap}}
2
2
  /*$vite$:1*/