feat(desktop): add basic targeting window
This commit is contained in:
parent
98e7889844
commit
2807f695ae
|
@ -217,9 +217,8 @@ namespace XIVChat_Desktop {
|
|||
// tell the server our preferences
|
||||
var preferences = new ClientPreferences {
|
||||
Preferences = new Dictionary<ClientPreference, object> {
|
||||
{
|
||||
ClientPreference.BacklogNewestMessagesFirst, true
|
||||
},
|
||||
[ClientPreference.BacklogNewestMessagesFirst] = true,
|
||||
[ClientPreference.TargetingListSupport] = true,
|
||||
},
|
||||
};
|
||||
await SecretMessage.SendSecretMessage(stream, handshake.Keys.tx, preferences, this.cancel.Token);
|
||||
|
@ -418,16 +417,24 @@ namespace XIVChat_Desktop {
|
|||
case ServerOperation.PlayerList:
|
||||
var playerList = ServerPlayerList.Decode(payload);
|
||||
|
||||
if (playerList.Type == PlayerListType.Friend) {
|
||||
var players = playerList.Players
|
||||
.OrderBy(player => !player.HasStatus(PlayerStatus.Online));
|
||||
switch (playerList.Type) {
|
||||
case PlayerListType.Friend: {
|
||||
var players = playerList.Players
|
||||
.OrderBy(player => !player.HasStatus(PlayerStatus.Online));
|
||||
|
||||
this.app.Dispatch(() => {
|
||||
this.app.Window.FriendList.Clear();
|
||||
foreach (var player in players) {
|
||||
this.app.Window.FriendList.Add(player);
|
||||
}
|
||||
});
|
||||
this.app.Dispatch(() => {
|
||||
this.app.Window.FriendList.Clear();
|
||||
foreach (var player in players) {
|
||||
this.app.Window.FriendList.Add(player);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case PlayerListType.Targeting:
|
||||
this.app.Dispatch(() => {
|
||||
this.app.Window.UpdateTargeting(playerList.Players);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace XIVChat_Desktop {
|
|||
|
||||
public class SenderPlayerConverter : IValueConverter {
|
||||
public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
if (!(value is ServerMessage.SenderPlayer sender)) {
|
||||
if (value is not ServerMessage.SenderPlayer sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ namespace XIVChat_Desktop {
|
|||
if (worldName != null) {
|
||||
s.Append(" (");
|
||||
s.Append(worldName);
|
||||
s.Append(")");
|
||||
s.Append(')');
|
||||
}
|
||||
|
||||
return s.ToString();
|
||||
|
@ -100,11 +100,11 @@ namespace XIVChat_Desktop {
|
|||
|
||||
public class NotConverter : IValueConverter {
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
return !((bool)value);
|
||||
return !(bool) value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
return !((bool)value);
|
||||
return !(bool) value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,11 +113,11 @@ namespace XIVChat_Desktop {
|
|||
public T FalseValue { get; set; } = default!;
|
||||
|
||||
public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
return (bool)value ? this.TrueValue : this.FalseValue;
|
||||
return (bool) value ? this.TrueValue : this.FalseValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
var val = (T)value;
|
||||
var val = (T) value;
|
||||
return EqualityComparer<T>.Default.Equals(val, this.TrueValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
WindowChrome.IsHitTestVisibleInChrome="{Binding App.Config.CompactMode}">
|
||||
<MenuItem Header="Friend list"
|
||||
Click="FriendList_Click" />
|
||||
<MenuItem Header="Targeting"
|
||||
Click="Targeting_Click" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<TabControl x:Name="Tabs"
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
@ -163,6 +164,7 @@ namespace XIVChat_Desktop {
|
|||
|
||||
public List<ServerMessage> Messages { get; } = new();
|
||||
public ObservableCollection<Player> FriendList { get; } = new();
|
||||
public List<TargetingPlayer> Targeting { get; set; } = new();
|
||||
|
||||
private bool ShowMessageForNoUpdate { get; set; }
|
||||
|
||||
|
@ -349,6 +351,31 @@ namespace XIVChat_Desktop {
|
|||
}
|
||||
}
|
||||
|
||||
internal void UpdateTargeting(IEnumerable<Player> players) {
|
||||
var now = DateTime.UtcNow;
|
||||
var data = players as Player[] ?? players.ToArray();
|
||||
|
||||
var newPlayers = data
|
||||
.Where(player => this.Targeting.All(t => t.Player.Name != player.Name && t.Player.HomeWorld != player.HomeWorld))
|
||||
.Select(player => new TargetingPlayer(player, true, now));
|
||||
|
||||
var oldPlayers = this.Targeting
|
||||
.Select(t => {
|
||||
var timestamp = t.Timestamp;
|
||||
var current = data.Any(current => current.Name == t.Player.Name && current.HomeWorld == t.Player.HomeWorld);
|
||||
if (current || t.Current) {
|
||||
timestamp = now;
|
||||
}
|
||||
|
||||
return new TargetingPlayer(t.Player, current, timestamp);
|
||||
})
|
||||
.Concat(newPlayers)
|
||||
.OrderByDescending(t => t.Current)
|
||||
.ThenByDescending(t => t.Timestamp);
|
||||
|
||||
this.Targeting = oldPlayers.ToList();
|
||||
}
|
||||
|
||||
private void Connect_Click(object sender, RoutedEventArgs e) {
|
||||
new ConnectDialog(this).ShowDialog();
|
||||
}
|
||||
|
@ -518,5 +545,27 @@ namespace XIVChat_Desktop {
|
|||
private void TabGrid_OnInitialized(object? sender, EventArgs e) {
|
||||
this.CalculateCompactMargins();
|
||||
}
|
||||
|
||||
private void Targeting_Click(object sender, RoutedEventArgs e) {
|
||||
new Targeting(this).Show();
|
||||
}
|
||||
}
|
||||
|
||||
public class TargetingPlayer {
|
||||
public Player Player { get; }
|
||||
public bool Current { get; }
|
||||
public DateTime Timestamp { get; }
|
||||
|
||||
public string UiTimestamp => this.Current
|
||||
? "Now"
|
||||
: DateTime.UtcNow - this.Timestamp >= TimeSpan.FromDays(1)
|
||||
? this.Timestamp.ToLocalTime().ToString("dd/MM")
|
||||
: this.Timestamp.ToLocalTime().ToString("t");
|
||||
|
||||
public TargetingPlayer(Player player, bool current, DateTime timestamp) {
|
||||
this.Player = player;
|
||||
this.Current = current;
|
||||
this.Timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<local:XivChatWindow x:Class="XIVChat_Desktop.Targeting"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:XIVChat_Desktop"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
ui:WindowHelper.UseModernWindowStyle="True"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
mc:Ignorable="d"
|
||||
Title="Targeting"
|
||||
Height="225"
|
||||
Width="250"
|
||||
WindowStyle="ToolWindow"
|
||||
d:DataContext="{d:DesignInstance local:Targeting}">
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<DataGrid Grid.Row="0"
|
||||
ItemsSource="{Binding App.Window.Targeting, UpdateSourceTrigger=PropertyChanged}"
|
||||
AutoGenerateColumns="False"
|
||||
RowHeaderWidth="0"
|
||||
IsReadOnly="True"
|
||||
SelectionUnit="FullRow"
|
||||
SelectionMode="Single"
|
||||
CanUserReorderColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Name"
|
||||
Binding="{Binding Player.Name}"
|
||||
d:DataContext="{d:DesignInstance local:TargetingPlayer}">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style TargetType="{x:Type DataGridCell}"
|
||||
BasedOn="{StaticResource DefaultDataGridCellStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Current}"
|
||||
Value="False">
|
||||
<Setter Property="Opacity"
|
||||
Value="0.75" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGridTextColumn.CellStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<DataGridTextColumn Header="Timestamp"
|
||||
Binding="{Binding UiTimestamp}"
|
||||
d:DataContext="{d:DesignInstance local:TargetingPlayer}">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style TargetType="{x:Type DataGridCell}"
|
||||
BasedOn="{StaticResource DefaultDataGridCellStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Current}"
|
||||
Value="False">
|
||||
<Setter Property="Opacity"
|
||||
Value="0.75" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGridTextColumn.CellStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
</local:XivChatWindow>
|
|
@ -0,0 +1,14 @@
|
|||
using System.Windows;
|
||||
|
||||
namespace XIVChat_Desktop {
|
||||
public partial class Targeting {
|
||||
public App App => (App) Application.Current;
|
||||
|
||||
public Targeting(Window owner) {
|
||||
this.Owner = owner;
|
||||
this.DataContext = this;
|
||||
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue