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, 315 insertions, 248 deletions
diff --git a/Juick/App.xaml b/Juick/App.xaml
index 0c60cc0..1b67f8c 100644
--- a/Juick/App.xaml
+++ b/Juick/App.xaml
@@ -1,20 +1,25 @@
-<Application
- x:Class="Juick.App"
+<Application
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">
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
+ x:Class="Juick.App"
+ >
- <!--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 1f9ffe5..eb99d92 100644
--- a/Juick/Classes/AccountManager.cs
+++ b/Juick/Classes/AccountManager.cs
@@ -3,6 +3,8 @@ using System.IO.IsolatedStorage;
using System.Net;
using System.Windows;
using System.Windows.Controls;
+using RestSharp;
+using System.Diagnostics;
namespace Juick.Classes
{
@@ -10,14 +12,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;
}
@@ -34,7 +36,7 @@ namespace Juick.Classes
{
if (_password == null)
{
- IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("password", out _password);
+ IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("password", out _password);
}
return _password;
}
@@ -47,7 +49,8 @@ namespace Juick.Classes
public bool IsAuthenticated
{
- get {
+ get
+ {
bool authenticated;
IsolatedStorageSettings.ApplicationSettings.TryGetValue<bool>("authenticated", out authenticated);
return authenticated;
@@ -55,26 +58,45 @@ namespace Juick.Classes
set { IsolatedStorageSettings.ApplicationSettings["authenticated"] = value; }
}
+
+
public string NotificationUri
{
get
{
- string savedUri;
- IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("notification_uri", out savedUri);
- return savedUri;
+ string _notificationUri;
+ IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("notification_uri", out _notificationUri);
+ return _notificationUri;
}
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
deleted file mode 100644
index 679cc3f..0000000
--- a/Juick/Classes/BooleanToVisibiltyConverter.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-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
new file mode 100644
index 0000000..072c56a
--- /dev/null
+++ b/Juick/Classes/DateHelper.cs
@@ -0,0 +1,67 @@
+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 afa6c69..ac6db00 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">
+ ItemsSource="{Binding Items}" IsFlatList="true" ItemTemplate="{StaticResource PostItemDataTemplate}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Link">
<bindings:InvokeDelegateCommandAction Command="{Binding LoadMessagesPageCommand}"
@@ -25,46 +25,7 @@
<bindings:InvokeDelegateCommandAction Command="{Binding NavigateNextCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=InvokeParameter}"/>
</i:EventTrigger>
- </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>
+ </i:Interaction.Triggers>
</toolkit:LongListSelector>
</Grid>
</UserControl>
diff --git a/Juick/DataTemplates/PostItemDataTemplate.xaml b/Juick/DataTemplates/PostItemDataTemplate.xaml
new file mode 100644
index 0000000..4668a48
--- /dev/null
+++ b/Juick/DataTemplates/PostItemDataTemplate.xaml
@@ -0,0 +1,44 @@
+<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 0163f65..c89c775 100644
--- a/Juick/Juick.csproj
+++ b/Juick/Juick.csproj
@@ -27,6 +27,8 @@
<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>
@@ -109,7 +111,6 @@
<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>
@@ -121,6 +122,10 @@
<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>
@@ -192,6 +197,12 @@
<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 004580a..3e204a4 100644
--- a/Juick/LoginView.xaml
+++ b/Juick/LoginView.xaml
@@ -9,10 +9,9 @@
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">
+ phoneshell:SystemTray.IsVisible="True" CacheMode="BitmapCache">
<phone:PhoneApplicationPage.DataContext>
<viewModels:LoginViewModel />
</phone:PhoneApplicationPage.DataContext>
diff --git a/Juick/MainPage.xaml.cs b/Juick/MainPage.xaml.cs
index 20beef5..7baa6dd 100644
--- a/Juick/MainPage.xaml.cs
+++ b/Juick/MainPage.xaml.cs
@@ -70,7 +70,7 @@ namespace Juick
}
if (!string.IsNullOrEmpty(FileId) || navigateUri.StartsWith(loginUriPart))
{
- NavigationService.Navigate(new Uri(navigateUri, UriKind.Relative));
+ ((App)Application.Current).NavigateTo(new Uri(navigateUri, UriKind.Relative), true);
}
if (queryStrings.ContainsKey("mid"))
{
diff --git a/Juick/NewPostView.xaml b/Juick/NewPostView.xaml
index f3a911b..1ed01b5 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">
+ shell:SystemTray.IsVisible="True" CacheMode="BitmapCache">
<!--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 d97b9eb..7d007ab 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.2")]
-[assembly: AssemblyFileVersion("1.1.0.2")]
+[assembly: AssemblyVersion("1.1.0")]
+[assembly: AssemblyFileVersion("1.1.0")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
diff --git a/Juick/SampleData/ThreadViewModelSampleData.xaml b/Juick/SampleData/ThreadViewModelSampleData.xaml
new file mode 100644
index 0000000..784bee3
--- /dev/null
+++ b/Juick/SampleData/ThreadViewModelSampleData.xaml
@@ -0,0 +1,16 @@
+<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 2778e2f..2f67219 100644
--- a/Juick/ThreadView.xaml
+++ b/Juick/ThreadView.xaml
@@ -1,92 +1,55 @@
-<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>
+<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>
diff --git a/Juick/ViewModels/AppViewModel.cs b/Juick/ViewModels/AppViewModel.cs
index 4b30c08..e3a58bb 100644
--- a/Juick/ViewModels/AppViewModel.cs
+++ b/Juick/ViewModels/AppViewModel.cs
@@ -19,12 +19,7 @@ namespace Juick.ViewModels
readonly HttpNotificationChannel pushChannel;
// The name of our push channel.
- private const string channelName = "JuickChannel";
-
- public void UpdateNetworkStatus()
- {
- NetworkUnavailable = !DeviceNetworkInformation.IsNetworkAvailable;
- }
+ string channelName = "JuickChannel";
public void UpdateNetworkStatus()
{
@@ -38,19 +33,24 @@ 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(e.ChannelUri.ToString());
- _pushChannel.ErrorOccurred += (sender, e) => DisableNotifications();
+ pushChannel.ChannelUriUpdated += (sender, e) => {
+ EnableNotifications();
+ };
+ 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) =>
{
- var message = new StringBuilder();
+ StringBuilder message = new StringBuilder();
string relativeUri = string.Empty;
message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
@@ -71,21 +71,19 @@ namespace Juick.ViewModels
}
Debug.WriteLine("Received: " + message.ToString());
};
-
- _pushChannel.Open();
-
- // Bind this new channel for toast events.
- _pushChannel.BindToShellToast();
-
+ pushChannel.Open();
}
else
{
// The channel was already open, so just register for all the events.
- _pushChannel.ChannelUriUpdated += (sender, e) => EnableNotifications(e.ChannelUri.ToString());
- _pushChannel.ErrorOccurred += (sender, e) => DisableNotifications();
+ pushChannel.ChannelUriUpdated += (sender, e) =>
+ {
+ EnableNotifications();
+ };
+ 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;
@@ -107,10 +105,8 @@ namespace Juick.ViewModels
}
}
Debug.WriteLine("Received: " + message.ToString());
- };
-
- EnableNotifications(_pushChannel.ChannelUri.ToString());
- }
+ };
+ }
}
private ObservableCollection<PageViewModel> _pages;
public ObservableCollection<PageViewModel> Pages
@@ -145,18 +141,6 @@ namespace Juick.ViewModels
}
}
- private bool _isNetworkUnavailable;
- public bool NetworkUnavailable
- {
- get { return _isNetworkUnavailable; }
- set
- {
- _isNetworkUnavailable = value;
- NotifyPropertyChanged(IsNetworkAvailablePropertyName);
- }
- }
-
-
private AccountManager _acc;
public AccountManager Account
@@ -176,37 +160,23 @@ namespace Juick.ViewModels
}
}
- public void EnableNotifications(string Url)
+ public void EnableNotifications()
{
if (!Account.IsAuthenticated) return;
- 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);
- }
+ 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();
}
public void DisableNotifications()
{
- UnregisterNotificationUrl(Account.NotificationUri);
+ if (pushChannel.IsShellToastBound)
+ pushChannel.UnbindToShellToast();
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 95528fe..c0bf1f9 100644
--- a/Juick/ViewModels/LoginViewModel.cs
+++ b/Juick/ViewModels/LoginViewModel.cs
@@ -2,12 +2,11 @@
using System.Net;
using System.Windows;
using Juick.Classes;
-using Juick.ViewModels.Validation;
using RestSharp;
namespace Juick.ViewModels
{
- public class LoginViewModel : DataViewModelBase
+ public class LoginViewModel : ViewModelBase
{
private string _username;
private string _password;
@@ -60,11 +59,12 @@ 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
{
- AddError("Username", "Invalid username or password", false);
+ MessageBox.Show("Invalid username or password", "Error", MessageBoxButton.OK);
}
});
}
diff --git a/Juick/ViewModels/NewPostViewModel.cs b/Juick/ViewModels/NewPostViewModel.cs
new file mode 100644
index 0000000..3c28cc7
--- /dev/null
+++ b/Juick/ViewModels/NewPostViewModel.cs
@@ -0,0 +1,28 @@
+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 97935b3..88f6b86 100644
--- a/Juick/ViewModels/PostItem.cs
+++ b/Juick/ViewModels/PostItem.cs
@@ -1,6 +1,8 @@
using System;
using System.Net;
using JuickApi;
+using Juick.Classes;
+using System.Globalization;
namespace Juick.ViewModels
{
@@ -11,8 +13,11 @@ namespace Juick.ViewModels
MID = message.Mid;
RID = message.Rid;
Username = message.User.UName;
- Status = string.Format("Posted on: {0}, replies: {1}", message.Timestamp, message.Replies);
-
+ // 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);
MessageText = HttpUtility.HtmlDecode(message.Body);
if (message.Tags != null)