summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Juick/App.xaml19
-rw-r--r--Juick/Classes/AccountManager.cs40
-rw-r--r--Juick/Classes/BooleanToVisibiltyConverter.cs24
-rw-r--r--Juick/Classes/DateHelper.cs67
-rw-r--r--Juick/Controls/MessageList.xaml45
-rw-r--r--Juick/DataTemplates/PostItemDataTemplate.xaml44
-rw-r--r--Juick/Juick.csproj13
-rw-r--r--Juick/LoginView.xaml3
-rw-r--r--Juick/MainPage.xaml.cs2
-rw-r--r--Juick/NewPostView.xaml2
-rw-r--r--Juick/Properties/AssemblyInfo.cs4
-rw-r--r--Juick/SampleData/ThreadViewModelSampleData.xaml16
-rw-r--r--Juick/ThreadView.xaml147
-rw-r--r--Juick/ViewModels/AppViewModel.cs94
-rw-r--r--Juick/ViewModels/LoginViewModel.cs6
-rw-r--r--Juick/ViewModels/NewPostViewModel.cs28
-rw-r--r--Juick/ViewModels/PostItem.cs9
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)