diff --git a/PokemonGo-UWP/App.xaml.cs b/PokemonGo-UWP/App.xaml.cs
index 6a4241419..d8da50fd7 100644
--- a/PokemonGo-UWP/App.xaml.cs
+++ b/PokemonGo-UWP/App.xaml.cs
@@ -40,7 +40,7 @@ sealed partial class App : BootStrapper
/// Stores the current instance for the app.
///
private readonly DisplayRequest _displayRequest;
-
+
#endregion
#region Properties
@@ -83,7 +83,7 @@ public App()
private static async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
e.Handled = true;
- await ExceptionHandler.HandleException();
+ await ExceptionHandler.HandleException(new Exception(e.Message));
// We should be logging these exceptions too so they can be tracked down.
HockeyClient.Current.TrackException(e.Exception);
}
@@ -96,7 +96,7 @@ private static void TaskScheduler_UnobservedTaskException(object sender, Unobser
}
///
- ///
+ ///
///
///
///
@@ -195,7 +195,7 @@ public override async Task OnInitializeAsync(IActivatedEventArgs args)
}
///
- ///
+ ///
///
///
///
diff --git a/PokemonGo-UWP/Entities/FortDataWrapper.cs b/PokemonGo-UWP/Entities/FortDataWrapper.cs
index 8c3904a83..a1d4dd07f 100644
--- a/PokemonGo-UWP/Entities/FortDataWrapper.cs
+++ b/PokemonGo-UWP/Entities/FortDataWrapper.cs
@@ -59,11 +59,11 @@ public FortDataWrapper(FortData fortData)
/// the actual capture method.
///
public DelegateCommand TrySearchPokestop => _trySearchPokestop ?? (
- _trySearchPokestop = new DelegateCommand(() =>
+ _trySearchPokestop = new DelegateCommand(async () =>
{
NavigationHelper.NavigationState["CurrentPokestop"] = this;
// Disable map update
- GameClient.ToggleUpdateTimer(false);
+ await GameClient.ToggleUpdateTimer(false);
BootStrapper.Current.NavigationService.Navigate(typeof(SearchPokestopPage));
}, () => true)
);
diff --git a/PokemonGo-UWP/Entities/MapPokemonWrapper.cs b/PokemonGo-UWP/Entities/MapPokemonWrapper.cs
index 075cb56ae..a8f3c30fd 100644
--- a/PokemonGo-UWP/Entities/MapPokemonWrapper.cs
+++ b/PokemonGo-UWP/Entities/MapPokemonWrapper.cs
@@ -32,11 +32,11 @@ public MapPokemonWrapper(MapPokemon mapPokemon)
/// We're just navigating to the capture page, reporting that the player wants to capture the selected Pokemon.
///
public DelegateCommand TryCatchPokemon => _tryCatchPokemon ?? (
- _tryCatchPokemon = new DelegateCommand(() =>
+ _tryCatchPokemon = new DelegateCommand(async () =>
{
NavigationHelper.NavigationState["CurrentPokemon"] = this;
// Disable map update
- GameClient.ToggleUpdateTimer(false);
+ await GameClient.ToggleUpdateTimer(false);
BootStrapper.Current.NavigationService.Navigate(typeof(CapturePokemonPage));
}, () => true)
);
diff --git a/PokemonGo-UWP/Utils/GameClient.cs b/PokemonGo-UWP/Utils/GameClient.cs
index 53604b0b0..69e8782e2 100644
--- a/PokemonGo-UWP/Utils/GameClient.cs
+++ b/PokemonGo-UWP/Utils/GameClient.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
@@ -12,6 +13,7 @@
using PokemonGo.RocketAPI.Enums;
using PokemonGo.RocketAPI.Extensions;
using PokemonGo_UWP.Entities;
+using PokemonGo_UWP.ViewModels;
using POGOProtos.Data;
using POGOProtos.Data.Player;
using POGOProtos.Enums;
@@ -23,6 +25,7 @@
using POGOProtos.Settings;
using POGOProtos.Settings.Master;
using Q42.WinRT.Data;
+using Template10.Common;
using Template10.Utils;
using Universal_Authenticator_v2.Views;
@@ -56,13 +59,11 @@ public async Task HandleApiFailure(RequestEnvelope request, Respon
await Task.Delay(500);
_retryCount++;
- if (_retryCount%5 == 0)
- {
- // Let's try to refresh the session by getting a new token
- await
- (_clientSettings.AuthType == AuthType.Google
- ? DoGoogleLogin(_clientSettings.GoogleUsername, _clientSettings.GooglePassword)
- : DoPtcLogin(_clientSettings.PtcUsername, _clientSettings.PtcPassword));
+ if (_retryCount % 5 == 0)
+ {
+ await DoRelogin();
+ Debug.WriteLine("[Relogin] Stopping API via ApiHandledException.");
+ throw new ApiHandledException("Relogin completed.");
}
return ApiOperation.Retry;
@@ -234,15 +235,15 @@ public static async Task InitializeClient()
}
catch (Exception e)
{
- if (e is PokemonGo.RocketAPI.Exceptions.AccessTokenExpiredException)
- {
- await Relogin();
- }
- else throw;
+ if (e is PokemonGo.RocketAPI.Exceptions.AccessTokenExpiredException)
+ {
+ await Relogin();
+ }
+ else throw;
}
}
- public static async Task Relogin()
- {
+ public static async Task Relogin()
+ {
switch (_clientSettings.AuthType)
{
case AuthType.Ptc:
@@ -266,7 +267,7 @@ public static async Task Relogin()
///
///
/// true if login worked
- public static async Task DoPtcLogin(string username, string password)
+ public static async Task DoPtcLogin(string username, string password)
{
_clientSettings = new Settings
{
@@ -303,7 +304,7 @@ public static async Task DoGoogleLogin(string email, string password)
AuthType = AuthType.Google
};
- _client = new Client(_clientSettings, new ApiFailure(), DeviceInfos.Instance);
+ _client = new Client(_clientSettings, new ApiFailure(), DeviceInfos.Instance);
// Get Google token
var authToken = await _client.Login.DoLogin();
// Update current token even if it's null
@@ -333,6 +334,29 @@ public static void DoLogout()
NearbyPokestops.Clear();
}
+ public static async Task DoRelogin()
+ {
+ Debug.WriteLine("[Relogin] Started.");
+ DoLogout();
+
+ var token = _client.AuthToken;
+
+ await
+ (_clientSettings.AuthType == AuthType.Google
+ ? DoGoogleLogin(_clientSettings.GoogleUsername, _clientSettings.GooglePassword)
+ : DoPtcLogin(_clientSettings.PtcUsername, _clientSettings.PtcPassword));
+
+ if (token != _client.AuthToken)
+ Debug.WriteLine("[Relogin] Token successfuly changed.");
+
+ Debug.WriteLine("[Relogin] Reloading gps and playerdata.");
+ await GameView.StartGpsDataService();
+ await GameView.UpdatePlayerData(true);
+ Debug.WriteLine("[Relogin] Restarting MapUpdate timer.");
+ _lastUpdate = DateTime.Now;
+ await ToggleUpdateTimer();
+ }
+
#endregion
#region Data Updating
@@ -340,6 +364,7 @@ public static void DoLogout()
private static Geolocator _geolocator;
public static Geoposition Geoposition { get; private set; }
+ public static GameMapPageViewModel GameView { get; set; }
private static DispatcherTimer _mapUpdateTimer;
@@ -375,7 +400,7 @@ public static async Task InitializeDataUpdate()
GameSetting =
await
DataCache.GetAsync(nameof(GameSetting), async () => (await _client.Download.GetSettings()).Settings,
- DateTime.Now.AddMonths(1));
+ DateTime.Now.AddMonths(1));
// Update geolocator settings based on server
_geolocator.MovementThreshold = GameSetting.MapSettings.GetMapObjectsMinDistanceMeters;
_mapUpdateTimer = new DispatcherTimer
@@ -388,9 +413,17 @@ public static async Task InitializeDataUpdate()
if ((DateTime.Now - _lastUpdate).Seconds <= GameSetting.MapSettings.GetMapObjectsMinRefreshSeconds)
return;
Logger.Write("Updating map");
- await UpdateMapObjects();
+
+ try
+ {
+ await UpdateMapObjects();
+ }
+ catch (Exception ex)
+ {
+ await ExceptionHandler.HandleException(ex);
+ }
};
- // Update before starting timer
+ // Update before starting timer
Busy.SetBusy(true, Resources.CodeResources.GetString("GettingUserDataText"));
await UpdateMapObjects();
await UpdateInventory();
@@ -407,7 +440,7 @@ public static async Task InitializeDataUpdate()
/// Toggles the update timer based on the isEnabled value
///
///
- public static async void ToggleUpdateTimer(bool isEnabled = true)
+ public static async Task ToggleUpdateTimer(bool isEnabled = true)
{
if (isEnabled)
{
@@ -429,7 +462,7 @@ public static async void ToggleUpdateTimer(bool isEnabled = true)
///
///
private static async Task UpdateMapObjects()
- {
+ {
// Get all map objects from server
var mapObjects = await GetMapObjects(Geoposition);
_lastUpdate = DateTime.Now;
@@ -443,7 +476,7 @@ private static async Task UpdateMapObjects()
// update nearby pokemons
var newNearByPokemons = mapObjects.Item1.MapCells.SelectMany(x => x.NearbyPokemons).ToArray();
Logger.Write($"Found {newNearByPokemons.Length} nearby pokemons");
- // for this collection the ordering is important, so we follow a slightly different update mechanism
+ // for this collection the ordering is important, so we follow a slightly different update mechanism
NearbyPokemons.UpdateByIndexWith(newNearByPokemons, x => new NearbyPokemonWrapper(x));
// update poke stops on map (gyms are ignored for now)
@@ -527,14 +560,14 @@ public static async Task UpdatePlayerStats(bool checkFor
// Update candies
CandyInventory.AddRange(from item in InventoryDelta.InventoryItems
- where item.InventoryItemData?.Candy != null
- where item.InventoryItemData?.Candy.FamilyId != PokemonFamilyId.FamilyUnset
- group item by item.InventoryItemData?.Candy.FamilyId into family
- select new Candy
- {
- FamilyId = family.FirstOrDefault().InventoryItemData.Candy.FamilyId,
- Candy_ = family.FirstOrDefault().InventoryItemData.Candy.Candy_
- },true);
+ where item.InventoryItemData?.Candy != null
+ where item.InventoryItemData?.Candy.FamilyId != PokemonFamilyId.FamilyUnset
+ group item by item.InventoryItemData?.Candy.FamilyId into family
+ select new Candy
+ {
+ FamilyId = family.FirstOrDefault().InventoryItemData.Candy.FamilyId,
+ Candy_ = family.FirstOrDefault().InventoryItemData.Candy.Candy_
+ }, true);
return null;
}
@@ -618,7 +651,7 @@ public static async Task UpdateInventory()
.GroupBy(item => item.InventoryItemData.Item)
.Select(item => item.First().InventoryItemData.Item), true);
- // Update incbuators
+ // Update incbuators
FreeIncubatorsInventory.AddRange(fullInventory.Where(item => item.InventoryItemData.EggIncubators != null)
.SelectMany(item => item.InventoryItemData.EggIncubators.EggIncubator)
.Where(item => item != null && item.PokemonId == 0), true);
@@ -632,13 +665,13 @@ public static async Task UpdateInventory()
EggsInventory.AddRange(fullInventory.Select(item => item.InventoryItemData.PokemonData)
.Where(item => item != null && item.IsEgg), true);
- // Update Pokedex
+ // Update Pokedex
PokedexInventory.AddRange(fullInventory.Where(item => item.InventoryItemData.PokedexEntry != null)
.Select(item => item.InventoryItemData.PokedexEntry), true);
// Update Player stats
PlayerStats =
- fullInventory.First(item => item.InventoryItemData.PlayerStats != null).InventoryItemData.PlayerStats;
+ fullInventory.First(item => item.InventoryItemData.PlayerStats != null).InventoryItemData.PlayerStats;
}
@@ -646,7 +679,7 @@ public static async Task UpdateInventory()
#region Pokemon Handling
- #region Pokedex
+ #region Pokedex
///
/// Gets extra data for the current pokemon
@@ -687,7 +720,7 @@ public static async Task CatchPokemon(ulong encounterId, s
var random = new Random();
return
await
- _client.Encounter.CatchPokemon(encounterId, spawnpointId, captureItem, random.NextDouble()*1.95D,
+ _client.Encounter.CatchPokemon(encounterId, spawnpointId, captureItem, random.NextDouble() * 1.95D,
random.NextDouble(), 1, hitPokemon);
}
@@ -709,7 +742,7 @@ public static async Task UseCaptureItem(ulong encounterI
#region Power Up & Evolving & Transfer
///
- ///
+ ///
///
///
///
@@ -719,7 +752,7 @@ public static async Task PowerUpPokemon(PokemonData poke
}
///
- ///
+ ///
///
///
///
diff --git a/PokemonGo-UWP/Utils/Helpers/ExceptionHandler.cs b/PokemonGo-UWP/Utils/Helpers/ExceptionHandler.cs
index 411028e9e..14ecdb820 100644
--- a/PokemonGo-UWP/Utils/Helpers/ExceptionHandler.cs
+++ b/PokemonGo-UWP/Utils/Helpers/ExceptionHandler.cs
@@ -4,14 +4,26 @@
using Template10.Common;
using Universal_Authenticator_v2.Views;
using System;
+using System.Diagnostics;
namespace PokemonGo_UWP.Utils
{
+ internal class ApiHandledException : Exception
+ {
+ public ApiHandledException(string reloginCompleted) : base(reloginCompleted)
+ {
+ }
+ }
public static class ExceptionHandler
{
public static async Task HandleException(Exception e = null)
{
- if (e.GetType().Namespace.Equals("PokemonGo.RocketAPI.Exceptions"))
+ if (e != null && (e.GetType().FullName.Contains("ApiHandledException") || e.Message == "Relogin completed."))
+ {
+ Debug.WriteLine("[Relogin] ApiHandledException from API handled.");
+ Debug.WriteLine("[Relogin] Successfuly ended.");
+ }
+ else if (e != null && e.GetType().Namespace.Equals("PokemonGo.RocketAPI.Exceptions"))
{
await
new MessageDialog(Resources.CodeResources.GetString("LoginExpired")).ShowAsyncQueue();
diff --git a/PokemonGo-UWP/ViewModels/CapturePokemonPageViewModel.cs b/PokemonGo-UWP/ViewModels/CapturePokemonPageViewModel.cs
index 41ab8c2d8..381fb5682 100644
--- a/PokemonGo-UWP/ViewModels/CapturePokemonPageViewModel.cs
+++ b/PokemonGo-UWP/ViewModels/CapturePokemonPageViewModel.cs
@@ -190,10 +190,10 @@ public CaptureAward CurrentCaptureAward
/// Going back to map page
///
public DelegateCommand EscapeEncounterCommand => _escapeEncounterCommand ?? (
- _escapeEncounterCommand = new DelegateCommand(() =>
+ _escapeEncounterCommand = new DelegateCommand(async () =>
{
// Re-enable update timer
- GameClient.ToggleUpdateTimer();
+ await GameClient.ToggleUpdateTimer();
NavigationService.GoBack();
}, () => true));
@@ -314,7 +314,7 @@ await GameClient.CatchPokemon(CurrentPokemon.EncounterId, CurrentPokemon.Spawnpo
GameClient.CatchablePokemons.Remove(CurrentPokemon);
GameClient.NearbyPokemons.Remove(nearbyPokemon);
// We just go back because there's nothing else to do
- GameClient.ToggleUpdateTimer();
+ await GameClient.ToggleUpdateTimer();
break;
case CatchPokemonResponse.Types.CatchStatus.CatchMissed:
Logger.Write($"We missed {CurrentPokemon.PokemonId}");
diff --git a/PokemonGo-UWP/ViewModels/GameMapPageViewModel.cs b/PokemonGo-UWP/ViewModels/GameMapPageViewModel.cs
index 72b8a4e54..e3513ed76 100644
--- a/PokemonGo-UWP/ViewModels/GameMapPageViewModel.cs
+++ b/PokemonGo-UWP/ViewModels/GameMapPageViewModel.cs
@@ -22,7 +22,7 @@ namespace PokemonGo_UWP.ViewModels
{
public class GameMapPageViewModel : ViewModelBase
{
- #region Lifecycle Handlers
+ #region Lifecycle Handlers
///
///
@@ -36,14 +36,14 @@ public override async Task OnNavigatedToAsync(object parameter, NavigationMode m
// Prevent from going back to other pages
NavigationService.ClearHistory();
if (parameter == null || mode == NavigationMode.Back) return;
- var gameMapNavigationMode = (GameMapNavigationModes) parameter;
+ var gameMapNavigationMode = (GameMapNavigationModes)parameter;
// We just resumed from suspension so we restart update service and we get data from suspension state
if (suspensionState.Any())
{
- // Recovering the state
- PlayerProfile = (PlayerData) suspensionState[nameof(PlayerProfile)];
- PlayerStats = (PlayerStats) suspensionState[nameof(PlayerStats)];
+ // Recovering the state
+ PlayerProfile = (PlayerData)suspensionState[nameof(PlayerProfile)];
+ PlayerStats = (PlayerStats)suspensionState[nameof(PlayerStats)];
// Restarting update service
await StartGpsDataService();
return;
@@ -56,19 +56,20 @@ public override async Task OnNavigatedToAsync(object parameter, NavigationMode m
// App just started, so we get GPS access and eventually initialize the client
await StartGpsDataService();
await UpdatePlayerData(true);
- GameClient.ToggleUpdateTimer();
+ await GameClient.ToggleUpdateTimer();
+ GameClient.GameView = this;
break;
case GameMapNavigationModes.SettingsUpdate:
- // We navigated back from Settings page after changing the Map provider, but this is managed in the page itself
+ // We navigated back from Settings page after changing the Map provider, but this is managed in the page itself
break;
case GameMapNavigationModes.PokestopUpdate:
- // We came here after the catching page so we need to restart map update timer and update player data. We also check for level up.
- GameClient.ToggleUpdateTimer();
+ // We came here after the catching page so we need to restart map update timer and update player data. We also check for level up.
+ await GameClient.ToggleUpdateTimer();
await UpdatePlayerData(true);
break;
case GameMapNavigationModes.PokemonUpdate:
- // As above
- GameClient.ToggleUpdateTimer();
+ // As above
+ await GameClient.ToggleUpdateTimer();
await UpdatePlayerData(true);
break;
default:
@@ -94,7 +95,7 @@ public override async Task OnNavigatedFromAsync(IDictionary susp
#endregion
- #region Game Management Vars
+ #region Game Management Vars
///
/// Player's profile, we use it just for the username
@@ -113,7 +114,7 @@ public override async Task OnNavigatedFromAsync(IDictionary susp
#endregion
- #region Bindable Game Vars
+ #region Bindable Game Vars
public ElementTheme CurrentTheme
{
@@ -193,7 +194,7 @@ public LevelUpRewardsResponse LevelUpResponse
/// Waits for GPS auth and, if auth is given, starts updating data
///
///
- private async Task StartGpsDataService()
+ public async Task StartGpsDataService()
{
await Dispatcher.DispatchAsync(async () =>
{
@@ -218,7 +219,7 @@ await Dispatcher.DispatchAsync(async () =>
///
///
///
- private async Task UpdatePlayerData(bool checkForLevelUp = false)
+ public async Task UpdatePlayerData(bool checkForLevelUp = false)
{
await GameClient.UpdateProfile();
LevelUpResponse = await GameClient.UpdatePlayerStats(checkForLevelUp);
diff --git a/PokemonGo-UWP/ViewModels/SearchPokeStopPageViewModel.cs b/PokemonGo-UWP/ViewModels/SearchPokeStopPageViewModel.cs
index b7db430f5..464dfb1dc 100644
--- a/PokemonGo-UWP/ViewModels/SearchPokeStopPageViewModel.cs
+++ b/PokemonGo-UWP/ViewModels/SearchPokeStopPageViewModel.cs
@@ -158,10 +158,10 @@ public FortSearchResponse CurrentSearchResponse
/// Going back to map page
///
public DelegateCommand AbandonPokestop => _abandonPokestop ?? (
- _abandonPokestop = new DelegateCommand(() =>
+ _abandonPokestop = new DelegateCommand(async () =>
{
// Re-enable update timer
- GameClient.ToggleUpdateTimer();
+ await GameClient.ToggleUpdateTimer();
NavigationService.GoBack();
}, () => true)
);
diff --git a/PokemonGo-UWP/Views/PlayerProfilePage.xaml.cs b/PokemonGo-UWP/Views/PlayerProfilePage.xaml.cs
index a51f0fe58..b4a3288c3 100644
--- a/PokemonGo-UWP/Views/PlayerProfilePage.xaml.cs
+++ b/PokemonGo-UWP/Views/PlayerProfilePage.xaml.cs
@@ -9,8 +9,9 @@ public PlayerProfilePage()
InitializeComponent();
}
- private void GridView_ItemClick(object sender, ItemClickEventArgs e) {
- ViewModel.NavigateToDetailPage(sender, e);
+ private void GridView_ItemClick(object sender, ItemClickEventArgs e)
+ {
+ //ViewModel.NavigateToDetailPage(sender, e);
}
}
}
\ No newline at end of file