feat(ui): Online Inbox settings tab + auth-code/PKCE login
New Settings tab: enable toggle, config fields, sign-in/out + status. OnlineLoginService runs the PKCE loopback flow (Duende.IdentityModel.OidcClient 7.1.0), opens the system browser, captures the callback, hands the refresh token to the Worker. en/de localized. Fixes: loopback callback URL built from host:port base (avoids doubled redirect path); PollIntervalSeconds threaded through the state DTO so it loads instead of resetting to 60. Visual layout + the live sign-in round-trip need manual verification. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -261,6 +261,99 @@
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{loc:Tr settings.onlineInbox.tabHeader}">
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="14" Margin="0,8,0,0">
|
||||
|
||||
<!-- Enable toggle + restart hint -->
|
||||
<StackPanel Spacing="4">
|
||||
<CheckBox IsChecked="{Binding OnlineInbox.Enabled, Mode=TwoWay}"
|
||||
Content="{loc:Tr settings.onlineInbox.enabledLabel}"/>
|
||||
<TextBlock Classes="meta" Text="{loc:Tr settings.onlineInbox.restartHint}"
|
||||
TextWrapping="Wrap" Opacity="0.6"/>
|
||||
</StackPanel>
|
||||
|
||||
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="0,1,0,0" Margin="0,2,0,0"/>
|
||||
|
||||
<!-- Auth status section -->
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Classes="section-label" Text="{loc:Tr settings.onlineInbox.statusSection}"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center"
|
||||
IsVisible="{Binding OnlineInbox.SignedIn}">
|
||||
<Border Width="8" Height="8" CornerRadius="4"
|
||||
Background="{DynamicResource StatusRunningBrush}"/>
|
||||
<TextBlock Classes="body" VerticalAlignment="Center"
|
||||
Text="{loc:Tr settings.onlineInbox.signedInStatus}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center"
|
||||
IsVisible="{Binding !OnlineInbox.SignedIn}">
|
||||
<Border Width="8" Height="8" CornerRadius="4"
|
||||
Background="{DynamicResource StatusIdleBrush}"/>
|
||||
<TextBlock Classes="body" VerticalAlignment="Center"
|
||||
Text="{loc:Tr settings.onlineInbox.signedOutStatus}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<Button Classes="btn"
|
||||
Content="{loc:Tr settings.onlineInbox.signInButton}"
|
||||
Command="{Binding OnlineInbox.SignInCommand}"
|
||||
IsEnabled="{Binding !OnlineInbox.IsBusy}"
|
||||
IsVisible="{Binding !OnlineInbox.SignedIn}"/>
|
||||
<Button Classes="btn danger"
|
||||
Content="{loc:Tr settings.onlineInbox.signOutButton}"
|
||||
Command="{Binding OnlineInbox.SignOutCommand}"
|
||||
IsEnabled="{Binding !OnlineInbox.IsBusy}"
|
||||
IsVisible="{Binding OnlineInbox.SignedIn}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="0,1,0,0" Margin="0,2,0,0"/>
|
||||
|
||||
<!-- Config fields -->
|
||||
<StackPanel Spacing="10">
|
||||
<TextBlock Classes="section-label" Text="{loc:Tr settings.onlineInbox.configSection}"/>
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.apiBaseUrlLabel}"/>
|
||||
<TextBox Text="{Binding OnlineInbox.ApiBaseUrl, Mode=TwoWay}"
|
||||
PlaceholderText="{loc:Tr settings.onlineInbox.apiBaseUrlPlaceholder}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.authorityLabel}"/>
|
||||
<TextBox Text="{Binding OnlineInbox.Authority, Mode=TwoWay}"
|
||||
PlaceholderText="{loc:Tr settings.onlineInbox.authorityPlaceholder}"/>
|
||||
</StackPanel>
|
||||
<Grid ColumnDefinitions="*,12,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.clientIdLabel}"/>
|
||||
<TextBox Text="{Binding OnlineInbox.ClientId, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.scopesLabel}"/>
|
||||
<TextBox Text="{Binding OnlineInbox.Scopes, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.redirectUriLabel}"/>
|
||||
<TextBox Text="{Binding OnlineInbox.RedirectUri, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.pollIntervalLabel}"/>
|
||||
<NumericUpDown Value="{Binding OnlineInbox.PollIntervalSeconds, Mode=TwoWay}"
|
||||
Minimum="10" Maximum="3600" Increment="10" FormatString="0"
|
||||
HorizontalAlignment="Left" Width="140"/>
|
||||
</StackPanel>
|
||||
<Button Classes="btn"
|
||||
Content="{loc:Tr settings.onlineInbox.saveButton}"
|
||||
Command="{Binding OnlineInbox.SaveCommand}"
|
||||
IsEnabled="{Binding !OnlineInbox.IsBusy}"
|
||||
HorizontalAlignment="Left"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Classes="meta" Text="{Binding OnlineInbox.StatusMessage}"
|
||||
IsVisible="{Binding OnlineInbox.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user