1.0 shell: one window with a party strip; protocol 9 profile + avatars by hash
The shell (lib/src/shell/) replaces the Home and session screens:
- Party strip: profile, Library / Schedule / Settings tabs, Join and
Host cards (hosting no longer takes media), status-ring avatar stack
with the member list, chat & activity panel, Leave.
- The real session player is mounted once and shown full, as a
draggable corner-snapping mini player, or fullscreen (window_manager,
party and toasts overlaid); the Video is never mounted twice.
- Profile popover with inline rename, colour and a crop picker (256 px
PNG), pushed live to the session; avatar toasts; waiting pill.
- Motion kit (fastEaseInToSlowEaseOut, fade-through, popovers,
mouse-drag/wheel horizontal scrolling).
- Library = the existing picker for now (restyled next round); Schedule
= the new SchedulePage; Settings = left nav over the existing panels.
Protocol 9 (packages/core, packages/server, sync client):
- {"t":"profile"} renames / changes the picture mid-session ("rename",
"avatar" feed actions); names are cleaned the same way at hello.
- state.members carry avatarHash; pictures are served once from
/a/<sid>/<token>/<hash> (PNG/JPEG/WebP/GIF by magic bytes only) and
cached by hash in the app (AvatarCache).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f790470935
commit
d29c12e4f0
62 files changed
+5777
-3572
No files matched your search
@@ -14,6 +14,7 @@ import '../playback/playback_controller.dart';
|
||||
import '../screens/home/picked_media.dart';
|
||||
import '../sfx/sfx.dart';
|
||||
import '../state/settings.dart';
|
||||
import '../sync/avatar_cache.dart';
|
||||
import '../sync/state_diff.dart';
|
||||
import '../sync/sync_client.dart';
|
||||
import '../sync/user_seek.dart';
|
||||
@@ -140,6 +141,8 @@ class SessionCoordinator {
|
||||
/// null when this app is not the host.
|
||||
Future<({String name, int size})?> Function(String path)? hostFile;
|
||||
final SyncClient sync = SyncClient();
|
||||
/// Member pictures by `avatarHash`, fetched from the server.
|
||||
late final AvatarCache avatars = AvatarCache(sync);
|
||||
final PlaybackController playback = PlaybackController();
|
||||
final StateDiff diff = StateDiff();
|
||||
|
||||
@@ -953,6 +956,26 @@ class SessionCoordinator {
|
||||
sync.sendChat(text);
|
||||
}
|
||||
|
||||
/// Name and/or picture (base64 PNG, empty removes it) change for
|
||||
/// everyone now; a later fresh join sends them too.
|
||||
void updateProfile({String? name, String? avatar}) {
|
||||
final p = _params;
|
||||
if (p != null) {
|
||||
_params = ConnectParams(
|
||||
host: p.host,
|
||||
port: p.port,
|
||||
secret: p.secret,
|
||||
name: name ?? p.name,
|
||||
avatar: avatar ?? p.avatar,
|
||||
mediaPath: p.mediaPath,
|
||||
linkUrl: p.linkUrl,
|
||||
hostKey: p.hostKey,
|
||||
media: p.media,
|
||||
);
|
||||
}
|
||||
sync.sendProfile(name: name, avatar: avatar);
|
||||
}
|
||||
|
||||
void kick(String memberId, {String reason = ''}) {
|
||||
markInput();
|
||||
sync.sendKick(memberId, reason: reason);
|
||||
@@ -1060,6 +1083,10 @@ class SessionCoordinator {
|
||||
|
||||
// ------------------------------------------------------------- jellyfin
|
||||
|
||||
/// A toast from outside the session (e.g. the Schedule tab's request
|
||||
/// results), shown like the session's own.
|
||||
void showToast(String text) => _pushToast(text);
|
||||
|
||||
void _pushToast(String text) {
|
||||
_toastId++;
|
||||
toasts.value = [
|
||||
|
||||
Reference in new issue
Block a user