diff options
-rw-r--r-- | Juick/App.xaml | 19 | ||||
-rw-r--r-- | Juick/Classes/AccountManager.cs | 40 | ||||
-rw-r--r-- | Juick/Classes/BooleanToVisibiltyConverter.cs | 24 | ||||
-rw-r--r-- | Juick/Classes/DateHelper.cs | 67 | ||||
-rw-r--r-- | Juick/Controls/MessageList.xaml | 45 | ||||
-rw-r--r-- | Juick/DataTemplates/PostItemDataTemplate.xaml | 44 | ||||
-rw-r--r-- | Juick/Juick.csproj | 13 | ||||
-rw-r--r-- | Juick/LoginView.xaml | 3 | ||||
-rw-r--r-- | Juick/MainPage.xaml.cs | 2 | ||||
-rw-r--r-- | Juick/NewPostView.xaml | 2 | ||||
-rw-r--r-- | Juick/Properties/AssemblyInfo.cs | 4 | ||||
-rw-r--r-- | Juick/SampleData/ThreadViewModelSampleData.xaml | 16 | ||||
-rw-r--r-- | Juick/ThreadView.xaml | 147 | ||||
-rw-r--r-- | Juick/ViewModels/AppViewModel.cs | 94 | ||||
-rw-r--r-- | Juick/ViewModels/LoginViewModel.cs | 6 | ||||
-rw-r--r-- | Juick/ViewModels/NewPostViewModel.cs | 28 | ||||
-rw-r--r-- | Juick/ViewModels/PostItem.cs | 9 |
17 files changed, 248 insertions, 315 deletions
diff --git a/Juick/App.xaml b/Juick/App.xaml index 1b67f8c..0c60cc0 100644 --- a/Juick/App.xaml +++ b/Juick/App.xaml @@ -1,25 +1,20 @@ -<Application
+<Application
+ x:Class="Juick.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
- xmlns:sys="clr-namespace:System;assembly=mscorlib"
- x:Class="Juick.App"
- >
+ xmlns:sys="clr-namespace:System;assembly=mscorlib">
+ <!--Application Resources-->
<Application.Resources>
- <ResourceDictionary>
- <ResourceDictionary.MergedDictionaries>
- <ResourceDictionary Source="DataTemplates/PostItemDataTemplate.xaml" />
- </ResourceDictionary.MergedDictionaries>
- </ResourceDictionary>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
- <shell:PhoneApplicationService
- Launching="Application_Launching" Closing="Application_Closing"
- Activated="Application_Activated" Deactivated="Application_Deactivated"/>
+ <shell:PhoneApplicationService
+ Launching="Application_Launching" Closing="Application_Closing"
+ Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
</Application>
\ No newline at end of file diff --git a/Juick/Classes/AccountManager.cs b/Juick/Classes/AccountManager.cs index eb99d92..1f9ffe5 100644 --- a/Juick/Classes/AccountManager.cs +++ b/Juick/Classes/AccountManager.cs @@ -3,8 +3,6 @@ using System.IO.IsolatedStorage; using System.Net;
using System.Windows;
using System.Windows.Controls;
-using RestSharp;
-using System.Diagnostics;
namespace Juick.Classes
{
@@ -12,14 +10,14 @@ namespace Juick.Classes {
private string _userName;
private string _password;
-
+
public string UserName
{
get
{
if (_userName == null)
{
- IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("user", out _userName);
+ IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("user", out _userName);
}
return _userName;
}
@@ -36,7 +34,7 @@ namespace Juick.Classes {
if (_password == null)
{
- IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("password", out _password);
+ IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("password", out _password);
}
return _password;
}
@@ -49,8 +47,7 @@ namespace Juick.Classes public bool IsAuthenticated
{
- get
- {
+ get {
bool authenticated;
IsolatedStorageSettings.ApplicationSettings.TryGetValue<bool>("authenticated", out authenticated);
return authenticated;
@@ -58,45 +55,26 @@ namespace Juick.Classes set { IsolatedStorageSettings.ApplicationSettings["authenticated"] = value; }
}
-
-
public string NotificationUri
{
get
{
- string _notificationUri;
- IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("notification_uri", out _notificationUri);
- return _notificationUri;
+ string savedUri;
+ IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("notification_uri", out savedUri);
+ return savedUri;
}
set
{
- var oldValue = NotificationUri;
- if (!string.IsNullOrEmpty(oldValue))
- UnregisterNotificationUrl(oldValue);
IsolatedStorageSettings.ApplicationSettings["notification_uri"] = value;
- if (!string.IsNullOrEmpty(value))
- RegisterNotificationUrl(value);
}
}
-
-
+
+
public void SignOut(Page page)
{
IsAuthenticated = false;
- App.AppContext.DisableNotifications();
page.NavigationService.Navigate(new Uri("/LoginView.xaml", UriKind.Relative));
page.Dispatcher.BeginInvoke(() => page.NavigationService.RemoveBackEntry());
}
-
- void RegisterNotificationUrl(string newUrl)
- {
- App.AppContext.Client.ExecuteAsync(new RestRequest("/winphone/register?url=" + newUrl),
- response => Debug.WriteLine("Registering push url, status {0}: {1}", response.Request.Resource, response.StatusCode));
- }
- void UnregisterNotificationUrl(string oldUrl)
- {
- App.AppContext.Client.ExecuteAsync(new RestRequest("/winphone/unregister?url=" + oldUrl),
- response => Debug.WriteLine("Unregistered push url, status {0}: {1}", response.Request.Resource, response.StatusCode));
- }
}
}
diff --git a/Juick/Classes/BooleanToVisibiltyConverter.cs b/Juick/Classes/BooleanToVisibiltyConverter.cs new file mode 100644 index 0000000..679cc3f --- /dev/null +++ b/Juick/Classes/BooleanToVisibiltyConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Data; + +namespace Juick.Classes +{ + public class BooleanToVisibiltyConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var visible = (bool) value; + return visible ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Juick/Classes/DateHelper.cs b/Juick/Classes/DateHelper.cs deleted file mode 100644 index 072c56a..0000000 --- a/Juick/Classes/DateHelper.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Net; -using System.Windows; -using System.Windows.Controls; -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 System.Globalization; - -namespace Juick.Classes -{ - public class DateHelper - { - public static string PrettyDate(DateTime dateTime) - { - var timeSpan = DateTime.Now - dateTime; - - // span is less than or equal to 60 seconds, measure in seconds. - if (timeSpan <= TimeSpan.FromSeconds(60)) - { - return timeSpan.Seconds > 5 - ? "about " + timeSpan.Seconds + " seconds ago" - : "just now"; - } - - // span is less than or equal to 60 minutes, measure in minutes. - if (timeSpan <= TimeSpan.FromMinutes(60)) - { - return timeSpan.Minutes > 1 - ? "about " + timeSpan.Minutes + " minutes ago" - : "about a minute ago"; - } - - // span is less than or equal to 24 hours, measure in hours. - if (timeSpan <= TimeSpan.FromHours(24)) - { - return timeSpan.Hours > 1 - ? "about " + timeSpan.Hours + " hours ago" - : "about an hour ago"; - } - - // span is less than or equal to 30 days (1 month), measure in days. - if (timeSpan <= TimeSpan.FromDays(30)) - { - return timeSpan.Days > 1 - ? "about " + timeSpan.Days + " days ago" - : "about a day ago"; - } - - // span is less than or equal to 365 days (1 year), measure in months. - if (timeSpan <= TimeSpan.FromDays(365)) - { - return timeSpan.Days > 30 - ? "about " + timeSpan.Days / 30 + " months ago" - : "about a month ago"; - } - - // span is greater than 365 days (1 year), measure in years. - return timeSpan.Days > 365 - ? "about " + timeSpan.Days / 365 + " years ago" - : "about a year ago"; - } - } -} diff --git a/Juick/Controls/MessageList.xaml b/Juick/Controls/MessageList.xaml index ac6db00..afa6c69 100644 --- a/Juick/Controls/MessageList.xaml +++ b/Juick/Controls/MessageList.xaml @@ -12,10 +12,10 @@ FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" d:DesignHeight="480" d:DesignWidth="480"> - + <Grid x:Name="LayoutRoot"> <toolkit:LongListSelector Margin="0, 0, -12, 0" - ItemsSource="{Binding Items}" IsFlatList="true" ItemTemplate="{StaticResource PostItemDataTemplate}"> + ItemsSource="{Binding Items}" IsFlatList="true"> <i:Interaction.Triggers> <i:EventTrigger EventName="Link"> <bindings:InvokeDelegateCommandAction Command="{Binding LoadMessagesPageCommand}" @@ -25,7 +25,46 @@ <bindings:InvokeDelegateCommandAction Command="{Binding NavigateNextCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=InvokeParameter}"/> </i:EventTrigger> - </i:Interaction.Triggers> + </i:Interaction.Triggers> + <toolkit:LongListSelector.ItemTemplate> + <DataTemplate> + <Border BorderBrush="{StaticResource PhoneForegroundBrush}" BorderThickness="0 0 0 1"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image bindings:LowProfileImageLoader.UriSource="{Binding AvatarUri}" Grid.Row="0" Grid.Column="0" Margin="3" /> + <TextBlock Text="{Binding Username}" Grid.Row="0" Grid.Column="1" + Margin="5,0,5,5" VerticalAlignment="Top" + HorizontalAlignment="Left" + FontFamily="{StaticResource PhoneFontFamilySemiLight}" + FontSize="{StaticResource PhoneFontSizeLarge}" + Style="{StaticResource PhoneTextAccentStyle}" /> + <!--Style="{StaticResource PhoneTextNormalStyle}"--> + <usercontrols:HyperLinkRichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" + TextWrapping="Wrap" HorizontalAlignment="Left" + Foreground="{StaticResource PhoneForegroundBrush}" + Margin="5,0,5,5" VerticalAlignment="Top" + IsReadOnly="True" Text="{Binding MessageText}" /> + <Image bindings:LowProfileImageLoader.UriSource="{Binding Attachment}" Grid.Row="2" Grid.Column="0" Margin="3" Grid.ColumnSpan="2" /> + <TextBlock Text="{Binding Status}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" + Foreground="{StaticResource PhoneForegroundBrush}" + Style="{StaticResource PhoneTextAccentStyle}" + FontSize="{StaticResource PhoneFontSizeSmall}" + Margin="5,0,5,5" VerticalAlignment="Top" + TextWrapping="Wrap" HorizontalAlignment="Left"/> + </Grid> + </Border> + + </DataTemplate> + </toolkit:LongListSelector.ItemTemplate> </toolkit:LongListSelector> </Grid> </UserControl> diff --git a/Juick/DataTemplates/PostItemDataTemplate.xaml b/Juick/DataTemplates/PostItemDataTemplate.xaml deleted file mode 100644 index 4668a48..0000000 --- a/Juick/DataTemplates/PostItemDataTemplate.xaml +++ /dev/null @@ -1,44 +0,0 @@ -<ResourceDictionary - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:bindings="clr-namespace:Juick.Classes" - xmlns:usercontrols="clr-namespace:Juick.Controls" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > - - <DataTemplate x:Key="PostItemDataTemplate"> - <Border BorderBrush="{StaticResource PhoneForegroundBrush}" BorderThickness="0 0 0 1"> - <Grid> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition Width="*" /> - </Grid.ColumnDefinitions> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Image bindings:LowProfileImageLoader.UriSource="{Binding AvatarUri}" Grid.Row="0" Grid.Column="0" Margin="3" /> - <TextBlock Text="{Binding Username}" Grid.Row="0" Grid.Column="1" - Margin="5,0,5,5" VerticalAlignment="Top" - HorizontalAlignment="Left" - FontFamily="{StaticResource PhoneFontFamilySemiLight}" - FontSize="{StaticResource PhoneFontSizeLarge}" - Style="{StaticResource PhoneTextAccentStyle}" /> - <usercontrols:HyperLinkRichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" - TextWrapping="Wrap" HorizontalAlignment="Left" - Foreground="{StaticResource PhoneForegroundBrush}" - Margin="5,0,5,5" VerticalAlignment="Top" - IsReadOnly="True" Text="{Binding MessageText}" /> - <Image bindings:LowProfileImageLoader.UriSource="{Binding Attachment}" Grid.Row="2" Grid.Column="0" Margin="3" - Grid.ColumnSpan="2" /> - <TextBlock Text="{Binding Status}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" - Foreground="{StaticResource PhoneForegroundBrush}" - Style="{StaticResource PhoneTextAccentStyle}" - FontSize="{StaticResource PhoneFontSizeSmall}" - Margin="5,0,5,5" VerticalAlignment="Top" - TextWrapping="NoWrap" TextAlignment="Right"/> - </Grid> - </Border> - - </DataTemplate> -</ResourceDictionary>
\ No newline at end of file diff --git a/Juick/Juick.csproj b/Juick/Juick.csproj index c89c775..0163f65 100644 --- a/Juick/Juick.csproj +++ b/Juick/Juick.csproj @@ -27,8 +27,6 @@ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
- <Utf8Output>true</Utf8Output>
- <ExpressionBlendVersion>4.0.30816.0</ExpressionBlendVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -111,6 +109,7 @@ <Compile Include="ViewModels\PageViewModel.cs" />
<Compile Include="ViewModels\PostItem.cs" />
<Compile Include="ViewModels\ThreadViewModel.cs" />
+ <Compile Include="ViewModels\Validation\DataViewModelBase.cs" />
<Compile Include="ViewModels\ViewModelBase.cs" />
</ItemGroup>
<ItemGroup>
@@ -122,10 +121,6 @@ <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
- <Page Include="DataTemplates\PostItemDataTemplate.xaml">
- <SubType>Designer</SubType>
- <Generator>MSBuild:Compile</Generator>
- </Page>
<Page Include="LoginView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -197,12 +192,6 @@ <Content Include="Images\appbar.send.png" />
<Content Include="SplashScreenImage.jpg" />
</ItemGroup>
- <ItemGroup>
- <DesignData Include="SampleData\ThreadViewModelSampleData.xaml">
- <Generator>MSBuild:MarkupCompilePass1</Generator>
- </DesignData>
- </ItemGroup>
- <ItemGroup />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.$(TargetFrameworkProfile).Overrides.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/Juick/LoginView.xaml b/Juick/LoginView.xaml index 3e204a4..004580a 100644 --- a/Juick/LoginView.xaml +++ b/Juick/LoginView.xaml @@ -9,9 +9,10 @@ xmlns:viewModels="clr-namespace:Juick.ViewModels"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
+ Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
- phoneshell:SystemTray.IsVisible="True" CacheMode="BitmapCache">
+ phoneshell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.DataContext>
<viewModels:LoginViewModel />
</phone:PhoneApplicationPage.DataContext>
diff --git a/Juick/MainPage.xaml.cs b/Juick/MainPage.xaml.cs index 7baa6dd..20beef5 100644 --- a/Juick/MainPage.xaml.cs +++ b/Juick/MainPage.xaml.cs @@ -70,7 +70,7 @@ namespace Juick }
if (!string.IsNullOrEmpty(FileId) || navigateUri.StartsWith(loginUriPart))
{
- ((App)Application.Current).NavigateTo(new Uri(navigateUri, UriKind.Relative), true);
+ NavigationService.Navigate(new Uri(navigateUri, UriKind.Relative));
}
if (queryStrings.ContainsKey("mid"))
{
diff --git a/Juick/NewPostView.xaml b/Juick/NewPostView.xaml index 1ed01b5..f3a911b 100644 --- a/Juick/NewPostView.xaml +++ b/Juick/NewPostView.xaml @@ -11,7 +11,7 @@ Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="696" d:DesignWidth="480"
- shell:SystemTray.IsVisible="True" CacheMode="BitmapCache">
+ shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
diff --git a/Juick/Properties/AssemblyInfo.cs b/Juick/Properties/AssemblyInfo.cs index 7d007ab..d97b9eb 100644 --- a/Juick/Properties/AssemblyInfo.cs +++ b/Juick/Properties/AssemblyInfo.cs @@ -32,6 +32,6 @@ using System.Resources; //
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.1.0")]
-[assembly: AssemblyFileVersion("1.1.0")]
+[assembly: AssemblyVersion("1.1.0.2")]
+[assembly: AssemblyFileVersion("1.1.0.2")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
diff --git a/Juick/SampleData/ThreadViewModelSampleData.xaml b/Juick/SampleData/ThreadViewModelSampleData.xaml deleted file mode 100644 index 784bee3..0000000 --- a/Juick/SampleData/ThreadViewModelSampleData.xaml +++ /dev/null @@ -1,16 +0,0 @@ -<Juick_ViewModels:ThreadViewModel xmlns:Juick_ViewModels="clr-namespace:Juick.ViewModels" Caption="#333333" Mid="86" RestUri="Augue vestibulum ligula senectus dolor"> - <Juick_ViewModels:ThreadViewModel.Items> - <Juick_ViewModels:PostItem MessageText="Integer vestibulum maecenas mauris duis" - MID="51" RID="29" Status="Quisque adipiscing parturient nam vestibulum" - Username="@ugnich" /> - <Juick_ViewModels:PostItem MessageText="Lorem Ipsum - это текст-рыба, часто используемый в печати и вэб-дизайне. Lorem Ipsum является стандартной рыбой для текстов на латинице с начала XVI века. В то время некий безымянный печатник создал большую коллекцию размеров и форм шрифтов, используя Lorem Ipsum для распечатки образцов. Lorem Ipsum не только успешно пережил без заметных изменений пять веков, но и перешагнул в электронный дизайн. Его популяризации в новое время послужили публикация листов Letraset с образцами Lorem Ipsum в 60-х годах и, в более недавнее время, программы электронной вёрстки типа Aldus PageMaker, в шаблонах которых используется Lorem Ipsum." MID="21" RID="57" Status="Est donec etiam consequat convallis" Username="@ugnich"/> - <Juick_ViewModels:PostItem MessageText="Nullam ante bibendum vivamus dictumst" MID="91" RID="43" Status="Eleifend adipiscing" Username="@ugnich"/> - <Juick_ViewModels:PostItem MessageText="Parturient aliquam facilisi fermentum aliquet" MID="42" RID="12" Status="Hac leo" Username="Blandit fusce fringilla habitasse auctor"/> - <Juick_ViewModels:PostItem MessageText="Faucibus mus hendrerit arcu" MID="84" RID="29" Status="Diam nec habitant" Username="Eget himenaeos inceptos"/> - <Juick_ViewModels:PostItem MessageText="Vestibulum imperdiet malesuada congue penatibus" MID="48" RID="26" Status="Elit porttitor" Username="Lorem enim interdum"/> - <Juick_ViewModels:PostItem MessageText="Commodo conubia vestibulum erat cursus" MID="14" RID="70" Status="Cubilia lobortis tincidunt" Username="Nascetur eros dictum lectus"/> - <Juick_ViewModels:PostItem MessageText="Non pharetra tristique per" MID="80" RID="43" Status="Ultricies morbi" Username="Libero dapibus nulla"/> - <Juick_ViewModels:PostItem MessageText="Proin adipiscing nibh placerat" MID="65" RID="52" Status="Venenatis sed sem nisi" Username="Vulputate curabitur parturient egestas sit"/> - <Juick_ViewModels:PostItem MessageText="Phasellus nisl" MID="55" RID="25" Status="Vel euismod" Username="Pulvinar sagittis"/> - </Juick_ViewModels:ThreadViewModel.Items> -</Juick_ViewModels:ThreadViewModel> diff --git a/Juick/ThreadView.xaml b/Juick/ThreadView.xaml index 2f67219..2778e2f 100644 --- a/Juick/ThreadView.xaml +++ b/Juick/ThreadView.xaml @@ -1,55 +1,92 @@ -<phone:PhoneApplicationPage - x:Class="Juick.ThreadView" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" - xmlns:phoneshell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:controls="clr-namespace:Juick.Controls" xmlns:bindings="clr-namespace:Juick.Classes" - FontFamily="{StaticResource PhoneFontFamilyNormal}" - FontSize="{StaticResource PhoneFontSizeNormal}" - Foreground="{StaticResource PhoneForegroundBrush}" - SupportedOrientations="PortraitOrLandscape" Orientation="Portrait" - mc:Ignorable="d" d:DesignHeight="696" d:DesignWidth="480" - phoneshell:SystemTray.IsVisible="True" CacheMode="BitmapCache"> - - <!--LayoutRoot is the root grid where all page content is placed--> - <Grid x:Name="LayoutRoot" Background="Transparent" d:DataContext="{d:DesignData /SampleData/ThreadViewModelSampleData.xaml}"> - <Grid.RowDefinitions> - <RowDefinition Height="Auto"/> - <RowDefinition/> - </Grid.RowDefinitions> - - <!--TitlePanel contains the name of the application and page title--> - <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> - <TextBlock x:Name="ApplicationTitle" Style="{StaticResource PhoneTextNormalStyle}" Text="{Binding Caption}"> </TextBlock> - </StackPanel> - - <!--ContentPanel - place additional content here--> - <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> - <ListBox Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="ListBox_SelectionChanged" DataContext="{Binding}" - ItemTemplate="{StaticResource PostItemDataTemplate}"> - <ListBox.ItemContainerStyle> - <Style TargetType="ListBoxItem"> - <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter> - </Style> - </ListBox.ItemContainerStyle> - </ListBox> - </Grid> - </Grid> - - <phone:PhoneApplicationPage.ApplicationBar> - <phoneshell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> - <!--<phoneshell:ApplicationBarIconButton IconUri="/Images/appbar.feature.email.rest.png" Text="New post" Click="ApplicationBarIconButtonClick1"/> - <phoneshell:ApplicationBarIconButton IconUri="/Images/appbar.refresh.rest.png" Text="Refresh" Click="ApplicationBarIconButtonClick" />--> - - <phoneshell:ApplicationBar.MenuItems> - <phoneshell:ApplicationBarMenuItem Text="Recommend/Unrecommend" Click="RecommendBarMenuItem_Click"/> - <phoneshell:ApplicationBarMenuItem Text="Subscribe" Click="SubscribeBarMenuItem_Click"/> - <phoneshell:ApplicationBarMenuItem Text="Unsubscribe" Click="UnsubscribeBarMenuItem_Click"/> - </phoneshell:ApplicationBar.MenuItems> - </phoneshell:ApplicationBar> - </phone:PhoneApplicationPage.ApplicationBar> - -</phone:PhoneApplicationPage> +<phone:PhoneApplicationPage
+ x:Class="Juick.ThreadView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
+ xmlns:phoneshell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:controls="clr-namespace:Juick.Controls" xmlns:bindings="clr-namespace:Juick.Classes"
+ FontFamily="{StaticResource PhoneFontFamilyNormal}"
+ FontSize="{StaticResource PhoneFontSizeNormal}"
+ Foreground="{StaticResource PhoneForegroundBrush}"
+ SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
+ mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
+ phoneshell:SystemTray.IsVisible="True">
+
+ <!--LayoutRoot is the root grid where all page content is placed-->
+ <Grid x:Name="LayoutRoot" Background="Transparent">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <!--TitlePanel contains the name of the application and page title-->
+ <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
+ <TextBlock x:Name="ApplicationTitle" Text="{Binding Caption}" Style="{StaticResource PhoneTextNormalStyle}"/>
+ </StackPanel>
+
+ <!--ContentPanel - place additional content here-->
+ <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
+ <ListBox Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="ListBox_SelectionChanged">
+ <ListBox.ItemContainerStyle>
+ <Style TargetType="ListBoxItem">
+ <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
+ </Style>
+ </ListBox.ItemContainerStyle>
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <Border BorderBrush="{StaticResource PhoneForegroundBrush}" BorderThickness="0 0 0 1">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <!-- RowDefinition Height="Auto" / -->
+ </Grid.RowDefinitions>
+ <Image bindings:LowProfileImageLoader.UriSource="{Binding AvatarUri}" Grid.Row="0" Grid.Column="0" Margin="3" />
+ <TextBlock Text="{Binding Username}" Grid.Row="0" Grid.Column="1"
+ Margin="5,0,5,5" VerticalAlignment="Top"
+ HorizontalAlignment="Left"
+ FontFamily="{StaticResource PhoneFontFamilySemiLight}"
+ FontSize="{StaticResource PhoneFontSizeLarge}"
+ Style="{StaticResource PhoneTextAccentStyle}" />
+ <!--Style="{StaticResource PhoneTextNormalStyle}"-->
+ <controls:HyperLinkRichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
+ Foreground="{StaticResource PhoneForegroundBrush}"
+ Margin="5,0,5,5" VerticalAlignment="Top"
+ TextWrapping="Wrap" HorizontalAlignment="Left"
+ IsReadOnly="True" Text="{Binding MessageText}" />
+ <Image bindings:LowProfileImageLoader.UriSource="{Binding Attachment}" Grid.Row="2" Grid.Column="0" Margin="3" Grid.ColumnSpan="2" />
+ <!-- TextBlock Text="{Binding Status}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
+ Foreground="{StaticResource PhoneForegroundBrush}"
+ Style="{StaticResource PhoneTextAccentStyle}"
+ FontSize="{StaticResource PhoneFontSizeSmall}"
+ Margin="5,0,5,5" VerticalAlignment="Top"
+ TextWrapping="Wrap" HorizontalAlignment="Left"/ -->
+ </Grid>
+ </Border>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+ </Grid>
+ </Grid>
+
+ <phone:PhoneApplicationPage.ApplicationBar>
+ <phoneshell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
+ <!--<phoneshell:ApplicationBarIconButton IconUri="/Images/appbar.feature.email.rest.png" Text="New post" Click="ApplicationBarIconButtonClick1"/>
+ <phoneshell:ApplicationBarIconButton IconUri="/Images/appbar.refresh.rest.png" Text="Refresh" Click="ApplicationBarIconButtonClick" />-->
+
+ <phoneshell:ApplicationBar.MenuItems>
+ <phoneshell:ApplicationBarMenuItem Text="Recommend/Unrecommend" Click="RecommendBarMenuItem_Click"/>
+ <phoneshell:ApplicationBarMenuItem Text="Subscribe" Click="SubscribeBarMenuItem_Click"/>
+ <phoneshell:ApplicationBarMenuItem Text="Unsubscribe" Click="UnsubscribeBarMenuItem_Click"/>
+ </phoneshell:ApplicationBar.MenuItems>
+ </phoneshell:ApplicationBar>
+ </phone:PhoneApplicationPage.ApplicationBar>
+
+</phone:PhoneApplicationPage>
diff --git a/Juick/ViewModels/AppViewModel.cs b/Juick/ViewModels/AppViewModel.cs index e3a58bb..4b30c08 100644 --- a/Juick/ViewModels/AppViewModel.cs +++ b/Juick/ViewModels/AppViewModel.cs @@ -19,7 +19,12 @@ namespace Juick.ViewModels readonly HttpNotificationChannel pushChannel; // The name of our push channel. - string channelName = "JuickChannel"; + private const string channelName = "JuickChannel"; + + public void UpdateNetworkStatus() + { + NetworkUnavailable = !DeviceNetworkInformation.IsNetworkAvailable; + } public void UpdateNetworkStatus() { @@ -33,24 +38,19 @@ namespace Juick.ViewModels pushChannel = HttpNotificationChannel.Find(channelName); // If the channel was not found, then create a new connection to the push service. - if (pushChannel == null) + if (_pushChannel == null) { - pushChannel = new HttpNotificationChannel(channelName); + _pushChannel = new HttpNotificationChannel(channelName); // Register for all the events before attempting to open the channel. - pushChannel.ChannelUriUpdated += (sender, e) => { - EnableNotifications(); - }; - pushChannel.ErrorOccurred += (sender, e) => - { - DisableNotifications(); - }; + _pushChannel.ChannelUriUpdated += (sender, e) => EnableNotifications(e.ChannelUri.ToString()); + _pushChannel.ErrorOccurred += (sender, e) => DisableNotifications(); // Register for this notification only if you need to receive the notifications while your application is running. // Register for this notification only if you need to receive the notifications while your application is running. - pushChannel.ShellToastNotificationReceived += (sender, e) => + _pushChannel.ShellToastNotificationReceived += (sender, e) => { - StringBuilder message = new StringBuilder(); + var message = new StringBuilder(); string relativeUri = string.Empty; message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString()); @@ -71,19 +71,21 @@ namespace Juick.ViewModels } Debug.WriteLine("Received: " + message.ToString()); }; - pushChannel.Open(); + + _pushChannel.Open(); + + // Bind this new channel for toast events. + _pushChannel.BindToShellToast(); + } else { // The channel was already open, so just register for all the events. - pushChannel.ChannelUriUpdated += (sender, e) => - { - EnableNotifications(); - }; - pushChannel.ErrorOccurred += (sender, e) => DisableNotifications(); + _pushChannel.ChannelUriUpdated += (sender, e) => EnableNotifications(e.ChannelUri.ToString()); + _pushChannel.ErrorOccurred += (sender, e) => DisableNotifications(); // Register for this notification only if you need to receive the notifications while your application is running. - pushChannel.ShellToastNotificationReceived += (sender, e) => + _pushChannel.ShellToastNotificationReceived += (sender, e) => { StringBuilder message = new StringBuilder(); string relativeUri = string.Empty; @@ -105,8 +107,10 @@ namespace Juick.ViewModels } } Debug.WriteLine("Received: " + message.ToString()); - }; - } + }; + + EnableNotifications(_pushChannel.ChannelUri.ToString()); + } } private ObservableCollection<PageViewModel> _pages; public ObservableCollection<PageViewModel> Pages @@ -141,6 +145,18 @@ namespace Juick.ViewModels } } + private bool _isNetworkUnavailable; + public bool NetworkUnavailable + { + get { return _isNetworkUnavailable; } + set + { + _isNetworkUnavailable = value; + NotifyPropertyChanged(IsNetworkAvailablePropertyName); + } + } + + private AccountManager _acc; public AccountManager Account @@ -160,23 +176,37 @@ namespace Juick.ViewModels } } - public void EnableNotifications() + public void EnableNotifications(string Url) { if (!Account.IsAuthenticated) return; - var channelUri = pushChannel.ChannelUri.ToString(); - if (channelUri == Account.NotificationUri) - return; - Account.NotificationUri = channelUri; - if (!pushChannel.IsShellToastBound) - // Bind this new channel for toast events. - pushChannel.BindToShellToast(); + Client.Authenticator = new HttpBasicAuthenticator(Account.UserName, Account.Password); + Debug.WriteLine(Url.ToString()); + if (string.IsNullOrEmpty(Account.NotificationUri) || Account.NotificationUri == Url) + { + Account.NotificationUri = Url; + RegisterNotificationUrl(Url); + } + else + { + UnregisterNotificationUrl(Account.NotificationUri); + Account.NotificationUri = Url; + RegisterNotificationUrl(Url); + } } public void DisableNotifications() { - if (pushChannel.IsShellToastBound) - pushChannel.UnbindToShellToast(); + UnregisterNotificationUrl(Account.NotificationUri); Account.NotificationUri = string.Empty; - } + } + + void RegisterNotificationUrl(string newUrl) + { + Client.ExecuteAsync(new RestRequest("/winphone/register?url=" + newUrl), response => Debug.WriteLine(response.StatusCode)); + } + void UnregisterNotificationUrl(string oldUrl) + { + Client.ExecuteAsync(new RestRequest("/winphone/unregister?url=" + oldUrl), response => Debug.WriteLine(response.StatusCode)); + } } } diff --git a/Juick/ViewModels/LoginViewModel.cs b/Juick/ViewModels/LoginViewModel.cs index c0bf1f9..95528fe 100644 --- a/Juick/ViewModels/LoginViewModel.cs +++ b/Juick/ViewModels/LoginViewModel.cs @@ -2,11 +2,12 @@ using System.Net; using System.Windows; using Juick.Classes; +using Juick.ViewModels.Validation; using RestSharp; namespace Juick.ViewModels { - public class LoginViewModel : ViewModelBase + public class LoginViewModel : DataViewModelBase { private string _username; private string _password; @@ -59,12 +60,11 @@ namespace Juick.ViewModels App.AppContext.Account.UserName = Username; App.AppContext.Account.Password = Password; App.AppContext.Account.IsAuthenticated = true; - App.AppContext.EnableNotifications(); ((App)Application.Current).NavigateTo(NextUri, true); } else { - MessageBox.Show("Invalid username or password", "Error", MessageBoxButton.OK); + AddError("Username", "Invalid username or password", false); } }); } diff --git a/Juick/ViewModels/NewPostViewModel.cs b/Juick/ViewModels/NewPostViewModel.cs deleted file mode 100644 index 3c28cc7..0000000 --- a/Juick/ViewModels/NewPostViewModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Net; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; -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; - -namespace Juick.ViewModels -{ - public class NewPostViewModel : ViewModelBase - { - public PostItem ReplyTo { get; set; } - - public PostItem Draft { get; set; } - - public BitmapImage Attachment { get; set; } - - public NewPostViewModel(PostItem replyTo) - { - ReplyTo = replyTo; - } - } -} diff --git a/Juick/ViewModels/PostItem.cs b/Juick/ViewModels/PostItem.cs index 88f6b86..97935b3 100644 --- a/Juick/ViewModels/PostItem.cs +++ b/Juick/ViewModels/PostItem.cs @@ -1,8 +1,6 @@ using System; using System.Net; using JuickApi; -using Juick.Classes; -using System.Globalization; namespace Juick.ViewModels { @@ -13,11 +11,8 @@ namespace Juick.ViewModels MID = message.Mid; RID = message.Rid; Username = message.User.UName; - // Juick timestamp in utc: 2013-04-22 13:14:30 - var timestamp = DateTime.ParseExact(message.Timestamp, "yyyy-MM-dd HH:mm:ss", null); - Status = string.Format("{0}", DateHelper.PrettyDate(timestamp.ToLocalTime())); - if (message.Replies > 0) - Status = string.Format("{0}, replies: {1}", Status, message.Replies); + Status = string.Format("Posted on: {0}, replies: {1}", message.Timestamp, message.Replies); + MessageText = HttpUtility.HtmlDecode(message.Body); if (message.Tags != null) |