stash changes

This commit is contained in:
Tian Liao 2024-10-17 15:59:22 +08:00
commit 7258237c8a
9 changed files with 183 additions and 131 deletions

View file

@ -38,9 +38,8 @@ namespace
StringReference CategoriesPropertyName(L"Categories"); StringReference CategoriesPropertyName(L"Categories");
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility"); StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
//struct SnapshotHelper // struct SnapshotHelper
//{ //{
// static constexpr int SnapshotVersion = 0;
// static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const ApplicationSnapshot& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const ApplicationSnapshot& value)
// { // {
@ -121,8 +120,9 @@ namespace
// static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CalculationManager::HISTORYITEM& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CalculationManager::HISTORYITEM& value)
// { // {
// auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
// jsonObject->SetNamedValue(L"Expression", Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.expression.c_str()))); // jsonObject->SetNamedValue(L"Expression", Windows::Data::Json::JsonValue::CreateStringValue(ref new
// jsonObject->SetNamedValue(L"Result", Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.result.c_str()))); // Platform::String(value.historyItemVector.expression.c_str()))); jsonObject->SetNamedValue(L"Result",
// Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.result.c_str())));
// auto tokensJsonArray = ref new Windows::Data::Json::JsonArray(); // auto tokensJsonArray = ref new Windows::Data::Json::JsonArray();
// for (const auto& token : *value.historyItemVector.spTokens) // for (const auto& token : *value.historyItemVector.spTokens)
@ -512,6 +512,17 @@ void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup ^>
} }
} }
ApplicationSnapshot ^ ApplicationViewModel::Snapshot::get()
{
auto snapshot = ref new ApplicationSnapshot();
snapshot->Mode = static_cast<int>(Mode);
if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard)
{
snapshot->StandardCalculator = m_CalculatorViewModel->Snapshot;
}
return snapshot;
}
void ApplicationViewModel::Initialize(ViewMode mode) void ApplicationViewModel::Initialize(ViewMode mode)
{ {
if (!NavCategoryStates::IsValidViewMode(mode) || !NavCategoryStates::IsViewModeEnabled(mode)) if (!NavCategoryStates::IsValidViewMode(mode) || !NavCategoryStates::IsViewModeEnabled(mode))
@ -545,6 +556,12 @@ void ApplicationViewModel::Initialize(ViewMode mode)
} }
} }
void ApplicationViewModel::Initialize(ApplicationSnapshot ^ snapshot)
{
// TODO: restore
Initialize(static_cast<ViewMode>(snapshot->Mode));
}
bool ApplicationViewModel::TryRecoverFromNavigationModeFailure() bool ApplicationViewModel::TryRecoverFromNavigationModeFailure()
{ {
// Here we are simply trying to recover from being unable to navigate to a mode. // Here we are simply trying to recover from being unable to navigate to a mode.
@ -712,47 +729,47 @@ void ApplicationViewModel::SetDisplayNormalAlwaysOnTopOption()
m_mode == ViewMode::Standard && ApplicationView::GetForCurrentView()->IsViewModeSupported(ApplicationViewMode::CompactOverlay) && !IsAlwaysOnTop; m_mode == ViewMode::Standard && ApplicationView::GetForCurrentView()->IsViewModeSupported(ApplicationViewMode::CompactOverlay) && !IsAlwaysOnTop;
} }
//Windows::Data::Json::JsonObject ^ ApplicationViewModel::SaveApplicationSnapshot() // Windows::Data::Json::JsonObject ^ ApplicationViewModel::SaveApplicationSnapshot()
//{ //{
// ApplicationSnapshot applicationSnapshot; // ApplicationSnapshot applicationSnapshot;
// applicationSnapshot.SnapshotVersion = SnapshotHelper::SnapshotVersion; // applicationSnapshot.SnapshotVersion = SnapshotHelper::SnapshotVersion;
// applicationSnapshot.Mode = static_cast<int>(Mode); // applicationSnapshot.Mode = static_cast<int>(Mode);
// if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard) // if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard)
// { // {
// // Standard calculator is the only supported mode so far. // // Standard calculator is the only supported mode so far.
// applicationSnapshot.StandardCalc = m_CalculatorViewModel->GetStandardCalculatorSnapshot(); // applicationSnapshot.StandardCalc = m_CalculatorViewModel->GetStandardCalculatorSnapshot();
// } // }
// return SnapshotHelper::SaveSnapshotToJson(applicationSnapshot); // return SnapshotHelper::SaveSnapshotToJson(applicationSnapshot);
//} // }
// //
//bool ApplicationViewModel::TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject) // bool ApplicationViewModel::TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject)
//{ //{
// std::optional<ApplicationSnapshot> applicationSnapshot; // std::optional<ApplicationSnapshot> applicationSnapshot;
// try // try
// { // {
// SnapshotHelper::RestoreJsonToSnapshot(jsonObject, applicationSnapshot); // SnapshotHelper::RestoreJsonToSnapshot(jsonObject, applicationSnapshot);
// } // }
// catch (Platform::COMException ^ e) // catch (Platform::COMException ^ e)
// { // {
// if (SnapshotHelper::IsJsonParsingException(e)) // if (SnapshotHelper::IsJsonParsingException(e))
// { // {
// return false; // return false;
// } // }
// throw; // throw;
// } // }
// //
// if (applicationSnapshot.has_value()) // if (applicationSnapshot.has_value())
// { // {
// Mode = static_cast<ViewMode>(applicationSnapshot->Mode); // Mode = static_cast<ViewMode>(applicationSnapshot->Mode);
// if (applicationSnapshot->StandardCalc.has_value()) // if (applicationSnapshot->StandardCalc.has_value())
// { // {
// if (m_CalculatorViewModel == nullptr) // if (m_CalculatorViewModel == nullptr)
// { // {
// m_CalculatorViewModel = ref new StandardCalculatorViewModel(); // m_CalculatorViewModel = ref new StandardCalculatorViewModel();
// } // }
// m_CalculatorViewModel->SetStandardCalculatorSnapshot(applicationSnapshot->StandardCalc.value()); // m_CalculatorViewModel->SetStandardCalculatorSnapshot(applicationSnapshot->StandardCalc.value());
// } // }
// return true; // return true;
// } // }
// return false; // return false;
//} // }

