Skip to content

Commit

Permalink
v2.1 (#55)
Browse files Browse the repository at this point in the history
* Update README

* Add Theme

* deprecated items

* Add VM Classes

* Rm Dotnet Core Test

* Add LoggerLib

* Add UnitTest

* Clean Code

* Use Logger

* Rename Source Folder for clarification

* Update README

* Oops :)

* RM old keys

* Rm OldUnitTestProj

* UI Changes

* Resharper suggestions

* Add ui concepts And Little ui changes

* ui update

* ui improvements

* improv Login + Singlton PocketHandler + Cleaning a bit

* Update UiUtil

* VM in MainPage

* VM in MainPage

* Half VM for MainContent

* New navview (#45)

* Fix Login Theme

* VM MainContent with Controls

* Rm MainPage

* TagsList Ctrl

* ArticleList Ctrl

* Fix ImageDialog

* Update Screenshots

* Fix All ListViews

* Bug fixes related to Themes

* Fix Minor Problems

* Encapsulate InAppNotification

* Fix InAppNotif UI

* Fix WhiteTheme

* Rm UserInfo from Settings

* Improve binding

* Fix Minor UI Bugs

* UPdate README

* Rm TagListCtrl

* little ui changes

* Fix WebViewBtn on Error Page (Issue #53)

* UpdateGitIgnore

* Minor fixes

* If there is no tag, get center

* Fix Caching the List

* Making sure first remove cache then Delete it from server - in case of exceptions

* Better tag loading

* Cache User Info

* Add UserStatistics
  • Loading branch information
yazdipour authored May 23, 2019
1 parent 0c1de77 commit 8491ac1
Show file tree
Hide file tree
Showing 14 changed files with 298 additions and 145 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Source/PocketX/Package.StoreAssociation.xml
Source/PocketX/Handlers/Keys.cs
14 changes: 8 additions & 6 deletions Source/PocketX/Controls/MarkdownControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:converter="using:PocketX.Converter"
Background="{x:Bind Settings.ReaderBg,Mode=OneWay}"
RequestedTheme="{x:Bind Settings.ReaderTheme,Mode=OneWay}"
mc:Ignorable="d">
<UserControl.Resources>
Expand Down Expand Up @@ -82,8 +81,7 @@
VerticalAlignment="Center" />
<StackPanel Orientation="Horizontal" Margin="0 8" HorizontalAlignment="Center">
<Button Content="Reload ArticleView" Click="Reload_ArticleView" />
<Button Margin="8 0" Content="Open WebView" Tag="webView"
Click="AppBar_Click" />
<Button Margin="8 0" Content="Open WebView" Tag="error" Click="AppBar_Click" />
</StackPanel>
</StackPanel>
<!--Audio Player-->
Expand Down Expand Up @@ -119,13 +117,17 @@
<!--Icon="{x:Bind ArchiveIcon,Mode=OneWay}"-->
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton Icon="Volume"
Label="Read"
Command="{x:Bind TextToSpeech}"/>

<AppBarButton Tag="Share"
Icon="Share"
Label="Share"
LabelPosition="Collapsed"
Width="48"
Margin="0 2 0 0"
Click="AppBar_Click" />
<AppBarButton Icon="Volume"
Label="Read"
Command="{x:Bind TextToSpeech}"/>
<CommandBar.SecondaryCommands>
<AppBarButton Click="AppBar_Click"
Tag="Favorite"
Expand Down
4 changes: 4 additions & 0 deletions Source/PocketX/Controls/MarkdownControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ private async void AppBar_Click(object sender, RoutedEventArgs e)
Utils.CopyToClipboard(Article?.Uri?.AbsoluteUri);
NotificationHandler.InAppNotification("Copied", 2000);
break;
case "error":
IsInTextView = true;
AppBar_Click("view", null);
break;
case "view":
if (IsInTextView)
{
Expand Down
13 changes: 13 additions & 0 deletions Source/PocketX/Converter/ArrayToStringConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using Windows.UI.Xaml.Data;

namespace PocketX.Converter
{
public class ArrayToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language) =>
string.Join(parameter is string spl ? spl : " ", value);

public object ConvertBack(object value, Type targetType, object parameter, string language) => value;
}
}
16 changes: 16 additions & 0 deletions Source/PocketX/Converter/HideIfEmptyConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;

namespace PocketX.Converter
{
public class HideIfEmptyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language) =>
value == null || value is string str && string.IsNullOrEmpty(str) || value is Array arr && arr.Length == 0
? Visibility.Collapsed
: Visibility.Visible;

public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException();
}
}
171 changes: 93 additions & 78 deletions Source/PocketX/Handlers/PocketHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using static Logger.Logger;

