1919package com .sevtinge .hyperceiler .settings ;
2020
2121import android .app .Activity ;
22+ import android .app .AlarmManager ;
23+ import android .app .PendingIntent ;
2224import android .content .ComponentName ;
25+ import android .content .Context ;
2326import android .content .Intent ;
2427import android .content .pm .PackageManager ;
2528import android .graphics .Rect ;
2629import android .net .Uri ;
30+ import android .text .TextUtils ;
2731import android .widget .Toast ;
2832
2933import androidx .activity .result .ActivityResultLauncher ;
3539import com .sevtinge .hyperceiler .R ;
3640import com .sevtinge .hyperceiler .common .base .BasePreferenceFragment ;
3741import com .sevtinge .hyperceiler .common .log .LogLevelManager ;
42+ import com .sevtinge .hyperceiler .common .utils .AppSettingsStore ;
3843import com .sevtinge .hyperceiler .common .utils .PrefsBridge ;
3944import com .sevtinge .hyperceiler .common .utils .api .ProjectApi ;
4045import com .sevtinge .hyperceiler .home .utils .HeaderManager ;
4146import com .sevtinge .hyperceiler .libhook .utils .api .BackupUtils ;
4247import com .sevtinge .hyperceiler .sub .ScopePickerActivity ;
4348import com .sevtinge .hyperceiler .ui .LauncherActivity ;
49+ import com .sevtinge .hyperceiler .ui .SplashActivity ;
4450import com .sevtinge .hyperceiler .utils .DialogHelper ;
4551import com .sevtinge .hyperceiler .utils .LanguageHelper ;
4652import com .sevtinge .hyperceiler .utils .ScopeManager ;
4753
4854import java .util .ArrayList ;
55+ import java .util .LinkedHashSet ;
4956import java .util .Set ;
5057
5158import fan .appcompat .app .AlertDialog ;
5259import fan .internal .utils .ViewUtils ;
5360import fan .preference .DropDownPreference ;
54- import fan .provider .Settings ;
5561import fan .provision .OobeUtils ;
5662
5763public class SettingsFragment extends BasePreferenceFragment
@@ -98,7 +104,13 @@ public int getPreferenceScreenResId() {
98104
99105 @ Override
100106 public void initPrefs () {
101- int mIconMode = PrefsBridge .getStringAsInt ("prefs_key_settings_icon" , 0 );
107+ int mIconMode = AppSettingsStore .getIconIndex (requireContext ());
108+ int iconModeStyle = AppSettingsStore .getIconModeIndex (requireContext ());
109+ int languageIndex = AppSettingsStore .getAppLanguageIndex (requireContext ());
110+ boolean hideAppIconEnabled = AppSettingsStore .isHideAppIconEnabled (requireContext ());
111+ boolean isFloating = AppSettingsStore .isFloatNavEnabled (requireContext ());
112+ boolean scopeSyncEnabled = AppSettingsStore .isScopeSyncEnabled (requireContext ());
113+
102114 mIconModePreference = findPreference ("prefs_key_settings_icon" );
103115 mIconModeValue = findPreference ("prefs_key_settings_icon_mode" );
104116 mLanguage = findPreference ("prefs_key_settings_app_language" );
@@ -108,14 +120,56 @@ public void initPrefs() {
108120 mScopeSyncPreference = findPreference ("prefs_key_settings_scope_sync" );
109121 mScopePreference = findPreference ("prefs_key_settings_scope" );
110122
123+ if (mHideAppIcon != null ) {
124+ mHideAppIcon .setPersistent (false );
125+ }
126+ if (mFloatBottomPreference != null ) {
127+ mFloatBottomPreference .setPersistent (false );
128+ }
129+ if (mScopeSyncPreference != null ) {
130+ mScopeSyncPreference .setPersistent (false );
131+ }
132+ if (mIconModePreference != null ) {
133+ mIconModePreference .setPersistent (false );
134+ }
135+ if (mIconModeValue != null ) {
136+ mIconModeValue .setPersistent (false );
137+ }
138+ if (mLanguage != null ) {
139+ mLanguage .setPersistent (false );
140+ }
141+
142+ if (mHideAppIcon != null ) {
143+ mHideAppIcon .setChecked (hideAppIconEnabled );
144+ }
145+ if (mFloatBottomPreference != null ) {
146+ mFloatBottomPreference .setChecked (isFloating );
147+ }
148+ if (mScopeSyncPreference != null ) {
149+ mScopeSyncPreference .setChecked (scopeSyncEnabled );
150+ }
151+ if (mIconModePreference != null ) {
152+ mIconModePreference .setValueIndex (mIconMode );
153+ }
154+ if (mIconModeValue != null ) {
155+ mIconModeValue .setValueIndex (iconModeStyle );
156+ }
157+ if (mLanguage != null ) {
158+ mLanguage .setValueIndex (languageIndex );
159+ }
160+
111161 setIconMode (mIconMode );
112162 mIconModePreference .setOnPreferenceChangeListener (this );
113- String language = LanguageHelper .getLanguage (requireContext ());
114- int value = LanguageHelper .resultIndex (LanguageHelper .APP_LANGUAGES , language );
115- mLanguage .setValueIndex (value );
116163
117164 mLanguage .setOnPreferenceChangeListener ((preference , o ) -> {
118- LanguageHelper .setIndexLanguage (getActivity (), Integer .parseInt ((String ) o ), true );
165+ int index = Integer .parseInt ((String ) o );
166+ AppSettingsStore .setAppLanguageIndex (requireContext (), index );
167+ LanguageHelper .setIndexLanguage (getActivity (), index , true );
168+ return true ;
169+ });
170+
171+ mIconModeValue .setOnPreferenceChangeListener ((preference , newValue ) -> {
172+ AppSettingsStore .setIconModeIndex (requireContext (), Integer .parseInt ((String ) newValue ));
119173 return true ;
120174 });
121175
@@ -124,11 +178,13 @@ public void initPrefs() {
124178
125179 if (mHideAppIcon != null ) {
126180 mHideAppIcon .setOnPreferenceChangeListener ((preference , o ) -> {
181+ boolean enabled = Boolean .TRUE .equals (o );
182+ AppSettingsStore .setHideAppIconEnabled (requireContext (), enabled );
127183
128184 PackageManager pm = requireActivity ().getPackageManager ();
129185 int mComponentEnabledState ;
130186
131- if (( Boolean ) o ) {
187+ if (enabled ) {
132188 mComponentEnabledState = PackageManager .COMPONENT_ENABLED_STATE_ENABLED ;
133189 } else {
134190 mComponentEnabledState = PackageManager .COMPONENT_ENABLED_STATE_DISABLED ;
@@ -140,18 +196,24 @@ public void initPrefs() {
140196 }
141197
142198 mFloatBottomPreference .setOnPreferenceChangeListener ((preference , newValue ) -> {
143- //getSwitchManager().setFloatingStyle((Boolean) newValue);
144- Settings . Global . putBoolean ( getContext (). getContentResolver (), "settings_float_nav" , ( Boolean ) newValue );
199+ boolean enabled = Boolean . TRUE . equals ( newValue );
200+ AppSettingsStore . setFloatNavEnabled ( requireContext (), enabled );
145201 return true ;
146202 });
147203
148204 if (mScopeSyncPreference != null ) {
205+ updateScopePreferenceTitle (scopeSyncEnabled );
149206 mScopeSyncPreference .setOnPreferenceChangeListener ((preference , newValue ) -> {
150- if (Boolean .TRUE .equals (newValue )) {
207+ boolean enabled = Boolean .TRUE .equals (newValue );
208+ AppSettingsStore .setScopeSyncEnabled (requireContext (), enabled );
209+ if (enabled ) {
151210 HeaderManager .syncHeaderPreferencesToCurrentScope (requireContext ());
152211 }
212+ updateScopePreferenceTitle (enabled );
153213 return true ;
154214 });
215+ } else {
216+ updateScopePreferenceTitle (false );
155217 }
156218
157219 if (mScopePreference != null ) {
@@ -189,6 +251,7 @@ public boolean onPreferenceClick(@NonNull Preference preference) {
189251 getString (com .sevtinge .hyperceiler .core .R .string .reset_desc ),
190252 (dialog , which ) -> {
191253 PrefsBridge .clearAllByApp ();
254+ AppSettingsStore .resetGlobalToDefaults (requireContext ());
192255 OobeUtils .resetOobeState (requireContext ());
193256 Toast .makeText (getActivity (), com .sevtinge .hyperceiler .core .R .string .reset_okay , Toast .LENGTH_LONG ).show ();
194257 }
@@ -201,7 +264,9 @@ public boolean onPreferenceClick(@NonNull Preference preference) {
201264 @ Override
202265 public boolean onPreferenceChange (@ NonNull Preference preference , Object o ) {
203266 if (preference == mIconModePreference ) {
204- setIconMode (Integer .parseInt ((String ) o ));
267+ int index = Integer .parseInt ((String ) o );
268+ AppSettingsStore .setIconIndex (requireContext (), index );
269+ setIconMode (index );
205270 }
206271 return true ;
207272 }
@@ -292,34 +357,148 @@ private void processBackup(Uri uri) {
292357 private void processRestore (Uri uri ) {
293358 try {
294359 BackupUtils .handleReadDocument (requireContext (), uri );
360+ AppSettingsStore .syncGlobalFromPrefs (requireContext ());
295361 if (!HeaderManager .isScopeSyncEnabled ()) {
296- showDialog (getString (com .sevtinge .hyperceiler .core .R .string .rest_success ), getString (com .sevtinge .hyperceiler .core .R .string .rest_success_message ));
362+ showDialog (
363+ getString (com .sevtinge .hyperceiler .core .R .string .rest_success ),
364+ getString (com .sevtinge .hyperceiler .core .R .string .rest_success_message ),
365+ (dialog , which ) -> restartApp ()
366+ );
297367 return ;
298368 }
299369
300- Set <String > currentSelected = HeaderManager .getCurrentScopeManagedPackages (requireContext ());
301- Set <String > targetSelected = HeaderManager .getStoredScopeManagedPackages (requireContext ());
302- ScopeManager .applyScopeDiffAsync (requireContext (), currentSelected , targetSelected , (success , message ) -> {
303- if (!isAdded ()) {
304- return ;
305- }
306-
307- String restoreMessage = getString (com .sevtinge .hyperceiler .core .R .string .rest_success_message );
308- if (!success && message != null && !message .isEmpty ()) {
309- restoreMessage = restoreMessage + "\n \n " + message ;
310- }
311- showDialog (getString (com .sevtinge .hyperceiler .core .R .string .rest_success ), restoreMessage );
312- });
370+ Set <String > currentSelected = ScopeManager .normalizeScopePackages (
371+ HeaderManager .getCurrentScopeManagedPackages (requireContext ())
372+ );
373+ Set <String > restoredSelected = ScopeManager .normalizeScopePackages (
374+ HeaderManager .getStoredScopeManagedPackages (requireContext ())
375+ );
376+ Set <String > targetSelected = filterInstalledScopePackages (restoredSelected );
377+ Set <String > skippedPackages = new LinkedHashSet <>(restoredSelected );
378+ skippedPackages .removeAll (targetSelected );
379+
380+ Set <String > newlyAddedScopes = new LinkedHashSet <>(targetSelected );
381+ newlyAddedScopes .removeAll (currentSelected );
382+ if (!newlyAddedScopes .isEmpty ()) {
383+ showScopeAuthorizationNotice (newlyAddedScopes , () ->
384+ applyRestoredScopeDiff (currentSelected , targetSelected , skippedPackages )
385+ );
386+ } else {
387+ applyRestoredScopeDiff (currentSelected , targetSelected , skippedPackages );
388+ }
313389 } catch (Exception e ) {
314390 showDialog (getString (com .sevtinge .hyperceiler .core .R .string .rest_failed ), e .getMessage ());
315391 }
316392 }
317393
394+ private void applyRestoredScopeDiff (
395+ Set <String > currentSelected ,
396+ Set <String > targetSelected ,
397+ Set <String > skippedPackages
398+ ) {
399+ ScopeManager .applyScopeDiffAsync (requireContext (), currentSelected , targetSelected , (success , message ) -> {
400+ if (!isAdded ()) {
401+ return ;
402+ }
403+
404+ String restoreMessage = getString (com .sevtinge .hyperceiler .core .R .string .rest_success_message );
405+ if (!skippedPackages .isEmpty ()) {
406+ restoreMessage = restoreMessage + "\n \n " + getString (
407+ com .sevtinge .hyperceiler .core .R .string .rest_scope_skip_uninstalled ,
408+ TextUtils .join ("、" , skippedPackages )
409+ );
410+ }
411+ if (!success && message != null && !message .isEmpty ()) {
412+ restoreMessage = restoreMessage + "\n \n " + message ;
413+ }
414+ showDialog (
415+ getString (com .sevtinge .hyperceiler .core .R .string .rest_success ),
416+ restoreMessage ,
417+ (dialog , which ) -> restartApp ()
418+ );
419+ });
420+ }
421+
422+ private Set <String > filterInstalledScopePackages (Set <String > packages ) {
423+ Set <String > installedPackages = new LinkedHashSet <>();
424+ if (packages == null || packages .isEmpty ()) {
425+ return installedPackages ;
426+ }
427+
428+ for (String packageName : packages ) {
429+ if (isScopePackageInstalled (packageName )) {
430+ installedPackages .add (packageName );
431+ }
432+ }
433+ return installedPackages ;
434+ }
435+
436+ private boolean isScopePackageInstalled (String packageName ) {
437+ if (ScopeManager .isSystemScopePackage (packageName )) {
438+ return true ;
439+ }
440+
441+ try {
442+ requireContext ().getPackageManager ().getPackageInfo (packageName , PackageManager .MATCH_ALL );
443+ return true ;
444+ } catch (Exception ignored ) {
445+ return false ;
446+ }
447+ }
448+
449+ private void showScopeAuthorizationNotice (Set <String > newlyAddedScopes , Runnable onConfirmed ) {
450+ String scopeList = TextUtils .join ("、" , newlyAddedScopes );
451+ new AlertDialog .Builder (requireContext ())
452+ .setTitle (com .sevtinge .hyperceiler .core .R .string .rest_scope_authorize_title )
453+ .setMessage (getString (com .sevtinge .hyperceiler .core .R .string .rest_scope_authorize_notice , scopeList ))
454+ .setPositiveButton (android .R .string .ok , (dialog , which ) -> onConfirmed .run ())
455+ .show ();
456+ }
457+
318458 private void showDialog (String title , String message ) {
459+ showDialog (title , message , null );
460+ }
461+
462+ private void showDialog (String title , String message , android .content .DialogInterface .OnClickListener onClickListener ) {
319463 new AlertDialog .Builder (requireContext ())
320464 .setTitle (title )
321465 .setMessage (message )
322- .setPositiveButton (android .R .string .ok , null )
466+ .setPositiveButton (android .R .string .ok , onClickListener )
323467 .show ();
324468 }
469+
470+ private void updateScopePreferenceTitle (boolean scopeSyncEnabled ) {
471+ if (mScopePreference == null ) {
472+ return ;
473+ }
474+ mScopePreference .setTitle (scopeSyncEnabled
475+ ? com .sevtinge .hyperceiler .core .R .string .settings_scope_extra
476+ : com .sevtinge .hyperceiler .core .R .string .settings_scope );
477+ }
478+
479+ private void restartApp () {
480+ Context context = requireContext ().getApplicationContext ();
481+ Intent restartIntent = new Intent (context , SplashActivity .class )
482+ .addFlags (Intent .FLAG_ACTIVITY_NEW_TASK | Intent .FLAG_ACTIVITY_CLEAR_TASK );
483+
484+ PendingIntent pendingIntent = PendingIntent .getActivity (
485+ context ,
486+ 0 ,
487+ restartIntent ,
488+ PendingIntent .FLAG_CANCEL_CURRENT | PendingIntent .FLAG_IMMUTABLE
489+ );
490+
491+ AlarmManager alarmManager = (AlarmManager ) context .getSystemService (Context .ALARM_SERVICE );
492+ if (alarmManager != null ) {
493+ alarmManager .set (AlarmManager .RTC , System .currentTimeMillis () + 200 , pendingIntent );
494+ } else {
495+ context .startActivity (restartIntent );
496+ }
497+
498+ Activity activity = getActivity ();
499+ if (activity != null ) {
500+ activity .finishAffinity ();
501+ }
502+ android .os .Process .killProcess (android .os .Process .myPid ());
503+ }
325504}
0 commit comments