Skip to content

Commit

Permalink
add follow button
Browse files Browse the repository at this point in the history
  • Loading branch information
Gargaj committed Dec 15, 2024
1 parent 4bc1a08 commit f2cad69
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 57 deletions.
3 changes: 3 additions & 0 deletions BlueWP.ATProto/Lexicons/App/BSky/Actor/Defs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public string Handle
return $"@{handle}";
}
}
public string DID => did;
public string AvatarURL => avatar;
}

Expand Down Expand Up @@ -75,6 +76,7 @@ public string Handle
return $"@{handle}";
}
}
public string DID => did;
public string AvatarURL => avatar;
public string Description => description;
}
Expand Down Expand Up @@ -117,6 +119,7 @@ public string Handle
return $"@{handle}";
}
}
public string DID => did;
public string AvatarURL => avatar;
public string Description => description;
}
Expand Down
57 changes: 30 additions & 27 deletions BlueWP/Controls/Profile.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,40 @@
d:DesignWidth="400">

<Grid x:Name="LayoutRoot">

<Grid Margin="0,0,0,5" BorderThickness="0,0,0,1" BorderBrush="{ThemeResource AppBarItemDisabledForegroundThemeBrush}" Padding="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<!-- big avatar -->
<Image Grid.Column="0" Width="32" Height="32" VerticalAlignment="Top" Margin="0,0,5,0">
<Image.Source>
<BitmapImage UriSource="{Binding AvatarURL}"/>
</Image.Source>
</Image>

<Button Grid.Column="1" Margin="0,0,5,0" Click="ViewProfile_Click">
<Button.Template>
<ControlTemplate>

<StackPanel Orientation="Vertical" Width="Auto">
<StackPanel Orientation="Horizontal">

<StackPanel Orientation="Vertical" Width="Auto" Margin="0" BorderThickness="0,0,0,1" BorderBrush="{ThemeResource AppBarItemDisabledForegroundThemeBrush}" Padding="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>

<!-- big avatar -->
<Image Grid.Column="0" Width="32" Height="32" VerticalAlignment="Top" Margin="0,0,5,0">
<Image.Source>
<BitmapImage UriSource="{Binding AvatarURL}"/>
</Image.Source>
</Image>

<Button Grid.Column="1" Margin="0,0,5,0" Click="ViewProfile_Click">
<Button.Template>
<ControlTemplate>

<StackPanel Orientation="Vertical" Width="Auto">
<TextBlock Text="{Binding DisplayName}" TextWrapping="WrapWholeWords" FontWeight="Bold" Margin="0,0,5,0"/>
<TextBlock Text="{Binding Handle}" TextWrapping="WrapWholeWords" Foreground="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
</StackPanel>
<TextBlock Text="{Binding Description}" TextWrapping="WrapWholeWords"/>
</StackPanel>

</ControlTemplate>
</Button.Template>
</Button>

</Grid>
</ControlTemplate>
</Button.Template>
</Button>

<Button Grid.Column="2" Click="Follow_Click" Content="{Binding FollowButtonText}"/>

</Grid>

<TextBlock Text="{Binding Description}" TextWrapping="WrapWholeWords" Margin="37,0,0,0"/>
</StackPanel>
</Grid>
</UserControl>
51 changes: 47 additions & 4 deletions BlueWP/Controls/Profile.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,61 @@ private void ProfileList_Loaded(object sender, RoutedEventArgs e)
_mainPage = _app.GetCurrentFrame<Pages.MainPage>();
}

public string ActorDID => ProfileData?.DID;
public string DisplayName => ProfileData?.DisplayName;
public string Handle => ProfileData?.Handle;
public string AvatarURL => ProfileData?.AvatarURL;
public string Description => ProfileData?.Description;

public bool IsFollowing => !string.IsNullOrEmpty(ProfileData?.viewer?.following);
public bool IsBeingFollowedBy => !string.IsNullOrEmpty(ProfileData?.viewer?.followedBy);
public string FollowButtonText => IsFollowing ? "Unfollow" : (IsBeingFollowedBy ? "Follow Back" : "Follow");

