@@ -19,26 +19,74 @@ class VanillaInstallDisk(Adw.Bin):
1919 disks_group = Gtk .Template .Child ()
2020 no_disks_label = Gtk .Template .Child ()
2121 fs_combo = Gtk .Template .Child ()
22- fde_checkbox = Gtk .Template .Child ()
22+ fde_row = Gtk .Template .Child ()
23+ passphrase_entry = Gtk .Template .Child ()
24+ passphrase_confirm_entry = Gtk .Template .Child ()
25+ tpm_row = Gtk .Template .Child ()
2326
2427 def __init__ (self , window , ** kwargs ):
2528 super ().__init__ (** kwargs )
2629 self .__window = window
2730 self .__selected_device = None
31+ # Persisted FDE settings
32+ self .__fde_enabled = False
33+ self .__fde_passphrase = ""
34+ self .__fde_passphrase_confirm = ""
35+ self .__tpm_enabled = False
2836 # store tuples of (action_row, radio_button)
2937 self .__rows = []
30- # wire up FDE checkbox behavior (currently no extra inputs)
38+ # wire up FDE switch behavior
3139 try :
32- self .fde_checkbox .connect ("toggled" , self .__on_fde_toggled )
40+ self .fde_row .connect ("notify::active" , self .__on_fde_toggled )
41+ except Exception :
42+ pass
43+ # wire up passphrase entry changes
44+ try :
45+ self .passphrase_entry .connect ("changed" , self .__on_passphrase_changed )
46+ self .passphrase_confirm_entry .connect ("changed" , self .__on_passphrase_changed )
47+ except Exception :
48+ pass
49+ # wire up TPM switch
50+ try :
51+ self .tpm_row .connect ("notify::active" , self .__on_tpm_toggled )
3352 except Exception :
3453 pass
3554
3655 def set_page_active (self ):
3756 # Refresh available disks each time the page becomes active
3857 GLib .idle_add (self .refresh_drives )
58+ # Restore persisted FDE settings to UI
59+ self .__restore_fde_settings ()
3960
4061 def set_page_inactive (self ):
41- return
62+ # Persist current FDE settings before leaving the page
63+ self .__save_fde_settings ()
64+
65+ def __save_fde_settings (self ):
66+ """Save current FDE UI state to instance variables."""
67+ try :
68+ self .__fde_enabled = self .fde_row .get_active ()
69+ self .__fde_passphrase = self .passphrase_entry .get_text ()
70+ self .__fde_passphrase_confirm = self .passphrase_confirm_entry .get_text ()
71+ self .__tpm_enabled = self .tpm_row .get_active ()
72+ except Exception :
73+ pass
74+
75+ def __restore_fde_settings (self ):
76+ """Restore persisted FDE settings to UI widgets."""
77+ try :
78+ self .fde_row .set_active (self .__fde_enabled )
79+ self .passphrase_entry .set_text (self .__fde_passphrase )
80+ self .passphrase_confirm_entry .set_text (self .__fde_passphrase_confirm )
81+ self .tpm_row .set_active (self .__tpm_enabled )
82+ # Update visibility based on FDE state
83+ self .passphrase_entry .set_visible (self .__fde_enabled )
84+ self .passphrase_confirm_entry .set_visible (self .__fde_enabled )
85+ self .tpm_row .set_visible (self .__fde_enabled )
86+ if self .__fde_enabled :
87+ self .__update_passphrase_validation_ui ()
88+ except Exception :
89+ pass
4290
4391 def finish (self ):
4492 # Called when the user presses next. Ensure a device is selected and store it on the window.
@@ -61,11 +109,15 @@ def finish(self):
61109 fs = "btrfs"
62110 self .__window .install_target_fs = fs
63111
64- # Handle Full Disk Encryption selection (no passphrase inputs)
65- try :
66- self .__window .install_fde_enabled = bool (self .fde_checkbox .get_active ())
67- except Exception :
68- self .__window .install_fde_enabled = False
112+ # Handle Full Disk Encryption selection - save and use persisted values
113+ self .__save_fde_settings ()
114+ self .__window .install_fde_enabled = self .__fde_enabled
115+ if self .__fde_enabled :
116+ self .__window .install_fde_passphrase = self .__fde_passphrase
117+ self .__window .install_tpm_enabled = self .__tpm_enabled
118+ else :
119+ self .__window .install_fde_passphrase = None
120+ self .__window .install_tpm_enabled = False
69121 return True
70122
71123 def refresh_drives (self ):
@@ -154,10 +206,88 @@ def __on_radio_toggled(self, radio, path):
154206 else :
155207 row .remove_css_class ("selected" )
156208
209+ self .__update_ready_state ()
210+
211+ def __validate_passphrase (self ):
212+ """Check if passphrase meets requirements: min 8 chars and both fields match."""
213+ passphrase = self .passphrase_entry .get_text ()
214+ confirm = self .passphrase_confirm_entry .get_text ()
215+ if len (passphrase ) < 8 :
216+ return False
217+ if passphrase != confirm :
218+ return False
219+ return True
220+
221+ def __update_passphrase_validation_ui (self ):
222+ """Update visual validation state for passphrase fields."""
223+ passphrase = self .passphrase_entry .get_text ()
224+ confirm = self .passphrase_confirm_entry .get_text ()
225+
226+ # Validate passphrase field: must be at least 8 characters
227+ if len (passphrase ) == 0 :
228+ self .passphrase_entry .add_css_class ("error" )
229+ elif len (passphrase ) < 8 :
230+ self .passphrase_entry .add_css_class ("error" )
231+ else :
232+ self .passphrase_entry .remove_css_class ("error" )
233+
234+ # Validate confirmation field: must match passphrase
235+ if len (confirm ) == 0 or confirm != passphrase :
236+ self .passphrase_confirm_entry .add_css_class ("error" )
237+ else :
238+ self .passphrase_confirm_entry .remove_css_class ("error" )
239+
240+ def __clear_passphrase_validation_ui (self ):
241+ """Clear validation error styling from passphrase fields."""
242+ try :
243+ self .passphrase_entry .remove_css_class ("error" )
244+ self .passphrase_confirm_entry .remove_css_class ("error" )
245+ except Exception :
246+ pass
247+
248+ def __update_ready_state (self ):
249+ """Update the window ready state based on disk selection and FDE passphrase validity."""
250+ if not self .__selected_device :
251+ self .__window .set_ready (False )
252+ return
253+ # If FDE is enabled, passphrase must be valid
254+ try :
255+ if self .fde_row .get_active ():
256+ if not self .__validate_passphrase ():
257+ self .__window .set_ready (False )
258+ return
259+ except Exception :
260+ pass
157261 self .__window .set_ready (True )
158262
263+ def __on_passphrase_changed (self , entry ):
264+ """Called when either passphrase field changes."""
265+ self .__update_passphrase_validation_ui ()
266+ self .__save_fde_settings ()
267+ self .__update_ready_state ()
159268
160- def __on_fde_toggled (self , checkbox ):
161- # No passphrase inputs to manage; optionally could trigger readiness update.
162- # Keep selection gating on disk radio buttons only.
163- return
269+ def __on_fde_toggled (self , switch , pspec ):
270+ """Enable/disable passphrase fields and TPM row based on FDE selection."""
271+ fde_active = switch .get_active ()
272+ try :
273+ # Show/hide encryption-related rows
274+ self .passphrase_entry .set_visible (fde_active )
275+ self .passphrase_confirm_entry .set_visible (fde_active )
276+ self .tpm_row .set_visible (fde_active )
277+ # If FDE is disabled, reset TPM and clear passphrases
278+ if not fde_active :
279+ self .tpm_row .set_active (False )
280+ self .passphrase_entry .set_text ("" )
281+ self .passphrase_confirm_entry .set_text ("" )
282+ self .__clear_passphrase_validation_ui ()
283+ else :
284+ # Show validation state when FDE is enabled
285+ self .__update_passphrase_validation_ui ()
286+ except Exception :
287+ pass
288+ self .__save_fde_settings ()
289+ self .__update_ready_state ()
290+
291+ def __on_tpm_toggled (self , switch , pspec ):
292+ """Called when TPM auto-unlock is toggled."""
293+ self .__save_fde_settings ()
0 commit comments