View file

@ -3,6 +3,7 @@
#pragma once #pragma once
#include "Snapshots.h"
#include "StandardCalculatorViewModel.h" #include "StandardCalculatorViewModel.h"
#include "DateCalculatorViewModel.h" #include "DateCalculatorViewModel.h"
#include "GraphingCalculator/GraphingCalculatorViewModel.h" #include "GraphingCalculator/GraphingCalculatorViewModel.h"
@ -12,19 +13,14 @@ namespace CalculatorApp
{ {
namespace ViewModel namespace ViewModel
{ {
struct ApplicationSnapshot
{
int SnapshotVersion;
int Mode;
//std::optional<StandardCalculatorSnapshot> StandardCalc;
};
[Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged [Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{ {
public: public:
ApplicationViewModel(); ApplicationViewModel();
[Windows::Foundation::Metadata::DefaultOverload]
void Initialize(CalculatorApp::ViewModel::Common::ViewMode mode); // Use for first init, use deserialize for rehydration void Initialize(CalculatorApp::ViewModel::Common::ViewMode mode); // Use for first init, use deserialize for rehydration
void Initialize(ApplicationSnapshot^ snapshot);
OBSERVABLE_OBJECT(); OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel); OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel);
@ -77,6 +73,11 @@ namespace CalculatorApp
} }
} }
property ApplicationSnapshot ^ Snapshot
{
ApplicationSnapshot ^ get();
}
static property Platform::String ^ LaunchedLocalSettings static property Platform::String ^ LaunchedLocalSettings
{ {
Platform::String ^ get() Platform::String ^ get()
@ -103,7 +104,6 @@ namespace CalculatorApp
void ToggleAlwaysOnTop(float width, float height); void ToggleAlwaysOnTop(float width, float height);
//Windows::Data::Json::JsonObject ^ SaveApplicationSnapshot();
//bool TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject); //bool TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject);
private: private:

View file

@ -6,6 +6,7 @@
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "CalcManager/ExpressionCommand.h"
#include "Snapshots.h" #include "Snapshots.h"
namespace namespace
@ -152,4 +153,41 @@ namespace CalculatorApp::ViewModel
{ {
return {}; // TODO return {}; // TODO
} }
std::vector<std::shared_ptr<IExpressionCommand>> ToUnderlying(Windows::Foundation::Collections::IVector<ICalcManagerIExprCommand ^> ^ commands)
{
std::vector<std::shared_ptr<IExpressionCommand>> result;
for (ICalcManagerIExprCommand ^ cmdEntry : commands)
{
if (auto unary = dynamic_cast<UnaryCommand ^>(cmdEntry); unary != nullptr)
{
if (unary->Commands.size() == 1)
{
result.push_back(std::make_shared<CUnaryCommand>(unary->Commands[0]));
}
else if (unary->Commands.size() == 2)
{
result.push_back(std::make_shared<CUnaryCommand>(unary->Commands[0], unary->Commands[1]));
}
else
{
throw std::logic_error{ "ill-formed command." };
}
}
else if (auto binary = dynamic_cast<BinaryCommand ^>(cmdEntry); binary != nullptr)
{
result.push_back(std::make_shared<CBinaryCommand>(binary->Command));
}
else if (auto paren = dynamic_cast<Parentheses ^>(cmdEntry); paren != nullptr)
{
result.push_back(std::make_shared<CParentheses>(paren->Command));
}
else if (auto operand = dynamic_cast<OperandCommand ^>(cmdEntry); operand != nullptr)
{
auto subcmds = std::make_shared<std::vector<int>>(operand->Commands);
result.push_back(std::make_shared<COpndCommand>(std::move(subcmds), operand->IsNegative, operand->IsDecimalPresent, operand->IsSciFmt));
}
}
return result;
}
} // namespace CalculatorApp::ViewModel } // namespace CalculatorApp::ViewModel

View file

@ -75,7 +75,15 @@ public
property Windows::Foundation::Collections::IVector<ICalcManagerIExprCommand ^> ^ DisplayCommands; // mandatory property Windows::Foundation::Collections::IVector<ICalcManagerIExprCommand ^> ^ DisplayCommands; // mandatory
}; };
public
ref struct ApplicationSnapshot sealed
{
property int Mode;
property StandardCalculatorSnapshot ^ StandardCalculator; // optional
};
ICalcManagerIExprCommand ^ CreateExprCommand(const IExpressionCommand* exprCmd); ICalcManagerIExprCommand ^ CreateExprCommand(const IExpressionCommand* exprCmd);
std::vector<std::shared_ptr<IExpressionCommand>> ToUnderlying(Windows::Foundation::Collections::IVector<ICalcManagerIExprCommand ^> ^ commands);
std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>> ToUnderlying(Windows::Foundation::Collections::IVector<CalcManagerHistoryItem ^> ^ items); std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>> ToUnderlying(Windows::Foundation::Collections::IVector<CalcManagerHistoryItem ^> ^ items);
} // namespace CalculatorApp::ViewModel } // namespace CalculatorApp::ViewModel

