XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

STHApplication

【MAUI】寄当家——安卓端交易管理系统

公开
关注 0 Fork 0 Star 0
UTF-8
using JiDangJia.Contracts;
using JiDangJia.Core;
using JiDangJia.Services;
using Microsoft.Maui.Devices.Sensors;

namespace JiDangJia.Views;

internal sealed class PostingLocationField
{
    private readonly string account=AuthClient.Current.AccountId;
    private readonly CommunityPost? editing;
    private readonly Label label=Ui.Text("正在获取发布位置…",13,Ui.Bronze);
    private readonly SemaphoreSlim gate=new(1,1);
    private PublishLocation? location;
    public View View{get;}
    public PostingLocationField(CommunityPost? editing)
    {
        this.editing=editing;
        var body=Ui.Stack(Ui.Section("发布位置"),label,Ui.Text("自动获取所在城市与区域,无法手动修改。",11,Ui.Muted));
        if(editing?.LocationVerified==true)label.Text=editing.City+" · "+editing.PublishArea+"(原发布位置)";
        else body.Add(Ui.Button("重新定位",()=>Load(),false));View=Ui.Card(body);
    }
    public async Task Start(){try{await Load();}catch(Exception ex){label.Text=ex.Message;}}
    private async Task Load()
    {
        if(editing?.LocationVerified==true)return;
        await gate.WaitAsync();try
        {
            if(location is not null&&location.RecordedAt>DateTimeOffset.UtcNow.AddMinutes(-2))return;
            label.Text="正在获取发布位置…";
            if(await Permissions.RequestAsync<Permissions.LocationWhenInUse>()!=PermissionStatus.Granted)throw new InvalidOperationException("请允许定位后重新获取发布位置");
            using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(35));
            var fix=await Geolocation.Default.GetLocationAsync(new GeolocationRequest(GeolocationAccuracy.High,TimeSpan.FromSeconds(20)),timeout.Token)??throw new InvalidOperationException("未取得位置,请到信号良好处重试");
            if(fix.IsFromMockProvider)throw new InvalidOperationException("请关闭模拟位置后重新定位");
            if(fix.Accuracy is not >0 or >1000||fix.Timestamp<DateTimeOffset.UtcNow.AddMinutes(-5))throw new InvalidOperationException("定位精度不足,请开启精确定位后重试");
            var place=(await Geocoding.Default.GetPlacemarksAsync(fix.Latitude,fix.Longitude).WaitAsync(TimeSpan.FromSeconds(12),timeout.Token)).FirstOrDefault()??throw new InvalidOperationException("暂未识别所在城市,请稍后重新定位");
            string city=place.Locality??"";
            if(city.Length==0&&new[]{"北京","天津","上海","重庆"}.Any(s=>place.AdminArea?.Contains(s)==true))city=place.AdminArea!;
            if(city.Length==0)throw new InvalidOperationException("暂未识别所在城市,请稍后重新定位");
            if(account!=AuthClient.Current.AccountId)throw new OperationCanceledException("账户已切换");
            location=new(fix.Latitude,fix.Longitude,fix.Accuracy.Value,CityCatalog.Normalize(city),place.SubLocality??"",fix.Timestamp);
            label.Text=location.City+(location.Area.Length>0?" · "+location.Area:"")+"(自动定位)";
        }
        catch{location=null;label.Text="定位未完成,请重新定位";throw;}
        finally{gate.Release();}
    }
    public async Task<PublishLocation?> Get()
    {
        await Load();return location; // Existing publications keep the location held by the server.
    }
}