Skip to content

Commit

Permalink
use default category on wear os
Browse files Browse the repository at this point in the history
  • Loading branch information
jamie-mh committed Feb 11, 2021
1 parent f19e75d commit e8270b5
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<ItemGroup>
<Compile Include="Source\Query\WearCategory.cs" />
<Compile Include="Source\Query\WearCustomIcon.cs" />
<Compile Include="Source\Query\WearPreferences.cs" />
<Compile Include="Source\Util\AnimUtil.cs" />
<Compile Include="Source\Query\WearAuthenticator.cs" />
<Compile Include="Resources\Resource.designer.cs" />
Expand Down
12 changes: 12 additions & 0 deletions AuthenticatorPro.Droid.Shared/Source/Query/WearPreferences.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace AuthenticatorPro.Droid.Shared.Query
{
public class WearPreferences
{
public readonly string DefaultCategory;

public WearPreferences(string defaultCategory)
{
DefaultCategory = defaultCategory;
}
}
}
2 changes: 1 addition & 1 deletion AuthenticatorPro.Droid/Resources/values/wear.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@array/android_wear_capabilities">
<string-array name="android_wear_capabilities">
<item>protocol_v2</item>
<item>protocol_v2.1</item>
</string-array>
</resources>
16 changes: 16 additions & 0 deletions AuthenticatorPro.Droid/Source/Service/WearQueryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ internal class WearQueryService : WearableListenerService
private const string ListCategoriesCapability = "list_categories";
private const string ListCustomIconsCapability = "list_custom_icons";
private const string GetCustomIconCapability = "get_custom_icon";
private const string GetPreferencesCapability = "get_preferences";

private readonly Lazy<Task> _initTask;

Expand Down Expand Up @@ -127,6 +128,17 @@ await WearableClass.GetMessageClient(this)
.SendMessageAsync(nodeId, GetCustomIconCapability, data);
}

private async Task GetPreferences(string nodeId)
{
var preferences = new PreferenceWrapper(this);
var settings = new WearPreferences(preferences.DefaultCategory);
var json = JsonConvert.SerializeObject(settings);
var data = Encoding.UTF8.GetBytes(json);

await WearableClass.GetMessageClient(this)
.SendMessageAsync(nodeId, GetPreferencesCapability, data);
}

public override async void OnMessageReceived(IMessageEvent messageEvent)
{
await _initTask.Value;
Expand All @@ -151,6 +163,10 @@ public override async void OnMessageReceived(IMessageEvent messageEvent)
await GetCustomIcon(id, messageEvent.SourceNodeId);
break;
}

case GetPreferencesCapability:
await GetPreferences(messageEvent.SourceNodeId);
break;
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion AuthenticatorPro.WearOS/AuthenticatorPro.WearOS.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down Expand Up @@ -85,6 +85,7 @@
<Compile Include="Source\Activity\MainActivity.cs" />
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Source\Util\PreferenceWrapper.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Assets\AboutAssets.txt" />
Expand Down Expand Up @@ -124,6 +125,9 @@
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData">
<Version>2.2.0.4</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Preference">
<Version>1.1.1.6</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Wear">
<Version>1.1.0.1</Version>
</PackageReference>
Expand Down
102 changes: 79 additions & 23 deletions AuthenticatorPro.WearOS/Source/Activity/MainActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using AuthenticatorPro.WearOS.Cache;
using AuthenticatorPro.WearOS.Data;
using AuthenticatorPro.WearOS.List;
using AuthenticatorPro.WearOS.Util;
using Newtonsoft.Json;


