using JiDangJia.Services; using JiDangJia.Core; namespace JiDangJia.Views; public sealed class UnlockPage : PrivatePage { private readonly Label message=Ui.Text("",13,Ui.Red); private readonly Label dots=Ui.Text("○ ○ ○ ○ ○ ○",27,Ui.Bronze,true); private string pin=""; private bool busy,appeared,visible; public UnlockPage() { Title="账户已锁定";NavigationPage.SetHasNavigationBar(this,false); var body=Ui.Stack(Ui.Icon("shield",Ui.Gold,46),Ui.Text(AppProduct.Name+"已锁定",25,bold:true),Ui.Text(AuthClient.Current.Name,14,Ui.Muted)); if(AppLock.UsesPin) { dots.HorizontalTextAlignment=TextAlignment.Center;body.Add(Ui.Text("输入 6 位数字密码,输满自动解锁",13,Ui.Muted));body.Add(dots);body.Add(message); var keys=new Grid{ColumnDefinitions=[new(GridLength.Star),new(GridLength.Star),new(GridLength.Star)],RowDefinitions=[new(GridLength.Auto),new(GridLength.Auto),new(GridLength.Auto),new(GridLength.Auto)],ColumnSpacing=10,RowSpacing=10}; string[] labels=["1","2","3","4","5","6","7","8","9","清空","0","删除"]; for(int i=0;i { if(busy)return;if(key=="清空")pin="";else if(key=="删除")pin=pin.Length>0?pin[..^1]:"";else if(pin.Length<6)pin+=key; Draw();if(pin.Length==6)await TryUnlock(pin,false); },false);button.HeightRequest=58;button.FontSize=key.Length==1?26:16;SemanticProperties.SetDescription(button,key);keys.Add(button,i%3,i/3); } body.Add(keys); } else { var password=new Entry{IsPassword=true,Placeholder="输入原解锁密码",MaxLength=128};body.Add(password);body.Add(message);body.Add(Ui.Button("密码解锁",()=>TryUnlock(password.Text,false))); body.Add(Ui.Text("原解锁密码继续有效,可在设置中改为 6 位数字密码。",11,Ui.Muted)); } if(AppLock.Fingerprint)body.Add(Ui.Button("指纹解锁",()=>TryUnlock(null,true),false)); body.Add(Ui.Button("忘记解锁密码",async()=>{if(busy)return;var secret=await PasswordDialog.Ask(this,"重置本机解锁","联网验证登录密码后,关闭本账户的本机解锁设置");if(secret is not null)await AppLock.Forgot(secret);},false)); body.Add(Ui.Button("退出 / 切换账户",async()=>{if(busy)return;AppLock.Abandon();await AuthClient.Current.Logout();LoginPage.ShowLogin();},false));body.Padding=new Thickness(25,35,25,25);Content=new ScrollView{Content=body}; } private void Draw()=>dots.Text=string.Join(" ",Enumerable.Range(0,6).Select(i=>itrue; protected override async void OnAppearing(){base.OnAppearing();visible=true;if(AuthClient.Current.AccountId.Length==0){AppLock.Abandon();LoginPage.ShowLogin();return;}if(!appeared&&AppLock.Fingerprint){appeared=true;await TryUnlock(null,true);}} protected override void OnDisappearing(){visible=false;BiometricUnlock.Cancel();base.OnDisappearing();} } public sealed class SecurityPage : PrivatePage { private readonly Action? retire; private readonly Label status=Ui.Text("",14,Ui.Bronze); #if COMMUNITY_APP private const string ClearScope="清除此设备本账户的社群草稿、照片缓存和本人可见的服务器聊天记录。方方聊天记录、账号、卡密授权、认证与已发布内容保留。"; public SecurityPage():this((Action?)null){} #else private const string ClearScope="清除此设备本账户的账目、经营记录、照片、本机自动备份、草稿与缓存。账号与卡密授权保留。外部导出文件需自行删除。"; public SecurityPage(Database database):this(database.Retire){} #endif private SecurityPage(Action? retire) { this.retire=retire;Title="密码 / 指纹与数据清除";var first=new Entry{IsPassword=true,Placeholder="设置 6 位数字解锁密码",Keyboard=Keyboard.Numeric,MaxLength=6};var second=new Entry{IsPassword=true,Placeholder="再次输入 6 位数字密码",Keyboard=Keyboard.Numeric,MaxLength=6};var finger=new Switch{OnColor=Ui.Bronze}; foreach(var entry in new[]{first,second})entry.TextChanged+=(_,_)=>{var digits=new string((entry.Text??"").Where(c=>c is >='0' and <='9').ToArray());if(entry.Text!=digits)entry.Text=digits;}; var body=Ui.Stack(Ui.Card(Ui.Stack(Ui.Section("本账户的本机解锁"),status,Ui.Text("可自行开启。解锁密码独立于登录密码;退出到后台或重新启动时验证。指纹不可用时使用密码。",12,Ui.Muted),first,second,Ui.Spread(Ui.Text("同时开启指纹 / 设备生物识别"),finger),Ui.Button("开启 / 更新解锁设置",async()=>{await AppLock.Set(first.Text??"",second.Text??"",finger.IsToggled);first.Text=second.Text="";Refresh();}),Ui.Button("关闭解锁设置",async()=>{var password=await PasswordDialog.Ask(this,"关闭本机解锁","输入当前解锁密码");if(password is not null){await AppLock.Disable(password);Refresh();}},false))),Ui.Card(Ui.Stack(Ui.Section("一键清除当前账户数据"),Ui.Text(ClearScope,13,Ui.Muted),Ui.Button("清除所有数据",Clear,false))));body.Padding=18;Content=new ScrollView{Content=body}; } protected override async void OnAppearing(){base.OnAppearing();await AppLock.Load();Refresh();} private void Refresh()=>status.Text=AppLock.Enabled?"已开启密码解锁"+(AppLock.Fingerprint?"与指纹解锁":""):"未开启,可自行设置"; private async Task Clear() { if(!await DisplayAlertAsync("清除本账户数据",ClearScope+" 清除后无法恢复,继续需两次输入登录密码。","继续","取消"))return; var first=await PasswordDialog.Ask(this,"确认清除(1 / 2)","输入登录密码");if(first is null)return;var second=await PasswordDialog.Ask(this,"确认清除(2 / 2)","再次输入登录密码");if(second is null)return; await AccountDataClear.Clear(first,second,retire); } }