View file

@ -194,11 +194,11 @@ StandardCalculatorViewModel::StandardCalculatorViewModel(StandardCalculatorSnaps
std::vector<int> commands; std::vector<int> commands;
if (snapshot->ExpressionDisplay != nullptr && snapshot->ExpressionDisplay->Tokens->GetAt(snapshot->ExpressionDisplay->Tokens->Size)) if (snapshot->ExpressionDisplay != nullptr && snapshot->ExpressionDisplay->Tokens->GetAt(snapshot->ExpressionDisplay->Tokens->Size))
{ {
// commands = GetCommandsFromExpressionCommands(Snapshot->ExpressionDisplay->Commands); commands = GetCommandsFromExpressionCommands(ToUnderlying(snapshot->ExpressionDisplay->Commands));
} }
if (commands.empty() && snapshot->DisplayCommands->Size > 0) if (commands.empty() && snapshot->DisplayCommands->Size > 0)
{ {
// commands = GetCommandsFromExpressionCommands(snapshot->DisplayCommands); commands = GetCommandsFromExpressionCommands(ToUnderlying(snapshot->DisplayCommands));
} }
for (auto cmd : commands) for (auto cmd : commands)
{ {
@ -206,9 +206,18 @@ StandardCalculatorViewModel::StandardCalculatorViewModel(StandardCalculatorSnaps
} }
if (snapshot->ExpressionDisplay != nullptr) if (snapshot->ExpressionDisplay != nullptr)
{ {
// SetExpressionDisplay(); using RawTokenCollection = std::vector<std::pair<std::wstring, int>>;
RawTokenCollection rawTokens;
for (CalcManagerHistoryToken ^ token : snapshot->ExpressionDisplay->Tokens)
{
rawTokens.push_back(std::pair{ token->OpCodeName->Data(), token->CommandIndex });
}
snapshot->ExpressionDisplay->Tokens;
SetExpressionDisplay(
std::make_shared<RawTokenCollection>(rawTokens),
std::make_shared<std::vector<std::shared_ptr<IExpressionCommand>>>(ToUnderlying(snapshot->ExpressionDisplay->Commands)));
} }
// SetPrimaryDisplay(); SetPrimaryDisplay(snapshot->PrimaryDisplay->DisplayValue, snapshot->PrimaryDisplay->IsError);
} }
} }

