Skip to content

feat: Dynamically update desktop window title#845

Open
schembriaiden wants to merge 5 commits intoDonutWare:developfrom
schembriaiden:dynamic-window-titles
Open

feat: Dynamically update desktop window title#845
schembriaiden wants to merge 5 commits intoDonutWare:developfrom
schembriaiden:dynamic-window-titles

Conversation

@schembriaiden
Copy link
Copy Markdown
Contributor

@schembriaiden schembriaiden commented Mar 15, 2026

Pull Request Description

This pull request introduces a new context-aware window title system for the application, ensuring that the window title reflects the current navigation state and playback context. The changes span across model classes, UI scaffolds, and platform-specific code, enhancing user experience and accessibility. The most important changes are grouped below.

Window Title Management

  • Added a new windowTitleProvider (lib/providers/window_title_provider.dart) implementing a stack-based approach to manage window titles, updating them based on navigation and playback events, and synchronizing with the OS window manager.
  • Integrated window title updates into navigation (lib/widgets/navigation_scaffold/navigation_scaffold.dart) and detail screens (lib/screens/shared/detail_scaffold.dart), including stack management and title updates on navigation changes.
  • Updated playback logic to set or reset the window title based on the currently playing item (lib/providers/video_player_provider.dart).

Model Enhancements

  • Introduced windowTitle getters for ItemBaseModel, EpisodeModel, and SeasonModel, providing context-rich titles for playback and navigation.

UI and Accessibility Improvements

  • Updated detail screens to pass windowTitle to scaffolds, ensuring correct title display during navigation and playback (lib/screens/details_screens/episode_detail_screen.dart, lib/screens/details_screens/season_detail_screen.dart).
  • Improved accessibility by wrapping video widgets in ExcludeSemantics to prevent redundant screen reader output (lib/wrappers/players/lib_mdk.dart, lib/wrappers/players/lib_mpv.dart).
  • Minor UI refinements, including replacing a Hero widget with a simple ValueKey for mini player, and wrapping children in RepaintBoundary for performance (lib/widgets/navigation_scaffold/components/floating_player_bar.dart, lib/screens/shared/animated_fade_size.dart).

Platform Title Consistency

  • Updated Linux platform code to use "Fladder" (capitalized) as the application and window name for consistency.

Issue Being Fixed

Resolves #issue-number

Screenshots / Recordings

Checklist

  • If a new package was added, did you ensure it works for all supported platforms? Is the package well maintained
  • Check that any changes are related to the issue at hand.

@schembriaiden schembriaiden marked this pull request as ready for review March 15, 2026 18:54
@schembriaiden
Copy link
Copy Markdown
Contributor Author

schembriaiden commented Mar 15, 2026

I was not able to test this on Windows due to having Visual Studio 2026 installed which is only supported by flutter v3.38 onwards, but it works on both Linux and Mac

I have also not been able to test the music part as I do not have music on my Jellyfin server.

}

@override
String get windowTitle {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use the translated season/episode prefixes

String get title => name;

String get windowTitle {
if (jellyType == dto.BaseItemKind.audio) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fladder doesn't support audio yet was this added for a reason?

switchInCurve: Curves.easeInOutCubic,
switchOutCurve: Curves.easeInOutCubic,
child: child,
child: RepaintBoundary(child: child),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this change was included. I'm not even sure the RepaintBoundary does anything here, considering the AnimatedFade/Switcher already re-paint the entire widget anyway.

subscriptions.add(subscription);
}

// Reset the window title when playback stops (model becomes null).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not call this in the media_control_wrapper "stop" instead of adding a new listener.


Future<bool> loadPlaybackItem(PlaybackModel model, Duration startPosition) async {
await state.stop();
ref.read(windowTitleProvider.notifier).setPlayTitle(model.item.windowTitle);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for this, currently the OS playback controls are set in media_control_wrapper where this should also live.

) ??
const SizedBox.shrink(),
),
player.videoWidget(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was the hero removed?

child: AspectRatio(
aspectRatio: aspectRatio,
child: VideoPlayer(controller),
child: ExcludeSemantics(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to exclude semantics in the video players?

@PartyDonut
Copy link
Copy Markdown
Collaborator

Thanks for the implementation, few comments here and there. Let me know if anything is unclear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants