@@ -198,7 +198,8 @@ public static Flyout CreateSettings(string currentTheme, string currentBackdropT
198198 Action < string > ? onLanguageSelected = null , Action < bool > ? onSlashToggled = null ,
199199 Action < Flyout > ? onShowAi = null , Action < Flyout > ? onShowPrompts = null ,
200200 string ? currentNoteStyle = null , Action < string > ? onNoteStyleSelected = null ,
201- string ? currentFont = null , Action < string > ? onFontSelected = null )
201+ string ? currentFont = null , Action < string > ? onFontSelected = null ,
202+ Action ? onResetPassword = null , Action ? onResetNotes = null )
202203 {
203204 var flyout = new Flyout ( ) ;
204205 flyout . FlyoutPresenterStyle = CreateFlyoutPresenterStyle ( 260 , 320 ) ;
@@ -332,6 +333,22 @@ static string FindLabel((string key, string label)[] items, string current)
332333 panel . Children . Add ( langBtn ) ;
333334 }
334335
336+ // Reset
337+ if ( onResetPassword != null || onResetNotes != null )
338+ {
339+ panel . Children . Add ( CreateSeparator ( ) ) ;
340+ var resetBtn = CreateNavigateButton ( Lang . T ( "reset" ) , ( ) =>
341+ ShowResetSubPanel ( flyout , onResetPassword , onResetNotes ) ) ;
342+ resetBtn . Tag = Lang . T ( "reset" ) + " Réinitialiser Reset" ;
343+ // Red text
344+ if ( resetBtn . Content is Grid rg )
345+ foreach ( var child in rg . Children )
346+ if ( child is TextBlock rtb )
347+ rtb . Foreground = new SolidColorBrush ( Windows . UI . Color . FromArgb ( 255 , 255 , 99 , 99 ) ) ;
348+ allButtons . Add ( resetBtn ) ;
349+ panel . Children . Add ( resetBtn ) ;
350+ }
351+
335352 // Search
336353 panel . Children . Add ( CreateSeparator ( ) ) ;
337354 var searchBox = new TextBox
@@ -674,6 +691,238 @@ internal static Button CreateButton(ActionItem action, Action handler)
674691 return btn ;
675692 }
676693
694+ // ── Reset sub-panel ──
695+
696+ private static void ShowResetSubPanel ( Flyout flyout , Action ? onResetPassword , Action ? onResetNotes )
697+ {
698+ var panel = CreateSubPanelWithHeader ( Lang . T ( "reset" ) , ( ) =>
699+ {
700+ // Back: re-show would require recreating settings; just hide
701+ flyout . Hide ( ) ;
702+ } ) ;
703+
704+ if ( onResetPassword != null )
705+ {
706+ var pwBtn = CreateNavigateButton ( Lang . T ( "reset_password" ) , ( ) =>
707+ ShowResetConfirmPanel ( flyout , Lang . T ( "reset_password" ) , Lang . T ( "reset_password_warn" ) , ( ) =>
708+ {
709+ flyout . Hide ( ) ;
710+ onResetPassword ( ) ;
711+ } , onResetPassword , onResetNotes , requirePassword : true ) ) ;
712+ panel . Children . Add ( pwBtn ) ;
713+ }
714+
715+ if ( onResetNotes != null )
716+ {
717+ var notesBtn = CreateNavigateButton ( Lang . T ( "reset_notes" ) , ( ) =>
718+ ShowResetConfirmPanel ( flyout , Lang . T ( "reset_notes" ) , Lang . T ( "reset_notes_warn" ) , ( ) =>
719+ {
720+ flyout . Hide ( ) ;
721+ onResetNotes ( ) ;
722+ } , onResetPassword , onResetNotes ) ) ;
723+ panel . Children . Add ( notesBtn ) ;
724+ }
725+
726+ flyout . Content = panel ;
727+ }
728+
729+ private static void ShowResetConfirmPanel ( Flyout flyout , string title , string warning , Action onConfirm ,
730+ Action ? onResetPassword = null , Action ? onResetNotes = null , bool requirePassword = false )
731+ {
732+ var panel = CreateSubPanelWithHeader ( title , ( ) =>
733+ ShowResetSubPanel ( flyout , onResetPassword , onResetNotes ) ) ;
734+
735+ var warningText = new TextBlock
736+ {
737+ Text = warning ,
738+ FontSize = 12 ,
739+ MaxWidth = 250 ,
740+ TextWrapping = TextWrapping . Wrap ,
741+ Foreground = new SolidColorBrush ( Windows . UI . Color . FromArgb ( 255 , 255 , 99 , 99 ) ) ,
742+ Margin = new Thickness ( 8 , 6 , 8 , 6 ) ,
743+ Opacity = 0.9 ,
744+ } ;
745+ panel . Children . Add ( warningText ) ;
746+
747+ PasswordBox ? passwordBox = null ;
748+ TextBlock ? errorText = null ;
749+
750+ if ( requirePassword )
751+ {
752+ passwordBox = new PasswordBox
753+ {
754+ PlaceholderText = Lang . T ( "master_password" ) ,
755+ FontSize = 12 ,
756+ Margin = new Thickness ( 6 , 4 , 6 , 0 ) ,
757+ } ;
758+ panel . Children . Add ( passwordBox ) ;
759+
760+ errorText = new TextBlock
761+ {
762+ FontSize = 11 ,
763+ Foreground = new SolidColorBrush ( Windows . UI . Color . FromArgb ( 255 , 255 , 99 , 99 ) ) ,
764+ Margin = new Thickness ( 8 , 0 , 8 , 0 ) ,
765+ Visibility = Visibility . Collapsed ,
766+ } ;
767+ panel . Children . Add ( errorText ) ;
768+ }
769+
770+ panel . Children . Add ( CreateSeparator ( ) ) ;
771+
772+ var confirmBtn = new Button
773+ {
774+ HorizontalAlignment = HorizontalAlignment . Stretch ,
775+ HorizontalContentAlignment = HorizontalAlignment . Stretch ,
776+ Background = new SolidColorBrush ( Microsoft . UI . Colors . Transparent ) ,
777+ BorderThickness = new Thickness ( 0 ) ,
778+ Padding = new Thickness ( 8 , 5 , 8 , 5 ) ,
779+ CornerRadius = new CornerRadius ( 4 ) ,
780+ MinHeight = 0 ,
781+ Content = new TextBlock
782+ {
783+ Text = Lang . T ( "reset_confirm" ) ,
784+ FontSize = 12 ,
785+ Foreground = new SolidColorBrush ( Windows . UI . Color . FromArgb ( 255 , 255 , 99 , 99 ) ) ,
786+ }
787+ } ;
788+ confirmBtn . Click += ( _ , _ ) =>
789+ {
790+ if ( requirePassword && passwordBox != null && errorText != null )
791+ {
792+ if ( string . IsNullOrEmpty ( passwordBox . Password ) )
793+ {
794+ errorText . Text = Lang . T ( "password_required" ) ;
795+ errorText . Visibility = Visibility . Visible ;
796+ return ;
797+ }
798+ var storedHash = AppSettings . LoadMasterPasswordHash ( ) ;
799+ if ( storedHash != null && AppSettings . HashPassword ( passwordBox . Password ) != storedHash )
800+ {
801+ errorText . Text = Lang . T ( "wrong_password" ) ;
802+ errorText . Visibility = Visibility . Visible ;
803+ return ;
804+ }
805+ }
806+ onConfirm ( ) ;
807+ } ;
808+ panel . Children . Add ( confirmBtn ) ;
809+
810+ flyout . Content = panel ;
811+ }
812+
813+ // ── Lock / Password flyouts ──
814+
815+ public static void ShowCreatePasswordFlyout ( FrameworkElement target , Action < string > onPasswordCreated )
816+ {
817+ var flyout = new Flyout ( ) ;
818+ flyout . FlyoutPresenterStyle = CreateFlyoutPresenterStyle ( ) ;
819+
820+ var panel = new StackPanel { Spacing = 4 } ;
821+ panel . Children . Add ( CreateHeader ( Lang . T ( "create_password" ) ) ) ;
822+ panel . Children . Add ( CreateSeparator ( ) ) ;
823+
824+ var passwordBox = new PasswordBox
825+ {
826+ PlaceholderText = Lang . T ( "master_password" ) ,
827+ FontSize = 12 ,
828+ Margin = new Thickness ( 6 , 4 , 6 , 0 ) ,
829+ } ;
830+ panel . Children . Add ( passwordBox ) ;
831+
832+ var confirmBox = new PasswordBox
833+ {
834+ PlaceholderText = Lang . T ( "confirm_password" ) ,
835+ FontSize = 12 ,
836+ Margin = new Thickness ( 6 , 0 , 6 , 0 ) ,
837+ } ;
838+ panel . Children . Add ( confirmBox ) ;
839+
840+ var errorText = new TextBlock
841+ {
842+ FontSize = 11 ,
843+ Foreground = new SolidColorBrush ( Windows . UI . Color . FromArgb ( 255 , 255 , 99 , 99 ) ) ,
844+ Margin = new Thickness ( 8 , 0 , 8 , 0 ) ,
845+ Visibility = Visibility . Collapsed ,
846+ } ;
847+ panel . Children . Add ( errorText ) ;
848+
849+ panel . Children . Add ( CreateSeparator ( ) ) ;
850+
851+ var confirmBtn = CreateCheckItem ( "OK" , false , ( ) =>
852+ {
853+ if ( string . IsNullOrEmpty ( passwordBox . Password ) )
854+ {
855+ errorText . Text = Lang . T ( "password_required" ) ;
856+ errorText . Visibility = Visibility . Visible ;
857+ return ;
858+ }
859+ if ( passwordBox . Password != confirmBox . Password )
860+ {
861+ errorText . Text = Lang . T ( "passwords_dont_match" ) ;
862+ errorText . Visibility = Visibility . Visible ;
863+ return ;
864+ }
865+ flyout . Hide ( ) ;
866+ onPasswordCreated ( passwordBox . Password ) ;
867+ } ) ;
868+ panel . Children . Add ( confirmBtn ) ;
869+
870+ flyout . Content = panel ;
871+ flyout . ShowAt ( target ) ;
872+ }
873+
874+ public static void ShowEnterPasswordFlyout ( FrameworkElement target , string storedHash , Action onSuccess )
875+ {
876+ var flyout = new Flyout ( ) ;
877+ flyout . FlyoutPresenterStyle = CreateFlyoutPresenterStyle ( ) ;
878+
879+ var panel = new StackPanel { Spacing = 4 } ;
880+ panel . Children . Add ( CreateHeader ( Lang . T ( "enter_password" ) ) ) ;
881+ panel . Children . Add ( CreateSeparator ( ) ) ;
882+
883+ var passwordBox = new PasswordBox
884+ {
885+ PlaceholderText = Lang . T ( "master_password" ) ,
886+ FontSize = 12 ,
887+ Margin = new Thickness ( 6 , 4 , 6 , 0 ) ,
888+ } ;
889+ panel . Children . Add ( passwordBox ) ;
890+
891+ var errorText = new TextBlock
892+ {
893+ FontSize = 11 ,
894+ Foreground = new SolidColorBrush ( Windows . UI . Color . FromArgb ( 255 , 255 , 99 , 99 ) ) ,
895+ Margin = new Thickness ( 8 , 0 , 8 , 0 ) ,
896+ Visibility = Visibility . Collapsed ,
897+ } ;
898+ panel . Children . Add ( errorText ) ;
899+
900+ panel . Children . Add ( CreateSeparator ( ) ) ;
901+
902+ var confirmBtn = CreateCheckItem ( "OK" , false , ( ) =>
903+ {
904+ if ( string . IsNullOrEmpty ( passwordBox . Password ) )
905+ {
906+ errorText . Text = Lang . T ( "password_required" ) ;
907+ errorText . Visibility = Visibility . Visible ;
908+ return ;
909+ }
910+ var inputHash = AppSettings . HashPassword ( passwordBox . Password ) ;
911+ if ( inputHash != storedHash )
912+ {
913+ errorText . Text = Lang . T ( "wrong_password" ) ;
914+ errorText . Visibility = Visibility . Visible ;
915+ return ;
916+ }
917+ flyout . Hide ( ) ;
918+ onSuccess ( ) ;
919+ } ) ;
920+ panel . Children . Add ( confirmBtn ) ;
921+
922+ flyout . Content = panel ;
923+ flyout . ShowAt ( target ) ;
924+ }
925+
677926 public static void ShowVoiceModelsPanel ( Flyout flyout , string ? currentModelId ,
678927 XamlRoot xamlRoot ,
679928 Action < SttModelInfo > onSelectModel , Action < SttModelInfo > onDeleteModel , Action onBack , Action onRebuild ,
0 commit comments