From 6a92a6a4d27dc07f8b32bd7d57ffbcbe15630ab9 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sun, 12 Feb 2012 01:53:36 +0400 Subject: Avatars support + broken clickable urls --- Juick/App.xaml.cs | 6 +++ Juick/Classes/RichTextConverter.cs | 58 +++++++++++++++++++++++++++ Juick/Juick.csproj | 2 +- Juick/MainPage.xaml | 58 ++++++++++++++++++--------- Juick/MainPage.xaml.cs | 44 +++++++++++++++++++-- Juick/ThreadView.xaml | 23 +++++++---- Juick/ViewModels/MainViewModel.cs | 76 ++++++++++++++++++++++++++++-------- Juick/ViewModels/MessageViewModel.cs | 8 ++-- Juick/ViewModels/ThreadViewModel.cs | 19 ++++++++- 9 files changed, 242 insertions(+), 52 deletions(-) create mode 100644 Juick/Classes/RichTextConverter.cs (limited to 'Juick') diff --git a/Juick/App.xaml.cs b/Juick/App.xaml.cs index 54abe20..b73398c 100644 --- a/Juick/App.xaml.cs +++ b/Juick/App.xaml.cs @@ -39,6 +39,12 @@ namespace Juick get { return _cl ?? (_cl = new RestClient("http://api.juick.com") {UserAgent = "Juick 0.999/Windows Phone " + Environment.OSVersion.Version}); } } + private static RestClient _acl; + public static RestClient AvatarClient + { + get { return _acl ?? (_acl = new RestClient("http://i.juick.com") { UserAgent = "Juick 0.999/Windows Phone " + Environment.OSVersion.Version }); } + } + /// /// Provides easy access to the root frame of the Phone Application. /// diff --git a/Juick/Classes/RichTextConverter.cs b/Juick/Classes/RichTextConverter.cs new file mode 100644 index 0000000..ee6ffa7 --- /dev/null +++ b/Juick/Classes/RichTextConverter.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; +using Microsoft.Phone.Tasks; + +namespace Juick.Classes +{ + public class RichTextConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var message = value as string; + var runs = new List(); + + foreach (var word in message.Split(new char[] {' ', '\n'})) + { + Uri uri; + + if (Uri.TryCreate(word, UriKind.Absolute, out uri) || + (word.StartsWith("www.") && Uri.TryCreate("http://" + word, UriKind.Absolute, out uri))) + { + var link = new Hyperlink(); + link.Inlines.Add(new Run() { Text = word }); + link.Click += (sender, e) => + { + var hyperLink = (sender as Hyperlink); + new WebBrowserTask() { Uri = uri }.Show(); + }; + + runs.Add(link); + } + else + { + runs.Add(new Run() { Text = word }); + } + + runs.Add(new Run() { Text = " " }); + } + + return runs; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } + } +} diff --git a/Juick/Juick.csproj b/Juick/Juick.csproj index e550947..73d65c1 100644 --- a/Juick/Juick.csproj +++ b/Juick/Juick.csproj @@ -71,6 +71,7 @@ App.xaml + LoginView.xaml @@ -125,7 +126,6 @@ PreserveNewest - diff --git a/Juick/MainPage.xaml b/Juick/MainPage.xaml index 3d7245c..84e7bd7 100644 --- a/Juick/MainPage.xaml +++ b/Juick/MainPage.xaml @@ -6,14 +6,19 @@ xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="728" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:bindings="clr-namespace:Juick.Classes" + xmlns:Juick="clr-namespace:Juick" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="728" d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="False"> + + + + + @@ -26,10 +31,15 @@ + + + - - + + @@ -39,24 +49,28 @@ - + - + - - + + @@ -64,8 +78,14 @@ + + + + @@ -76,26 +96,26 @@ - - + - - - + @@ -104,14 +124,14 @@ - - - + + + - - - + + + diff --git a/Juick/MainPage.xaml.cs b/Juick/MainPage.xaml.cs index 4468f6a..1654c1b 100644 --- a/Juick/MainPage.xaml.cs +++ b/Juick/MainPage.xaml.cs @@ -64,19 +64,57 @@ namespace Juick ((ListBox)sender).SelectedIndex = -1; } - private void ApplicationBarIconButton_Click(object sender, EventArgs e) + public static string GetInlineList(TextBlock element) + { + if (element != null) + return element.GetValue(InlineList) as string; + return string.Empty; + } + + public static void SetInlineList(TextBlock element, string value) + { + if (element != null) + element.SetValue(InlineList, value); + } + + public static readonly DependencyProperty InlineList = + DependencyProperty.RegisterAttached( + "InlineList", + typeof(List), + typeof(MainPage), + new PropertyMetadata(null, OnInlineListPropertyChanged)); + + private static void OnInlineListPropertyChanged(DependencyObject obj, + DependencyPropertyChangedEventArgs e) + { + var tb = obj as TextBlock; + if (tb != null) + { + // clear previous inlines + tb.Inlines.Clear(); + + // add new inlines + var inlines = e.NewValue as List; + if (inlines != null) + { + inlines.ForEach(inl => tb.Inlines.Add((inl))); + } + } + } + + private void ApplicationBarIconButtonClick(object sender, EventArgs e) { App.ViewModel.MyFeed.Clear(); App.ViewModel.Last.Clear(); App.ViewModel.LoadData(); } - private void ApplicationBarMenuItem_Click(object sender, EventArgs e) + private void ApplicationBarMenuItemClick(object sender, EventArgs e) { App.Account.SignOut(this); } - private void ApplicationBarIconButton_Click_1(object sender, EventArgs e) + private void ApplicationBarIconButtonClick1(object sender, EventArgs e) { NavigationService.Navigate(new Uri("/NewPostView.xaml", UriKind.Relative)); } diff --git a/Juick/ThreadView.xaml b/Juick/ThreadView.xaml index 20529c2..2decd6e 100644 --- a/Juick/ThreadView.xaml +++ b/Juick/ThreadView.xaml @@ -28,9 +28,15 @@ + + + - + + @@ -40,20 +46,21 @@ - + + - + + TextWrapping="Wrap" /> - + diff --git a/Juick/ViewModels/MainViewModel.cs b/Juick/ViewModels/MainViewModel.cs index a504658..23ff020 100644 --- a/Juick/ViewModels/MainViewModel.cs +++ b/Juick/ViewModels/MainViewModel.cs @@ -2,10 +2,13 @@ using System.ComponentModel; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; using System.Runtime.Serialization.Json; using System.Collections.ObjectModel; using System.Windows; +using System.Windows.Controls; +using System.Windows.Media.Imaging; using Juick.Api; using RestSharp; @@ -52,16 +55,36 @@ namespace Juick.ViewModels var ser = new DataContractJsonSerializer(typeof (List)); var messages = - (List)ser.ReadObject(new MemoryStream(response.RawBytes)); + ser.ReadObject(new MemoryStream(response.RawBytes)) as List; MyFeed.Clear(); - messages.ForEach(post => MyFeed.Add(new MessageViewModel(post) - { - Status = - string.Format( - "Posted on: {0}, replies: {1}", - post.timestamp, - post.replies) - })); + messages.ForEach(post => + { + var item = new MessageViewModel(post) + { + Status = + string.Format( + "Posted on: {0}, replies: {1}", + post. + timestamp, + post. + replies) + }; + MyFeed.Add(item); + var imageRequest = + new RestRequest( + string.Format("/as/{0}.png", + post.user.uid)); + App.AvatarClient.ExecuteAsync( + imageRequest, restResponse => + { + item.UserAvatar = new BitmapImage + (); + item.UserAvatar.SetSource(new MemoryStream(restResponse.RawBytes)); + item. + NotifyPropertyChanged + ("UserAvatar"); + }); + }); NotifyPropertyChanged("MyFeed"); }); @@ -75,13 +98,34 @@ namespace Juick.ViewModels (List)ser.ReadObject(ms); if (messages == null) return; Last.Clear(); - messages.ForEach(post => Last.Add(new MessageViewModel(post) + messages.ForEach(post => { - Status = string.Format( - "Posted on: {0}, replies: {1}", - post.timestamp, post.replies - ) - })); + var item = new MessageViewModel(post) + { + Status = + string.Format( + "Posted on: {0}, replies: {1}", + post. + timestamp, + post. + replies) + }; + Last.Add(item); + var imageRequest = + new RestRequest( + string.Format("/as/{0}.png", + post.user.uid)); + App.AvatarClient.ExecuteAsync( + imageRequest, restResponse => + { + item.UserAvatar = new BitmapImage + (); + item.UserAvatar.SetSource(new MemoryStream(restResponse.RawBytes)); + item. + NotifyPropertyChanged + ("UserAvatar"); + }); + }); NotifyPropertyChanged("Last"); } }); @@ -89,7 +133,7 @@ namespace Juick.ViewModels public event PropertyChangedEventHandler PropertyChanged; - private void NotifyPropertyChanged(String propertyName) + public void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) diff --git a/Juick/ViewModels/MessageViewModel.cs b/Juick/ViewModels/MessageViewModel.cs index 32da0aa..8620ab3 100644 --- a/Juick/ViewModels/MessageViewModel.cs +++ b/Juick/ViewModels/MessageViewModel.cs @@ -9,6 +9,7 @@ using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; using System.Windows.Shapes; using Juick.Api; @@ -90,8 +91,8 @@ namespace Juick } } - private Image _avatar; - public Image UserAvatar + private BitmapImage _avatar; + public BitmapImage UserAvatar { get { return _avatar; } set @@ -147,7 +148,8 @@ namespace Juick } public event PropertyChangedEventHandler PropertyChanged; - private void NotifyPropertyChanged(String propertyName) + + public void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) diff --git a/Juick/ViewModels/ThreadViewModel.cs b/Juick/ViewModels/ThreadViewModel.cs index 48ebe65..bff72b7 100644 --- a/Juick/ViewModels/ThreadViewModel.cs +++ b/Juick/ViewModels/ThreadViewModel.cs @@ -6,6 +6,7 @@ using System.IO; using System.Net; using System.Net.Browser; using System.Runtime.Serialization.Json; +using System.Windows.Media.Imaging; using Juick.Api; using RestSharp; @@ -48,8 +49,22 @@ namespace Juick.ViewModels Items.Clear(); messages.ForEach(post => { - this.Items.Add( - new MessageViewModel(post)); + var item = new MessageViewModel(post); + Items.Add(item); + var imageRequest = + new RestRequest( + string.Format("/as/{0}.png", + post.user.uid)); + App.AvatarClient.ExecuteAsync( + imageRequest, restResponse => + { + item.UserAvatar = new BitmapImage + (); + item.UserAvatar.SetSource(new MemoryStream(restResponse.RawBytes)); + item. + NotifyPropertyChanged + ("UserAvatar"); + }); }); IsDataLoaded = true; NotifyPropertyChanged("Items"); -- cgit v1.2.3