private void ViewProfile_Click(object sender, RoutedEventArgs e)
{
var b = sender as Button;
var profile = b?.DataContext as Profile;
if (profile?.ProfileData?.did != null)
_mainPage.SwitchToProfileInlay(ActorDID);
}

private async void Follow_Click(object sender, RoutedEventArgs e)
{
if (IsFollowing)
{
var followURL = ProfileData?.viewer?.following;
var repo = string.Empty;
var collection = string.Empty;
var rkey = string.Empty;
if (ATProto.Helpers.ParseATURI(followURL, ref repo, ref collection, ref rkey))
{
var response = await _mainPage.Post<ATProto.Lexicons.COM.ATProto.Repo.DeleteRecord.Response>(new ATProto.Lexicons.COM.ATProto.Repo.DeleteRecord()
{
repo = repo,
collection = collection,
rkey = rkey,
});
}
if (ProfileData?.viewer != null)
{
ProfileData.viewer.following = null;
}
}
else
{
_mainPage.SwitchToProfileInlay(profile.ProfileData.did);
var response = await _mainPage.Post<ATProto.Lexicons.COM.ATProto.Repo.CreateRecord.Response>(new ATProto.Lexicons.COM.ATProto.Repo.CreateRecord()
{
repo = _app.Client.DID,
collection = "app.bsky.graph.follow",
record = new ATProto.Lexicons.App.BSky.Graph.Follow()
{
createdAt = DateTime.Now,
subject = ActorDID
}
});
if (ProfileData?.viewer != null)
{
ProfileData.viewer.following = response.uri;
}
}
OnPropertyChanged(nameof(FollowButtonText));
}

public ATProto.Lexicons.App.BSky.Actor.Defs.ProfileView ProfileData
Expand All @@ -59,6 +101,7 @@ private static void OnPostDataChanged(DependencyObject d, DependencyPropertyChan
profile.OnPropertyChanged(nameof(Handle));
profile.OnPropertyChanged(nameof(AvatarURL));
profile.OnPropertyChanged(nameof(Description));
profile.OnPropertyChanged(nameof(FollowButtonText));
}
}

Expand Down
15 changes: 13 additions & 2 deletions BlueWP/Inlays/ProfileInlay.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,19 @@
</Canvas>
</Grid>
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="15,5,0,0">
<TextBlock Text="{Binding DisplayName}" FontWeight="Bold" FontSize="24"/>
<TextBlock Text="{Binding Handle}" Foreground="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
<Grid Margin="0,0,10,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Vertical">
<TextBlock Text="{Binding DisplayName}" FontWeight="Bold" FontSize="24"/>
<TextBlock Text="{Binding Handle}" Foreground="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Content="{Binding FollowButtonText}" Click="Follow_Click"/>
</StackPanel>
</Grid>
<ScrollViewer MaxHeight="55" VerticalScrollBarVisibility="Visible">
<TextBlock Text="{Binding Description}" Margin="0,5,0,5" TextWrapping="WrapWholeWords"/>
</ScrollViewer>
Expand Down
85 changes: 63 additions & 22 deletions BlueWP/Inlays/ProfileInlay.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.ComponentModel;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
Expand All @@ -17,14 +18,20 @@ public ProfileInlay()
DataContext = this;
}

public ATProto.Lexicons.App.BSky.Actor.Defs.ProfileViewDetailed ProfileData;

public string ActorDID { get; set; }
public string CoverImageURL { get; set; }
public string AvatarURL { get; set; }
public string DisplayName { get; set; }
public string Handle { get; set; }
public string Description { get; set; }
public uint FollowerCount { get; set; }
public uint FollowCount { get; set; }
public string CoverImageURL => ProfileData?.banner;
public string AvatarURL => ProfileData?.AvatarURL;
public string DisplayName => ProfileData?.DisplayName;
public string Handle => ProfileData?.Handle;
public string Description => ProfileData?.Description;
public uint? FollowerCount => ProfileData?.followersCount;
public uint? FollowCount => ProfileData?.followsCount;