View file

@ -394,6 +394,14 @@
<ItemDefinitionGroup Condition="!Exists('..\CalcViewModel\DataLoaders\DataLoaderConstants.h')"> <ItemDefinitionGroup Condition="!Exists('..\CalcViewModel\DataLoaders\DataLoaderConstants.h')">
<ClCompile> <ClCompile>
<AdditionalOptions>/DUSE_MOCK_DATA %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/DUSE_MOCK_DATA %(AdditionalOptions)</AdditionalOptions>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|x64'">stdcpp17</LanguageStandard>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<Choose> <Choose>

View file

@ -81,8 +81,7 @@ namespace CalculatorApp
OnAppLaunch(args, OnAppLaunch(args,
new SnapshotLaunchArguments new SnapshotLaunchArguments
{ {
ActivityId = protoArgs.Uri.GetActivityId(), Snapshot = null // TODO:
LaunchUri = protoArgs.Uri
}, },
false); false);
} }

View file

@ -1,14 +1,13 @@
using System; using System;
using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.UserActivities; using Windows.ApplicationModel.UserActivities;
using CalculatorApp.ViewModel;
namespace CalculatorApp namespace CalculatorApp
{ {
internal class SnapshotLaunchArguments internal class SnapshotLaunchArguments
{ {
public string ActivityId { get; set; } public ApplicationSnapshot Snapshot;
public Uri LaunchUri { get; set; }
} }
internal static class LaunchExtensions internal static class LaunchExtensions
@ -18,31 +17,6 @@ namespace CalculatorApp
protoArgs.Uri != null && protoArgs.Uri != null &&
protoArgs.Uri.Segments != null && protoArgs.Uri.Segments != null &&
protoArgs.Uri.Segments.Length == 2 && protoArgs.Uri.Segments.Length == 2 &&
protoArgs.Uri.Segments[0] == "snapshots/"; protoArgs.Uri.Segments[0] == "snapshot/";
/// <summary>
/// GetActivityId() requires the parameter `launchUri` to be a well-formed
/// snapshot URI.
/// </summary>
/// <param name="launchUri">the Uri to launch with a snapshot context.</param>
/// <returns>Activity ID</returns>
public static string GetActivityId(this Uri launchUri)
{
return launchUri.Segments[1].Trim();
}
public static bool VerifyIncomingActivity(this SnapshotLaunchArguments launchArgs, UserActivity activity)
{
if (activity.State != UserActivityState.Published ||
string.IsNullOrEmpty(activity.ActivityId) ||
activity.ActivationUri == null ||
activity.ActivationUri.Segments == null ||
activity.ActivationUri.Segments.Length != 2 ||
activity.ActivationUri.Segments[0] != "snapshots/")
{
return false;
}
return activity.ActivityId == GetActivityId(launchArgs.LaunchUri);
}
} }
} }

View file

