diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index d3bdaa19..1d4e6e12 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -38,9 +38,8 @@ namespace StringReference CategoriesPropertyName(L"Categories"); StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility"); - //struct SnapshotHelper + // struct SnapshotHelper //{ - // static constexpr int SnapshotVersion = 0; // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const ApplicationSnapshot& value) // { @@ -121,8 +120,9 @@ namespace // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CalculationManager::HISTORYITEM& value) // { // 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"Result", Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.result.c_str()))); + // jsonObject->SetNamedValue(L"Expression", Windows::Data::Json::JsonValue::CreateStringValue(ref new + // 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(); // for (const auto& token : *value.historyItemVector.spTokens) @@ -512,6 +512,17 @@ void ApplicationViewModel::Categories::set(IObservableVector } } +ApplicationSnapshot ^ ApplicationViewModel::Snapshot::get() +{ + auto snapshot = ref new ApplicationSnapshot(); + snapshot->Mode = static_cast(Mode); + if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard) + { + snapshot->StandardCalculator = m_CalculatorViewModel->Snapshot; + } + return snapshot; +} + void ApplicationViewModel::Initialize(ViewMode 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(snapshot->Mode)); +} + bool ApplicationViewModel::TryRecoverFromNavigationModeFailure() { // 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; } -//Windows::Data::Json::JsonObject ^ ApplicationViewModel::SaveApplicationSnapshot() +// Windows::Data::Json::JsonObject ^ ApplicationViewModel::SaveApplicationSnapshot() //{ -// ApplicationSnapshot applicationSnapshot; -// applicationSnapshot.SnapshotVersion = SnapshotHelper::SnapshotVersion; -// applicationSnapshot.Mode = static_cast(Mode); -// if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard) -// { -// // Standard calculator is the only supported mode so far. -// applicationSnapshot.StandardCalc = m_CalculatorViewModel->GetStandardCalculatorSnapshot(); -// } -// return SnapshotHelper::SaveSnapshotToJson(applicationSnapshot); -//} +// ApplicationSnapshot applicationSnapshot; +// applicationSnapshot.SnapshotVersion = SnapshotHelper::SnapshotVersion; +// applicationSnapshot.Mode = static_cast(Mode); +// if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard) +// { +// // Standard calculator is the only supported mode so far. +// applicationSnapshot.StandardCalc = m_CalculatorViewModel->GetStandardCalculatorSnapshot(); +// } +// return SnapshotHelper::SaveSnapshotToJson(applicationSnapshot); +// } // -//bool ApplicationViewModel::TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject) +// bool ApplicationViewModel::TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject) //{ -// std::optional applicationSnapshot; -// try -// { -// SnapshotHelper::RestoreJsonToSnapshot(jsonObject, applicationSnapshot); -// } -// catch (Platform::COMException ^ e) -// { -// if (SnapshotHelper::IsJsonParsingException(e)) -// { -// return false; -// } -// throw; -// } +// std::optional applicationSnapshot; +// try +// { +// SnapshotHelper::RestoreJsonToSnapshot(jsonObject, applicationSnapshot); +// } +// catch (Platform::COMException ^ e) +// { +// if (SnapshotHelper::IsJsonParsingException(e)) +// { +// return false; +// } +// throw; +// } // -// if (applicationSnapshot.has_value()) -// { -// Mode = static_cast(applicationSnapshot->Mode); -// if (applicationSnapshot->StandardCalc.has_value()) -// { -// if (m_CalculatorViewModel == nullptr) -// { -// m_CalculatorViewModel = ref new StandardCalculatorViewModel(); -// } -// m_CalculatorViewModel->SetStandardCalculatorSnapshot(applicationSnapshot->StandardCalc.value()); -// } -// return true; -// } -// return false; -//} +// if (applicationSnapshot.has_value()) +// { +// Mode = static_cast(applicationSnapshot->Mode); +// if (applicationSnapshot->StandardCalc.has_value()) +// { +// if (m_CalculatorViewModel == nullptr) +// { +// m_CalculatorViewModel = ref new StandardCalculatorViewModel(); +// } +// m_CalculatorViewModel->SetStandardCalculatorSnapshot(applicationSnapshot->StandardCalc.value()); +// } +// return true; +// } +// return false; +// } diff --git a/src/CalcViewModel/ApplicationViewModel.h b/src/CalcViewModel/ApplicationViewModel.h index 992754d5..05cd1fbd 100644 --- a/src/CalcViewModel/ApplicationViewModel.h +++ b/src/CalcViewModel/ApplicationViewModel.h @@ -3,6 +3,7 @@ #pragma once +#include "Snapshots.h" #include "StandardCalculatorViewModel.h" #include "DateCalculatorViewModel.h" #include "GraphingCalculator/GraphingCalculatorViewModel.h" @@ -12,19 +13,14 @@ namespace CalculatorApp { namespace ViewModel { - struct ApplicationSnapshot - { - int SnapshotVersion; - int Mode; - //std::optional StandardCalc; - }; - [Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { public: ApplicationViewModel(); + [Windows::Foundation::Metadata::DefaultOverload] void Initialize(CalculatorApp::ViewModel::Common::ViewMode mode); // Use for first init, use deserialize for rehydration + void Initialize(ApplicationSnapshot^ snapshot); OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel); @@ -77,6 +73,11 @@ namespace CalculatorApp } } + property ApplicationSnapshot ^ Snapshot + { + ApplicationSnapshot ^ get(); + } + static property Platform::String ^ LaunchedLocalSettings { Platform::String ^ get() @@ -103,7 +104,6 @@ namespace CalculatorApp void ToggleAlwaysOnTop(float width, float height); - //Windows::Data::Json::JsonObject ^ SaveApplicationSnapshot(); //bool TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject); private: diff --git a/src/CalcViewModel/Snapshots.cpp b/src/CalcViewModel/Snapshots.cpp index ca6dc339..a7ffccea 100644 --- a/src/CalcViewModel/Snapshots.cpp +++ b/src/CalcViewModel/Snapshots.cpp @@ -6,6 +6,7 @@ #include #include +#include "CalcManager/ExpressionCommand.h" #include "Snapshots.h" namespace @@ -152,4 +153,41 @@ namespace CalculatorApp::ViewModel { return {}; // TODO } + + std::vector> ToUnderlying(Windows::Foundation::Collections::IVector ^ commands) + { + std::vector> result; + for (ICalcManagerIExprCommand ^ cmdEntry : commands) + { + if (auto unary = dynamic_cast(cmdEntry); unary != nullptr) + { + if (unary->Commands.size() == 1) + { + result.push_back(std::make_shared(unary->Commands[0])); + } + else if (unary->Commands.size() == 2) + { + result.push_back(std::make_shared(unary->Commands[0], unary->Commands[1])); + } + else + { + throw std::logic_error{ "ill-formed command." }; + } + } + else if (auto binary = dynamic_cast(cmdEntry); binary != nullptr) + { + result.push_back(std::make_shared(binary->Command)); + } + else if (auto paren = dynamic_cast(cmdEntry); paren != nullptr) + { + result.push_back(std::make_shared(paren->Command)); + } + else if (auto operand = dynamic_cast(cmdEntry); operand != nullptr) + { + auto subcmds = std::make_shared>(operand->Commands); + result.push_back(std::make_shared(std::move(subcmds), operand->IsNegative, operand->IsDecimalPresent, operand->IsSciFmt)); + } + } + return result; + } } // namespace CalculatorApp::ViewModel diff --git a/src/CalcViewModel/Snapshots.h b/src/CalcViewModel/Snapshots.h index 507fc032..558e302f 100644 --- a/src/CalcViewModel/Snapshots.h +++ b/src/CalcViewModel/Snapshots.h @@ -75,7 +75,15 @@ public property Windows::Foundation::Collections::IVector ^ DisplayCommands; // mandatory }; +public + ref struct ApplicationSnapshot sealed + { + property int Mode; + property StandardCalculatorSnapshot ^ StandardCalculator; // optional + }; + ICalcManagerIExprCommand ^ CreateExprCommand(const IExpressionCommand* exprCmd); + std::vector> ToUnderlying(Windows::Foundation::Collections::IVector ^ commands); std::vector> ToUnderlying(Windows::Foundation::Collections::IVector ^ items); } // namespace CalculatorApp::ViewModel diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index 38889fe1..844a063c 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -194,11 +194,11 @@ StandardCalculatorViewModel::StandardCalculatorViewModel(StandardCalculatorSnaps std::vector commands; 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) { - // commands = GetCommandsFromExpressionCommands(snapshot->DisplayCommands); + commands = GetCommandsFromExpressionCommands(ToUnderlying(snapshot->DisplayCommands)); } for (auto cmd : commands) { @@ -206,9 +206,18 @@ StandardCalculatorViewModel::StandardCalculatorViewModel(StandardCalculatorSnaps } if (snapshot->ExpressionDisplay != nullptr) { - // SetExpressionDisplay(); + using RawTokenCollection = std::vector>; + 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(rawTokens), + std::make_shared>>(ToUnderlying(snapshot->ExpressionDisplay->Commands))); } - // SetPrimaryDisplay(); + SetPrimaryDisplay(snapshot->PrimaryDisplay->DisplayValue, snapshot->PrimaryDisplay->IsError); } } diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj index 2171c9cd..ed1a9fb1 100644 --- a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj @@ -394,6 +394,14 @@ /DUSE_MOCK_DATA %(AdditionalOptions) + stdcpp17 + stdcpp17 + stdcpp17 + stdcpp17 + stdcpp17 + stdcpp17 + stdcpp17 + stdcpp17 diff --git a/src/Calculator/App.xaml.cs b/src/Calculator/App.xaml.cs index 342e6851..78254322 100644 --- a/src/Calculator/App.xaml.cs +++ b/src/Calculator/App.xaml.cs @@ -81,8 +81,7 @@ namespace CalculatorApp OnAppLaunch(args, new SnapshotLaunchArguments { - ActivityId = protoArgs.Uri.GetActivityId(), - LaunchUri = protoArgs.Uri + Snapshot = null // TODO: }, false); } diff --git a/src/Calculator/Common/LaunchArguments.cs b/src/Calculator/Common/LaunchArguments.cs index 8a1be58d..0686e1aa 100644 --- a/src/Calculator/Common/LaunchArguments.cs +++ b/src/Calculator/Common/LaunchArguments.cs @@ -1,14 +1,13 @@ using System; - using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.UserActivities; +using CalculatorApp.ViewModel; namespace CalculatorApp { internal class SnapshotLaunchArguments { - public string ActivityId { get; set; } - public Uri LaunchUri { get; set; } + public ApplicationSnapshot Snapshot; } internal static class LaunchExtensions @@ -18,31 +17,6 @@ namespace CalculatorApp protoArgs.Uri != null && protoArgs.Uri.Segments != null && protoArgs.Uri.Segments.Length == 2 && - protoArgs.Uri.Segments[0] == "snapshots/"; - - /// - /// GetActivityId() requires the parameter `launchUri` to be a well-formed - /// snapshot URI. - /// - /// the Uri to launch with a snapshot context. - /// Activity ID - 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); - } + protoArgs.Uri.Segments[0] == "snapshot/"; } } diff --git a/src/Calculator/Views/MainPage.xaml.cs b/src/Calculator/Views/MainPage.xaml.cs index ff6fbe6c..0a3035fd 100644 --- a/src/Calculator/Views/MainPage.xaml.cs +++ b/src/Calculator/Views/MainPage.xaml.cs @@ -69,8 +69,7 @@ namespace CalculatorApp } var channel = UserActivityChannel.GetDefault(); var activity = await channel.GetOrCreateUserActivityAsync($"{Guid.NewGuid()}"); - activity.ActivationUri = new Uri($"ms-calculator:snapshots/{activity.ActivityId}"); - activity.ContentInfo = UserActivityContentInfo.FromJson(Model.SaveApplicationSnapshot().Stringify()); + activity.ActivationUri = new Uri($"ms-calculator:snapshot/TODO"); activity.IsRoamable = false; var resProvider = AppResourceProvider.GetInstance(); activity.VisualElements.DisplayText = @@ -165,22 +164,22 @@ namespace CalculatorApp } else if (e.Parameter is SnapshotLaunchArguments snapshotArgs) { - _ = Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => - { - var channel = UserActivityChannel.GetDefault(); - var activity = await channel.GetOrCreateUserActivityAsync(snapshotArgs.ActivityId); + //_ = Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => + //{ + // var channel = UserActivityChannel.GetDefault(); + // var activity = await channel.GetOrCreateUserActivityAsync(snapshotArgs.ActivityId); - if (TryRestoreFromActivity(snapshotArgs, activity, out var errorMessage)) - { - TraceLogger.GetInstance().LogRecallRestore(Model.Mode); - SelectNavigationItemByModel(); - } - else - { - TraceLogger.GetInstance().LogRecallError(Model.Mode, errorMessage); - } - }); - Model.Initialize(initialMode); + // if (TryRestoreFromActivity(snapshotArgs, activity, out var errorMessage)) + // { + // TraceLogger.GetInstance().LogRecallRestore(Model.Mode); + // SelectNavigationItemByModel(); + // } + // else + // { + // TraceLogger.GetInstance().LogRecallError(Model.Mode, errorMessage); + // } + //}); + Model.Initialize(snapshotArgs.Snapshot); } else { @@ -188,37 +187,37 @@ namespace CalculatorApp } } - private bool TryRestoreFromActivity(SnapshotLaunchArguments snapshotArgs, UserActivity activity, out string errorMessage) - { - if (!snapshotArgs.VerifyIncomingActivity(activity)) - { - errorMessage = "IncomingActivityFailed"; - return false; - } + //private bool TryRestoreFromActivity(SnapshotLaunchArguments snapshotArgs, UserActivity activity, out string errorMessage) + //{ + // if (!snapshotArgs.VerifyIncomingActivity(activity)) + // { + // errorMessage = "IncomingActivityFailed"; + // return false; + // } - // Work around for bug https://microsoft.visualstudio.com/DefaultCollection/OS/_workitems/edit/48931227 - // where ContentInfo can't be directly accessed. - if (!JsonObject.TryParse(activity.ToJson(), out var activityJson)) - { - errorMessage = "ParseJsonError"; - return false; - } + // // Work around for bug https://microsoft.visualstudio.com/DefaultCollection/OS/_workitems/edit/48931227 + // // where ContentInfo can't be directly accessed. + // if (!JsonObject.TryParse(activity.ToJson(), out var activityJson)) + // { + // errorMessage = "ParseJsonError"; + // return false; + // } - if (!activityJson.ContainsKey("contentInfo")) - { - errorMessage = "ContentInfoNotExist"; - return false; - } + // if (!activityJson.ContainsKey("contentInfo")) + // { + // errorMessage = "ContentInfoNotExist"; + // return false; + // } - if (!Model.TryRestoreFromSnapshot(activityJson.GetNamedObject("contentInfo"))) - { - errorMessage = "RestoreFromSnapshotFailed"; - return false; - } + // if (!Model.TryRestoreFromSnapshot(activityJson.GetNamedObject("contentInfo"))) + // { + // errorMessage = "RestoreFromSnapshotFailed"; + // return false; + // } - errorMessage = string.Empty; - return true; - } + // errorMessage = string.Empty; + // return true; + //} private void InitializeNavViewCategoriesSource() {