Expand All @@ -28,11 +29,12 @@ namespace AuthenticatorPro.WearOS.Activity
internal class MainActivity : AppCompatActivity, MessageClient.IOnMessageReceivedListener
{
// Query Paths
private const string ProtocolVersion = "protocol_v2";
private const string ProtocolVersion = "protocol_v2.1";
private const string ListAuthenticatorsCapability = "list_authenticators";
private const string ListCategoriesCapability = "list_categories";
private const string ListCustomIconsCapability = "list_custom_icons";
private const string GetCustomIconCapability = "get_custom_icon";
private const string GetPreferencesCapability = "get_preferences";
private const string RefreshCapability = "refresh";

// Cache Names
Expand All @@ -44,12 +46,14 @@ internal class MainActivity : AppCompatActivity, MessageClient.IOnMessageReceive
private RelativeLayout _loadingLayout;
private RelativeLayout _emptyLayout;
private WearableRecyclerView _authList;
private WearableNavigationDrawerView _categoryList;

// Data
private AuthenticatorSource _authSource;
private ListCache<WearAuthenticator> _authCache;
private ListCache<WearCategory> _categoryCache;
private CustomIconCache _customIconCache;
private PreferenceWrapper _preferences;

private AuthenticatorListAdapter _authListAdapter;
private CategoryListAdapter _categoryListAdapter;
Expand All @@ -61,11 +65,13 @@ internal class MainActivity : AppCompatActivity, MessageClient.IOnMessageReceive

// Lifecycle Synchronisation
private readonly SemaphoreSlim _onCreateLock;
private readonly SemaphoreSlim _refreshLock;


public MainActivity()
{
_onCreateLock = new SemaphoreSlim(1, 1);
_onCreateLock = new SemaphoreSlim(1, 1);
_refreshLock = new SemaphoreSlim(1, 1);
}

#region Activity Lifecycle
Expand All @@ -76,6 +82,8 @@ protected override async void OnCreate(Bundle bundle)
await _onCreateLock.WaitAsync();
SetContentView(Resource.Layout.activityMain);

_preferences = new PreferenceWrapper(this);

_authCache = new ListCache<WearAuthenticator>(AuthenticatorCacheName, this);
_categoryCache = new ListCache<WearCategory>(CategoryCacheName, this);
_customIconCache = new CustomIconCache(this);
Expand Down Expand Up @@ -103,12 +111,36 @@ protected override async void OnResume()
}
catch(ApiException)
{
RunOnUiThread(UpdateViewState);
RunOnUiThread(CheckOfflineState);
return;
}

RunOnUiThread(UpdateViewState);
RunOnUiThread(CheckOfflineState);
await Refresh();

await _refreshLock.WaitAsync();
_refreshLock.Release();

var defaultCategory = _preferences.DefaultCategory;

if(defaultCategory == null)
{
RunOnUiThread(CheckEmptyState);
return;
}

_authSource.SetCategory(defaultCategory);
var position = _categoryCache.FindIndex(c => c.Id == defaultCategory) + 1;

if(position < 0)
return;

RunOnUiThread(delegate
{
_categoryList.SetCurrentItem(position, false);
_authListAdapter.NotifyDataSetChanged();
CheckEmptyState();
});
}

protected override async void OnPause()
Expand Down Expand Up @@ -144,17 +176,17 @@ private void InitViews()
_authListAdapter.HasStableIds = true;
_authList.SetAdapter(_authListAdapter);

var categoriesDrawer = FindViewById<WearableNavigationDrawerView>(Resource.Id.drawerCategories);
_categoryList = FindViewById<WearableNavigationDrawerView>(Resource.Id.drawerCategories);
_categoryListAdapter = new CategoryListAdapter(this, _categoryCache);
categoriesDrawer.SetAdapter(_categoryListAdapter);
categoriesDrawer.ItemSelected += OnCategorySelected;
_categoryList.SetAdapter(_categoryListAdapter);
_categoryList.ItemSelected += OnCategorySelected;
}