public bool IsFollowing => !string.IsNullOrEmpty(ProfileData?.viewer?.following);
public bool IsBeingFollowedBy => !string.IsNullOrEmpty(ProfileData?.viewer?.followedBy);
public string FollowButtonText => IsFollowing ? "Unfollow" : (IsBeingFollowedBy ? "Follow Back" : "Follow");

private void ProfileInlay_Loaded(object sender, RoutedEventArgs e)
{
Expand All @@ -45,20 +52,16 @@ public async Task Refresh()
});
if (response != null)
{
CoverImageURL = response.banner;
AvatarURL = response.avatar;
DisplayName = response.displayName;
Handle = $"@{response.handle}";
Description = response.description;
FollowerCount = response.followersCount;
FollowCount = response.followsCount;
ProfileData = response;

OnPropertyChanged(nameof(CoverImageURL));
OnPropertyChanged(nameof(AvatarURL));
OnPropertyChanged(nameof(DisplayName));
OnPropertyChanged(nameof(Handle));
OnPropertyChanged(nameof(Description));
OnPropertyChanged(nameof(FollowerCount));
OnPropertyChanged(nameof(FollowCount));
OnPropertyChanged(nameof(FollowButtonText));
}

if (feed != null)
Expand All @@ -71,20 +74,16 @@ public async Task Refresh()

public void Flush()
{
CoverImageURL = null;
AvatarURL = null;
DisplayName = string.Empty;
Handle = string.Empty;
Description = string.Empty;
FollowerCount = 0;
FollowCount = 0;
ProfileData = null;

OnPropertyChanged(nameof(CoverImageURL));
OnPropertyChanged(nameof(AvatarURL));
OnPropertyChanged(nameof(DisplayName));
OnPropertyChanged(nameof(Handle));
OnPropertyChanged(nameof(Description));
OnPropertyChanged(nameof(FollowerCount));
OnPropertyChanged(nameof(FollowCount));
OnPropertyChanged(nameof(FollowButtonText));

feed.Flush();
}
Expand All @@ -99,6 +98,48 @@ private async void Following_Click(object sender, RoutedEventArgs e)
await _mainPage.SwitchToFollowingInlay(ActorDID);
}

private async void Follow_Click(object sender, RoutedEventArgs e)
{
if (IsFollowing)
{
var followURL = ProfileData?.viewer?.following;
var repo = string.Empty;
var collection = string.Empty;
var rkey = string.Empty;
if (ATProto.Helpers.ParseATURI(followURL, ref repo, ref collection, ref rkey))
{
var response = await _mainPage.Post<ATProto.Lexicons.COM.ATProto.Repo.DeleteRecord.Response>(new ATProto.Lexicons.COM.ATProto.Repo.DeleteRecord()
{
repo = repo,
collection = collection,
rkey = rkey,
});
}
if (ProfileData?.viewer != null)
{
ProfileData.viewer.following = null;
}
}
else
{
var response = await _mainPage.Post<ATProto.Lexicons.COM.ATProto.Repo.CreateRecord.Response>(new ATProto.Lexicons.COM.ATProto.Repo.CreateRecord()
{
repo = _app.Client.DID,
collection = "app.bsky.graph.follow",
record = new ATProto.Lexicons.App.BSky.Graph.Follow()
{
createdAt = DateTime.Now,
subject = ActorDID
}
});
if (ProfileData?.viewer != null)
{
ProfileData.viewer.following = response.uri;
}
}
OnPropertyChanged(nameof(FollowButtonText));
}

public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
Expand Down
8 changes: 7 additions & 1 deletion BlueWP/Pages/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</PivotItem.Style>
</PivotItem.Style>
<bwpi:NotificationsInlay />
</PivotItem>

Expand Down Expand Up @@ -124,6 +124,12 @@

<!-- Search -->
<PivotItem>
<PivotItem.Style>
<Style TargetType="PivotItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</PivotItem.Style>
<PivotItem.Header>
<bwpc:MainPagePivotHeader Glyph="&#xE721;" Label="Search"/>
</PivotItem.Header>
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ to the device, but you should be able to compile and build packages with VS2022

## Todo
- Posting: Autocomplete handles
- Following / unfollowing action
- Pagination / infinite scrolling

0 comments on commit f2cad69

Please sign in to comment.