namespace PocketX.Handlers
{
internal class PocketHandler : INotifyPropertyChanged
{
public PocketClient Client;
public PocketUser User { get; set; }
private static PocketHandler _pocketHandler;
private PocketItem _currentPocketItem;
public ObservableCollection<string> Tags { set; get; } = new ObservableCollection<string>();
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected virtual void OnPropertyChanged(string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public PocketItem CurrentPocketItem
{
get => _currentPocketItem;
Expand All @@ -31,44 +32,39 @@ public PocketItem CurrentPocketItem
OnPropertyChanged(nameof(CurrentPocketItem));
}
}

public PocketUser User { get; set; }

#region Login\Logout

public static PocketHandler GetInstance() => _pocketHandler ?? (_pocketHandler = new PocketHandler());

public async void LoadCacheClient()
#region Login\Logout
public void LoadCacheClient()
{
var cache = new LocalObjectStorageHelper().Read(Keys.PocketClientCache, "");
Client = cache == "" ? null : new PocketClient(Keys.Pocket, cache);
try { if (Client != null) User = await Client.GetUser(); }
catch{ }
User = new LocalObjectStorageHelper().Read<PocketUser>(Keys.PocketClientCache + "user");
}

private void SaveCacheUser(PocketUser user)
=> new LocalObjectStorageHelper().Save(Keys.PocketClientCache, user.Code);

internal void Logout()
{
Logger.Logger.L("Logout");
L("Logout");
Client = null;
User = null;
_pocketHandler = null;
SettingsHandler.Clear();
BlobCache.LocalMachine.InvalidateAll();
BlobCache.LocalMachine.Vacuum();
new LocalObjectStorageHelper().Save(Keys.PocketClientCache, "");
new LocalObjectStorageHelper().Save(Keys.PocketClientCache + "user", "");
}

internal async Task<bool> LoginAsync()
public async Task<bool> LoginAsync()
{
User = await Client.GetUser();
if (User == null) return false;
SaveCacheUser(User);
new LocalObjectStorageHelper().Save(Keys.PocketClientCache, User.Code);
new LocalObjectStorageHelper().Save(Keys.PocketClientCache + "user", User);
return true;
}

internal async Task<Uri> LoginUriAsync()
public async Task<Uri> LoginUriAsync()
{
Client = new PocketClient(Keys.Pocket, callbackUri: App.Protocol);
await Client.GetRequestCode();
Expand All @@ -77,48 +73,6 @@ internal async Task<Uri> LoginUriAsync()

#endregion Login\Logout

internal async Task<(string, string)> AddFromShare(Uri url)
{
var SUCCESS = "Successfully Saved to Pocket";
var FAILED = "FAILED (Be Sure You Are Logged In)";
if (Client != null)
{
await Client.Add(url);
return (SUCCESS, url.AbsoluteUri);
}
try
{
_pocketHandler.LoadCacheClient();
await _pocketHandler.Client.Add(url);
return (SUCCESS, url.AbsoluteUri);
}
catch (Exception e) { return (FAILED, e.Message); }
}

internal async Task<IEnumerable<PocketItem>> GetListAsync(
State state, bool? favorite, string tag, string search, int count, int offset)
{
try
{
if (!Microsoft.Toolkit.Uwp.Connectivity.NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
throw new Exception();
var pocketItems = await Client.Get(
state: state, favorite: favorite,
tag: tag, contentType: null,
sort: Sort.newest, search: search,
domain: null, since: null,
count: count, offset: offset);

if (offset == 0) await SetItemsCache(pocketItems);
return pocketItems;
}
catch
{
if (offset == 0) return await GetItemsCache();
else return null;
}
}

#region Cache Items

internal async Task<IEnumerable<PocketItem>> GetItemsCache()
Expand Down Expand Up @@ -165,7 +119,49 @@ internal async Task SetItemCache(int index, PocketItem item)

#endregion Cache Items

internal async Task<string> Read(Uri url, bool force)
#region Tags
public async Task FetchOnlineTagsAsync()
{
var tags = (await Client.GetTags()).ToArray().Select(o => o.Name).ToArray();
if (!tags.Any()) return;
Tags.Clear();
foreach (var t in tags) Tags?.Add(t);
if (Tags?.Count > 0)
{
OnPropertyChanged(nameof(Tags));
await BlobCache.LocalMachine.InsertObject("tags", Tags);
}
}
public async Task FetchOfflineTagsAsync()
{
foreach (var t in await BlobCache.LocalMachine.GetObject<IEnumerable<string>>("tags")) Tags?.Add(t);
if (Tags?.Count > 0) OnPropertyChanged(nameof(Tags));
}
public async Task FetchTagsAsync()
{
if (Tags.Count > 0) return;
try
{
await FetchOfflineTagsAsync();
}
catch (Exception e)
{
E(e);
}
try
{
await FetchOnlineTagsAsync();
}
catch (Exception e)
{
E(e);
}
}
#endregion

public async Task<PocketStatistics> UserStatistics() => await Client.GetUserStatistics();

public async Task<string> Read(Uri url, bool force)
{
var cache = await BlobCache.LocalMachine.GetObject<string>(url?.AbsoluteUri)
.Catch(Observable.Return(""));
Expand All @@ -180,40 +176,59 @@ internal async Task<string> Read(Uri url, bool force)
return content;
}

internal async Task FetchTagsAsync()
public async Task<(string, string)> AddFromShare(Uri url)
{
const string success = "Successfully Saved to Pocket";
const string failed = "FAILED (Be Sure You Are Logged In)";
if (Client != null)
{
await Client.Add(url);
return (success, url.AbsoluteUri);
}
try
{
_pocketHandler.LoadCacheClient();
await _pocketHandler.Client.Add(url);
return (success, url.AbsoluteUri);
}
catch (Exception e) { return (failed, e.Message); }
}

public async Task<IEnumerable<PocketItem>> GetListAsync(
State state, bool? favorite, string tag, string search, int count, int offset)
{
try
{
if (Tags?.Count > 0) return;
var offlineTags = await BlobCache.LocalMachine.GetObject<ObservableCollection<string>>("tags");
if (offlineTags != null)
foreach (var t in offlineTags)
Tags?.Add(t);
var tags = (await Client.GetTags()).ToList().Select(o => o.Name);
var enumerable = tags as string[] ?? tags.ToArray();
if (enumerable.Length < 1) return;
Tags.Clear();
foreach (var t in enumerable) Tags?.Add(t);
await BlobCache.LocalMachine.InsertObject("tags", Tags);
if (!Microsoft.Toolkit.Uwp.Connectivity.NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
throw new Exception();
var pocketItems = await Client.Get(
state: state, favorite: favorite,
tag: tag, contentType: null,
sort: Sort.newest, search: search,
domain: null, since: null,
count: count, offset: offset);

if (state == State.unread && tag == null && search == null && offset == 0)
await SetItemsCache(pocketItems);
return pocketItems;
}
catch { }
finally
catch
{
OnPropertyChanged(nameof(Tags));
return state == State.unread && tag == null && search == null && offset == 0 ? await GetItemsCache() : null;
}
}

internal async Task Delete(PocketItem pocketItem)
public async Task Delete(PocketItem pocketItem)
{
try
{
await Client.Delete(pocketItem);
await BlobCache.LocalMachine.Invalidate(pocketItem.Uri.AbsoluteUri);
await BlobCache.LocalMachine.Invalidate("plain_" + pocketItem.Uri.AbsoluteUri);
await Client.Delete(pocketItem);
}
catch (Exception e)
{
Logger.Logger.E(e);
E(e);
}
}

Expand Down
Loading

0 comments on commit 8491ac1

Please sign in to comment.