@ -69,8 +69,7 @@ namespace CalculatorApp
} }
var channel = UserActivityChannel.GetDefault(); var channel = UserActivityChannel.GetDefault();
var activity = await channel.GetOrCreateUserActivityAsync($"{Guid.NewGuid()}"); var activity = await channel.GetOrCreateUserActivityAsync($"{Guid.NewGuid()}");
activity.ActivationUri = new Uri($"ms-calculator:snapshots/{activity.ActivityId}"); activity.ActivationUri = new Uri($"ms-calculator:snapshot/TODO");
activity.ContentInfo = UserActivityContentInfo.FromJson(Model.SaveApplicationSnapshot().Stringify());
activity.IsRoamable = false; activity.IsRoamable = false;
var resProvider = AppResourceProvider.GetInstance(); var resProvider = AppResourceProvider.GetInstance();
activity.VisualElements.DisplayText = activity.VisualElements.DisplayText =
@ -165,22 +164,22 @@ namespace CalculatorApp
} }
else if (e.Parameter is SnapshotLaunchArguments snapshotArgs) else if (e.Parameter is SnapshotLaunchArguments snapshotArgs)
{ {
_ = Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => //_ = Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{ //{
var channel = UserActivityChannel.GetDefault(); // var channel = UserActivityChannel.GetDefault();
var activity = await channel.GetOrCreateUserActivityAsync(snapshotArgs.ActivityId); // var activity = await channel.GetOrCreateUserActivityAsync(snapshotArgs.ActivityId);
if (TryRestoreFromActivity(snapshotArgs, activity, out var errorMessage)) // if (TryRestoreFromActivity(snapshotArgs, activity, out var errorMessage))
{ // {
TraceLogger.GetInstance().LogRecallRestore(Model.Mode); // TraceLogger.GetInstance().LogRecallRestore(Model.Mode);
SelectNavigationItemByModel(); // SelectNavigationItemByModel();
} // }
else // else
{ // {
TraceLogger.GetInstance().LogRecallError(Model.Mode, errorMessage); // TraceLogger.GetInstance().LogRecallError(Model.Mode, errorMessage);
} // }
}); //});
Model.Initialize(initialMode); Model.Initialize(snapshotArgs.Snapshot);
} }
else else
{ {
@ -188,37 +187,37 @@ namespace CalculatorApp
} }
} }
private bool TryRestoreFromActivity(SnapshotLaunchArguments snapshotArgs, UserActivity activity, out string errorMessage) //private bool TryRestoreFromActivity(SnapshotLaunchArguments snapshotArgs, UserActivity activity, out string errorMessage)
{ //{
if (!snapshotArgs.VerifyIncomingActivity(activity)) // if (!snapshotArgs.VerifyIncomingActivity(activity))
{ // {
errorMessage = "IncomingActivityFailed"; // errorMessage = "IncomingActivityFailed";
return false; // return false;
} // }
// Work around for bug https://microsoft.visualstudio.com/DefaultCollection/OS/_workitems/edit/48931227 // // Work around for bug https://microsoft.visualstudio.com/DefaultCollection/OS/_workitems/edit/48931227
// where ContentInfo can't be directly accessed. // // where ContentInfo can't be directly accessed.
if (!JsonObject.TryParse(activity.ToJson(), out var activityJson)) // if (!JsonObject.TryParse(activity.ToJson(), out var activityJson))
{ // {
errorMessage = "ParseJsonError"; // errorMessage = "ParseJsonError";
return false; // return false;
} // }
if (!activityJson.ContainsKey("contentInfo")) // if (!activityJson.ContainsKey("contentInfo"))
{ // {
errorMessage = "ContentInfoNotExist"; // errorMessage = "ContentInfoNotExist";
return false; // return false;
} // }
if (!Model.TryRestoreFromSnapshot(activityJson.GetNamedObject("contentInfo"))) // if (!Model.TryRestoreFromSnapshot(activityJson.GetNamedObject("contentInfo")))
{ // {
errorMessage = "RestoreFromSnapshotFailed"; // errorMessage = "RestoreFromSnapshotFailed";
return false; // return false;
} // }
errorMessage = string.Empty; // errorMessage = string.Empty;
return true; // return true;
} //}
private void InitializeNavViewCategoriesSource() private void InitializeNavViewCategoriesSource()
{ {