Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Added proper support for RTL languages #16514

Draft
wants to merge 37 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ba3d280
CQ: Add Win32 methods
XTorLukas Nov 23, 2024
bfc8002
CQ: Create SourceGenerator
XTorLukas Nov 23, 2024
52daef5
Feature: Implemented service `RealTimeLayoutService`
XTorLukas Nov 23, 2024
85b8f95
CQ: Change visibility
XTorLukas Nov 24, 2024
e7668e4
CQ: Correct change CurrentCulture
XTorLukas Nov 24, 2024
ae06d2d
CQ: Fix DragRegions
XTorLukas Nov 24, 2024
88b8f21
Fix: Use guid in the name
XTorLukas Nov 24, 2024
e61ee02
Feature: Add all Dialogs to RealRimeLayout
XTorLukas Nov 24, 2024
46cff34
CQ: Add FilePropertiesPage
XTorLukas Nov 24, 2024
37c35e2
CQ: Fix
XTorLukas Nov 24, 2024
4f551c1
CQ: Add comments
XTorLukas Nov 24, 2024
d515296
CQ: Add licence header
XTorLukas Nov 24, 2024
16e8842
CQ: Redesign the code
XTorLukas Nov 26, 2024
58c9adb
CQ: Fix
XTorLukas Nov 26, 2024
0344538
CQ: Add interface for class
XTorLukas Nov 26, 2024
8d5e95f
Fix: Solve problem with null reference
XTorLukas Nov 26, 2024
28e8805
CQ: Updates
XTorLukas Nov 26, 2024
67d6e34
Merge branch 'main' into xtorlukas/Featue-RealTimeLayoutUpdate
XTorLukas Nov 26, 2024
dde4c74
CQ: Removal of unnecessary parts
XTorLukas Nov 26, 2024
d8c717c
CQ: Set static FlowDirection
XTorLukas Nov 26, 2024
580e4f5
CQ: Update
XTorLukas Nov 26, 2024
a0cb941
CQ: Only one create field
XTorLukas Nov 26, 2024
77b7aa2
CQ: Add comments
XTorLukas Nov 26, 2024
2e56817
Fix: Arrows in RTL/LTR not visibility correctly
XTorLukas Nov 26, 2024
37e34a9
CQ: Add for Animated Icon
XTorLukas Nov 27, 2024
d591ae3
CQ: Correction
XTorLukas Nov 27, 2024
2a3eac4
CQ: Add gap
XTorLukas Nov 27, 2024
7f7e660
CQ: Turn off RealTime feature
XTorLukas Nov 29, 2024
31440a4
Revert: Gap changes
XTorLukas Dec 1, 2024
596c16e
Merge branch 'xtorlukas/Featue-RealTimeLayoutUpdate' into xtorlukas/F…
XTorLukas Dec 1, 2024
ca698e2
CQ: Add Forward & Back arrow correctly
XTorLukas Dec 1, 2024
38e6465
CQ: Add `FlowDirectionChanged` event
XTorLukas Dec 1, 2024
d7b8474
Merge branch 'xtorlukas/Fix-WrongArrowInRTL' into xtorlukas/Featue-Re…
XTorLukas Dec 1, 2024
702f84b
CQ: Fix Forward & Back buttons for RTL
XTorLukas Dec 1, 2024
0bd2cd5
Fix
XTorLukas Dec 1, 2024
05b3046
CQ: Fix `MainPropertiesPage` drag area for RTL
XTorLukas Dec 2, 2024
004be1b
CQ: ProgressRing fix in RTL
XTorLukas Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Files.App.CsWin32/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,5 @@ IApplicationDocumentLists
ApplicationDocumentLists
IApplicationActivationManager
MENU_ITEM_TYPE
SetWindowLongPtr
GetWindowLongPtr
8 changes: 8 additions & 0 deletions src/Files.App/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

using CommunityToolkit.WinUI.Helpers;
using Files.App.Helpers.Application;
using Files.App.Services.Content;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
Expand Down Expand Up @@ -97,6 +100,11 @@ async Task ActivateAsync()
var userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
var isLeaveAppRunning = userSettingsService.GeneralSettingsService.LeaveAppRunning;

var realTimeLayoutService = Ioc.Default.GetRequiredService<IRealTimeLayoutService>();
realTimeLayoutService.UpdateCulture(new(AppLanguageHelper.PreferredLanguage.Code));

MainWindow.Instance.InitializeContentLayout();
XTorLukas marked this conversation as resolved.
Show resolved Hide resolved