private void OnCategorySelected(object sender, WearableNavigationDrawerView.ItemSelectedEventArgs e)
{
if(e.Pos > 0)
{
var category = _categoryCache.Get(e.Pos - 1);
var category = _categoryCache[e.Pos - 1];

if(category == null)
return;
Expand All @@ -165,20 +197,27 @@ private void OnCategorySelected(object sender, WearableNavigationDrawerView.Item
_authSource.SetCategory(null);

_authListAdapter.NotifyDataSetChanged();
UpdateViewState();
CheckEmptyState();
}

private void CheckOfflineState()
{
if(_serverNode == null)
{
AnimUtil.FadeOutView(_loadingLayout, AnimUtil.LengthShort);
_offlineLayout.Visibility = ViewStates.Visible;
}
else
_offlineLayout.Visibility = ViewStates.Invisible;
}

private void UpdateViewState()
private void CheckEmptyState()
{
if(_loadingLayout.Visibility == ViewStates.Visible)
AnimUtil.FadeOutView(_loadingLayout, AnimUtil.LengthShort);

_emptyLayout.Visibility = ViewStates.Gone;

_offlineLayout.Visibility = _serverNode == null
? ViewStates.Visible
: ViewStates.Gone;

if(_authSource.GetView().Count == 0)
_emptyLayout.Visibility = ViewStates.Visible;
else
Expand Down Expand Up @@ -263,18 +302,23 @@ private async Task Refresh()
{
if(_serverNode == null)
return;

await _refreshLock.WaitAsync();

Interlocked.Exchange(ref _responsesReceived, 0);
Interlocked.Exchange(ref _responsesRequired, 3);
Interlocked.Exchange(ref _responsesRequired, 4);

await WearableClass.GetMessageClient(this)
.SendMessageAsync(_serverNode.Id, ListAuthenticatorsCapability, new byte[] { });

await WearableClass.GetMessageClient(this)
.SendMessageAsync(_serverNode.Id, ListCategoriesCapability, new byte[] { });
var client = WearableClass.GetMessageClient(this);

await WearableClass.GetMessageClient(this)
.SendMessageAsync(_serverNode.Id, ListCustomIconsCapability, new byte[] { });
async Task MakeRequest(string capability)
{
await client.SendMessageAsync(_serverNode.Id, capability, new byte[] { });
}

await MakeRequest(ListAuthenticatorsCapability);
await MakeRequest(ListCategoriesCapability);
await MakeRequest(ListCustomIconsCapability);
await MakeRequest(GetPreferencesCapability);
}

private async Task OnAuthenticatorListReceived(byte[] data)
Expand Down Expand Up @@ -330,6 +374,14 @@ private async Task OnCustomIconReceived(byte[] data)

await _customIconCache.Add(icon.Id, icon.Data);
}

private void OnPreferencesReceived(byte[] data)
{
var json = Encoding.UTF8.GetString(data);
var prefs = JsonConvert.DeserializeObject<WearPreferences>(json);

_preferences.DefaultCategory = prefs.DefaultCategory;
}

public async void OnMessageReceived(IMessageEvent messageEvent)
{
Expand All @@ -350,6 +402,10 @@ public async void OnMessageReceived(IMessageEvent messageEvent)
case GetCustomIconCapability:
await OnCustomIconReceived(messageEvent.GetData());
break;

case GetPreferencesCapability:
OnPreferencesReceived(messageEvent.GetData());
break;

case RefreshCapability:
await Refresh();
Expand All @@ -362,7 +418,7 @@ public async void OnMessageReceived(IMessageEvent messageEvent)
var required = Interlocked.CompareExchange(ref _responsesRequired, 0, 0);

if(received == required)
RunOnUiThread(UpdateViewState);
_refreshLock.Release();
}
#endregion
}
Expand Down
39 changes: 31 additions & 8 deletions AuthenticatorPro.WearOS/Source/Cache/ListCache.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Android.Content;
using System;
using System.Collections;
using Android.Content;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -9,13 +11,13 @@

namespace AuthenticatorPro.WearOS.Cache
{
internal class ListCache<T>
internal class ListCache<T> : IEnumerable
{
private readonly string _name;
private readonly Context _context;
private readonly SemaphoreSlim _flushLock;

private List<T> _items;

public int Count => _items.Count;

public ListCache(string name, Context context)
Expand Down Expand Up @@ -48,7 +50,7 @@ public async Task Replace(List<T> items)
await Flush();
}

public bool Dirty(List<T> items, IEqualityComparer<T> comparer = null)
public bool Dirty(IEnumerable<T> items, IEqualityComparer<T> comparer = null)
{
return comparer != null
? !_items.SequenceEqual(items, comparer)
Expand All @@ -70,14 +72,35 @@ private async Task Flush()
}
}

public T Get(int position)
public List<T> GetItems()
{
return _items.ElementAtOrDefault(position);
return _items;
}

public List<T> GetItems()
public bool Contains(T item)
{
return _items;
return _items.Contains(item);
}

private IEnumerator<T> GetEnumerator()
{
return _items.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public int FindIndex(Predicate<T> predicate)
{
return _items.FindIndex(predicate);
}

public T this[int index]
{
get => _items[index];
set => _items[index] = value;
}
}
}
2 changes: 1 addition & 1 deletion AuthenticatorPro.WearOS/Source/List/CategoryListAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override ICharSequence GetItemTextFormatted(int pos)
if(pos == 0)
return new String(_context.GetString(Resource.String.categoryAll));

var item = _cache.Get(pos - 1);
var item = _cache[pos - 1];

return item == null
? new String()
Expand Down
Loading

0 comments on commit e8270b5

Please sign in to comment.