Desktop session batch 09-12: frameless chrome, bisect removal, chat/idle fixes

Frameless (window_manager, hidden titlebar): chrome bar on welcome,
drag-to-move appbar + window buttons on connect, drag layer + window
buttons in session controls; min size 160x90; volume-scroll off for
drag; session maximize = fullscreen toggle. Verified on KDE Wayland.
Delete legacy/minimal/nosheet bisect screens; session routes direct
(black-screen fix verified incl. WAN).
Avatar: pipeline now 128px aspect-kept PNG (was cropped JPEG);
profile card centered 64px hover-to-change; member avatar drops
ResizeImage downscale. NOTE open: pipeline 512 KiB check vs server
64 KiB enforcement mismatch.
Fixes: idle warn/unready skipped while PLAYING; sendChat drops
blanks; one chat row per send (drop textless server feed echo);
chat field keeps focus after send. Playback libass true; sdk floor
3.13. Handoff 9-11: 9+10 fixed, 11 jumpy seek still open.
Docs: handoff/roadmap/protocol record all of the above; few-commits
preference going forward.
This commit is contained in:
foxyz committed 2026-09-12 11:42:18 +03:00
1 parent 3303d88a5b
commit ff154c5030
26 files changed
+1147 -881

No files matched your search

+25 -22
View File
@@ -86,8 +86,7 @@ class _ConnectProfileCardState extends State<ConnectProfileCard> {
return;
} catch (_) {
if (!mounted) return;
setState(() => _error =
'could not read that image — pick a PNG, JPG or WebP photo');
setState(() => _error = 'could not read that image — pick a PNG, JPG or WebP photo');
return;
}
_avatarPath = path;
@@ -102,25 +101,25 @@ class _ConnectProfileCardState extends State<ConnectProfileCard> {
@override
Widget build(BuildContext context) {
return Row(
return Column(
crossAxisAlignment: .center,
mainAxisSize: MainAxisSize.min,
spacing: 12,
children: [
GestureDetector(
onTap: _pickAvatar,
ClipOval(
clipBehavior: .antiAlias,
child: Tooltip(
message: 'Change avatar',
child: CircleAvatar(
radius: 22,
backgroundColor: Colors.grey.shade800,
backgroundImage: _preview != null ? MemoryImage(_preview!) : null,
child: _preview != null
? null
: _picking
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
child: Stack(
children: [
CircleAvatar(
radius: 64,
backgroundColor: Colors.transparent,
backgroundImage: _preview != null ? MemoryImage(_preview!) : null,
child: _preview != null
? null
: _picking
? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
: ListenableBuilder(
listenable: widget.name,
builder: (context, _) {
@@ -128,10 +127,17 @@ class _ConnectProfileCardState extends State<ConnectProfileCard> {
return Text(t.isEmpty ? '?' : t[0].toUpperCase());
},
),
),
Positioned.fill(
child: Material(
type: .transparency,
child: InkWell(onTap: _pickAvatar),
),
),
],
),
),
),
const SizedBox(width: 12),
SizedBox(
width: 180,
child: Column(
@@ -140,10 +146,7 @@ class _ConnectProfileCardState extends State<ConnectProfileCard> {
children: [
TextField(
controller: widget.name,
decoration: const InputDecoration(
labelText: 'Display name',
isDense: true,
),
decoration: const InputDecoration(labelText: 'Display name', isDense: true),
onChanged: (_) {
SessionState.instance.lastForm.name = widget.name.text.trim();
},