if (isStartupTask && !isLeaveAppRunning)
{
// Initialize and activate MainWindow
Expand Down
26 changes: 26 additions & 0 deletions src/Files.App/Data/Contracts/IRealTimeControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Data.Contracts
{
/// <summary>
/// Defines an interface for real-time control components that manage content layout updates.
/// </summary>
internal interface IRealTimeControl
{
/// <summary>
/// Gets the service for managing real-time layout updates.
/// </summary>
IRealTimeLayoutService RealTimeLayoutService { get; }

/// <summary>
/// Initializes the content layout for the control.
/// </summary>
void InitializeContentLayout();

/// <summary>
/// Updates the content layout of the control.
/// </summary>
void UpdateContentLayout();
}
}
65 changes: 65 additions & 0 deletions src/Files.App/Data/Contracts/IRealTimeLayoutService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using Microsoft.UI.Xaml;
using System.Globalization;

namespace Files.App.Data.Contracts
{
/// <summary>
/// Provides an interface for managing real-time layout updates and related operations.
/// </summary>
public interface IRealTimeLayoutService
{
/// <summary>
/// Occurs when the flow direction of the layout changes.
/// </summary>
public event EventHandler<FlowDirection>? FlowDirectionChanged;

/// <summary>
/// Gets the current flow direction for layout (e.g., LeftToRight or RightToLeft).
/// </summary>
FlowDirection FlowDirection { get; }

/// <summary>
/// Updates the culture settings for the layout.
/// </summary>
/// <param name="culture">The culture information to apply.</param>
void UpdateCulture(CultureInfo culture);

/// <summary>
/// Adds a callback for a <see cref="Window"/> implementing <see cref="IRealTimeWindow"/>.
/// The callback is automatically removed when the window is closed.
/// </summary>
/// <param name="target">The <see cref="Window"/> instance that implements <see cref="IRealTimeWindow"/>.</param>
/// <param name="callback">The action to be executed when the callback is triggered.</param>
void AddCallback(Window target, Action callback);

/// <summary>
/// Adds a callback for a <see cref="FrameworkElement"/> implementing <see cref="IRealTimeControl"/>.
/// The callback is automatically removed when the element is unloaded.
/// </summary>
/// <param name="target">The <see cref="FrameworkElement"/> instance that implements <see cref="IRealTimeControl"/>.</param>
/// <param name="callback">The action to be executed when the callback is triggered.</param>
void AddCallback(FrameworkElement target, Action callback);

/// <summary>
/// Updates the title bar layout of the specified window based on the current flow direction.
/// </summary>
/// <param name="window">The window whose title bar layout needs updating.</param>
/// <returns>True if the title bar layout was successfully updated; otherwise, false.</returns>
bool UpdateTitleBar(Window window);

/// <summary>
/// Updates the content layout of the specified window to match the current flow direction.
/// </summary>
/// <param name="window">The window whose content layout needs updating.</param>
void UpdateContent(Window window);

/// <summary>
/// Updates the content layout of the specified framework element to match the current flow direction.
/// </summary>
/// <param name="frameworkElement">The framework element whose content layout needs updating.</param>
void UpdateContent(FrameworkElement frameworkElement);
}
}
26 changes: 26 additions & 0 deletions src/Files.App/Data/Contracts/IRealTimeWindow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Data.Contracts
{
/// <summary>
/// Defines an interface for real-time window components that manage content layout updates.
/// </summary>
internal interface IRealTimeWindow
{
/// <summary>
/// Gets the service for managing real-time layout updates.
/// </summary>
IRealTimeLayoutService RealTimeLayoutService { get; }

/// <summary>
/// Initializes the content layout for the window.
/// </summary>
void InitializeContentLayout();

/// <summary>
/// Updates the content layout of the window.
/// </summary>
void UpdateContentLayout();
}
}
13 changes: 13 additions & 0 deletions src/Files.App/Data/Enums/ArrowSymbolType.cs
XTorLukas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Data.Enums
{
public enum ArrowSymbolType
{
Forward,
Back,
ChevronLeft,
ChevronRight
}
}
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/AddBranchDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Files.App.Dialogs
{
public sealed partial class AddBranchDialog : ContentDialog, IDialog<AddBranchDialogViewModel>
public sealed partial class AddBranchDialog : ContentDialog, IDialog<AddBranchDialogViewModel>, IRealTimeControl
XTorLukas marked this conversation as resolved.
Show resolved Hide resolved
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -21,6 +21,7 @@ public AddBranchDialogViewModel ViewModel
public AddBranchDialog()
{
InitializeComponent();
InitializeContentLayout();
}

public new async Task<DialogResult> ShowAsync() => (DialogResult)await base.ShowAsync();
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/AddItemDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Files.App.Dialogs
{
public sealed partial class AddItemDialog : ContentDialog, IDialog<AddItemDialogViewModel>
public sealed partial class AddItemDialog : ContentDialog, IDialog<AddItemDialogViewModel>, IRealTimeControl
{
private readonly IAddItemService addItemService = Ioc.Default.GetRequiredService<IAddItemService>();

Expand All @@ -24,6 +24,7 @@ public AddItemDialogViewModel ViewModel
public AddItemDialog()
{
InitializeComponent();
InitializeContentLayout();
}

public new async Task<DialogResult> ShowAsync()
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/BulkRenameDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Files.App.Dialogs
{
public sealed partial class BulkRenameDialog : ContentDialog, IDialog<BulkRenameDialogViewModel>
public sealed partial class BulkRenameDialog : ContentDialog, IDialog<BulkRenameDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -19,6 +19,7 @@ public BulkRenameDialogViewModel ViewModel
public BulkRenameDialog()
{
InitializeComponent();
InitializeContentLayout();
}

public new async Task<DialogResult> ShowAsync()
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Files.App.Dialogs
{
public sealed partial class CreateArchiveDialog : ContentDialog
public sealed partial class CreateArchiveDialog : ContentDialog, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand Down Expand Up @@ -63,6 +63,7 @@ public int CPUThreads
public CreateArchiveDialog()
{
InitializeComponent();
InitializeContentLayout();

ViewModel.PropertyChanged += ViewModel_PropertyChanged;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/CreateShortcutDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Files.App.Dialogs
{
public sealed partial class CreateShortcutDialog : ContentDialog, IDialog<CreateShortcutDialogViewModel>
public sealed partial class CreateShortcutDialog : ContentDialog, IDialog<CreateShortcutDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -23,6 +23,7 @@ public CreateShortcutDialogViewModel ViewModel
public CreateShortcutDialog()
{
InitializeComponent();
InitializeContentLayout();
this.Closing += CreateShortcutDialog_Closing;

InvalidPathWarning.SetBinding(TeachingTip.TargetProperty, new Binding()
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/CredentialDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Files.App.Dialogs
{
public sealed partial class CredentialDialog : ContentDialog, IDialog<CredentialDialogViewModel>
public sealed partial class CredentialDialog : ContentDialog, IDialog<CredentialDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -21,6 +21,7 @@ public CredentialDialogViewModel ViewModel
public CredentialDialog()
{
InitializeComponent();
InitializeContentLayout();
}

public new async Task<DialogResult> ShowAsync()
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/DecompressArchiveDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Files.App.Dialogs
{
public sealed partial class DecompressArchiveDialog : ContentDialog
public sealed partial class DecompressArchiveDialog : ContentDialog, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -22,6 +22,7 @@ public DecompressArchiveDialogViewModel ViewModel
public DecompressArchiveDialog()
{
InitializeComponent();
InitializeContentLayout();
}

private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/DynamicDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Files.App.Dialogs
{
public sealed partial class DynamicDialog : ContentDialog, IDisposable
public sealed partial class DynamicDialog : ContentDialog, IDisposable, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -31,6 +31,7 @@ public DynamicDialogResult DynamicResult
public DynamicDialog(DynamicDialogViewModel dynamicDialogViewModel)
{
InitializeComponent();
InitializeContentLayout();

dynamicDialogViewModel.HideDialog = Hide;
ViewModel = dynamicDialogViewModel;
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/ElevateConfirmDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Files.App.Dialogs
{
public sealed partial class ElevateConfirmDialog : ContentDialog, IDialog<ElevateConfirmDialogViewModel>
public sealed partial class ElevateConfirmDialog : ContentDialog, IDialog<ElevateConfirmDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -23,6 +23,7 @@ public ElevateConfirmDialogViewModel ViewModel
public ElevateConfirmDialog()
{
InitializeComponent();
InitializeContentLayout();
}

public new async Task<DialogResult> ShowAsync()
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/FileTooLargeDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Files.App.Dialogs
{
public sealed partial class FileTooLargeDialog : ContentDialog, IDialog<FileTooLargeDialogViewModel>
public sealed partial class FileTooLargeDialog : ContentDialog, IDialog<FileTooLargeDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -20,6 +20,7 @@ public FileTooLargeDialogViewModel ViewModel
public FileTooLargeDialog()
{
InitializeComponent();
InitializeContentLayout();
}

public new async Task<DialogResult> ShowAsync()
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Files.App.Dialogs
{
public sealed partial class FilesystemOperationDialog : ContentDialog, IDialog<FileSystemDialogViewModel>
public sealed partial class FilesystemOperationDialog : ContentDialog, IDialog<FileSystemDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -30,6 +30,7 @@ public FileSystemDialogViewModel ViewModel
public FilesystemOperationDialog()
{
InitializeComponent();
InitializeContentLayout();

MainWindow.Instance.SizeChanged += Current_SizeChanged;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/GitHubLoginDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Files.App.Dialogs
{
public sealed partial class GitHubLoginDialog : ContentDialog, IDialog<GitHubLoginDialogViewModel>
public sealed partial class GitHubLoginDialog : ContentDialog, IDialog<GitHubLoginDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -29,6 +29,7 @@ public GitHubLoginDialogViewModel ViewModel
public GitHubLoginDialog()
{
InitializeComponent();
InitializeContentLayout();
}

public new async Task<DialogResult> ShowAsync()
Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Dialogs/ReleaseNotesDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Files.App.Dialogs
{
public sealed partial class ReleaseNotesDialog : ContentDialog, IDialog<ReleaseNotesDialogViewModel>
public sealed partial class ReleaseNotesDialog : ContentDialog, IDialog<ReleaseNotesDialogViewModel>, IRealTimeControl
{
private FrameworkElement RootAppElement
=> (FrameworkElement)MainWindow.Instance.Content;
Expand All @@ -21,6 +21,7 @@ public ReleaseNotesDialogViewModel ViewModel
public ReleaseNotesDialog()
{
InitializeComponent();
InitializeContentLayout();

MainWindow.Instance.SizeChanged += Current_SizeChanged;
UpdateDialogLayout();
Expand Down
Loading