- Sneedchat: detect a reconnect that silently lands as a guest (server's own can_send permission flag) and force a session refresh + relogin; add an idle-read timeout so a dead websocket is actually noticed - Sneedchat: multipart file upload support in http.rs, wired into sendMessage's attachment path (qu.ax-hosted images/video) - Discord-style optimistic message sends: dim pending messages, resolve to the real server echo, turn red and offer Retry on failure/timeout - MessageList: fix scroll-to-end/New-divider landing, anchored-scroll reliability during scrollbar drags, and BBCode [img][/img] tags merging into one URL when posted back-to-back - MediaEmbed: real audio output device, working scrub-bar seek/pan, restart-from-start on a finished video - DaemonStatusSettings: chatd connection indicator + build (git branch) badge for DMS's plugin manager pane - BufferList: scope the "+" join-channel affordance to IRC accounts only - DisplaySettingsPanel: new toggle for content-sniffing unrecognized media links Co-Authored-By: Claude Sonnet 5 <[email protected]>
75 lines
2.9 KiB
QML
75 lines
2.9 KiB
QML
import QtQuick
|
|
import qs.Common
|
|
import qs.Widgets
|
|
import qs.Modules.Plugins
|
|
|
|
// Cross-protocol display preferences, loaded by ChatSettings.qml's rail
|
|
// under "Display" rather than any one service's own panel - unlike IRC's
|
|
// join/part filters etc., these apply to every buffer regardless of which
|
|
// backend it's talking to (see ChatView.qml's messageDisplayMode/
|
|
// mediaAutoplay/mediaLoop, read from the same "dankChat" plugin data these
|
|
// settings write to).
|
|
PluginSettings {
|
|
id: root
|
|
pluginId: "dankChat"
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: "Message layout"
|
|
font.weight: Font.Medium
|
|
color: Theme.surfaceVariantText
|
|
}
|
|
|
|
SelectionSetting {
|
|
settingKey: "display.messageMode"
|
|
label: "Display style"
|
|
description: "Classic: a compact IRC-style log, one line per message. Comfy: Discord-style, grouped by author with an avatar and more breathing room."
|
|
defaultValue: "classic"
|
|
options: [
|
|
{ "label": "Classic", "value": "classic" },
|
|
{ "label": "Comfy", "value": "comfy" }
|
|
]
|
|
}
|
|
|
|
ToggleSetting {
|
|
settingKey: "display.relativeTimestamps"
|
|
label: "Relative timestamps"
|
|
description: "Show \"8m ago\", \"2h ago\" instead of a clock time. Switches to \"Yesterday at 5:27 PM\" after 23h, then a short date after 47h. Hovering a timestamp always shows the full date/time either way."
|
|
defaultValue: false
|
|
}
|
|
|
|
Rectangle {
|
|
width: parent.width
|
|
height: 1
|
|
color: Theme.outlineMedium
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: "Media"
|
|
font.weight: Font.Medium
|
|
color: Theme.surfaceVariantText
|
|
}
|
|
|
|
ToggleSetting {
|
|
settingKey: "media.autoplay"
|
|
label: "Autoplay GIFs and WebP"
|
|
description: "Play animated images as soon as they're shown, instead of starting paused on the first frame"
|
|
defaultValue: true
|
|
}
|
|
|
|
ToggleSetting {
|
|
settingKey: "media.loop"
|
|
label: "Loop GIFs and WebP"
|
|
description: "Keep replaying an animated image instead of stopping after one pass"
|
|
defaultValue: true
|
|
}
|
|
|
|
ToggleSetting {
|
|
settingKey: "media.contentSniffing"
|
|
label: "Embed unrecognized links by content type"
|
|
description: "Many image hosts use short, extensionless links (e.g. a ShareX-style upload host) that can't be identified as an image from the URL text alone. When on, an unrecognized link is checked directly to see if it's an image or video, and embedded if so. Privacy note: this contacts the linked site directly - the moment a message arrives, not only if you click it - which reveals your connection to that site, and for Sneedchat specifically bypasses its Tor transport entirely (this is a plain network request, not routed through the embedded Tor client). Turn off to only embed links with a recognizable image/video file extension."
|
|
defaultValue: true
|
|
}
|
|
}
|