#include "pch.h" #include "MRUListHandler.h" #include "Helpers.h" #include #include namespace { const wchar_t c_mruList[] = L"MRUList"; const wchar_t c_insertionIdx[] = L"InsertionIdx"; const wchar_t c_maxMRUSize[] = L"MaxMRUSize"; } MRUListHandler::MRUListHandler(unsigned int size, const std::wstring& filePath, const std::wstring& regPath) : pushIdx(0), nextIdx(1), size(size), jsonFilePath(PTSettingsHelper::get_module_save_folder_location(PowerRenameConstants::ModuleKey) + filePath), registryFilePath(regPath) { items.resize(size); Load(); } void MRUListHandler::Push(const std::wstring& data) { if (Exists(data)) { // TODO: Already existing item should be put on top of MRU list. return; } items[pushIdx] = data; pushIdx = (pushIdx + 1) % size; Save(); } bool MRUListHandler::Next(std::wstring& data) { if (nextIdx == size + 1) { Reset(); return false; } // Go backwards to consume latest items first. unsigned int idx = (pushIdx + size - nextIdx) % size; if (items[idx].empty()) { Reset(); return false; } data = items[idx]; ++nextIdx; return true; } void MRUListHandler::Reset() { nextIdx = 1; } const std::vector& MRUListHandler::GetItems() { return items; } void MRUListHandler::Load() { if (!std::filesystem::exists(jsonFilePath)) { MigrateFromRegistry(); Save(); } else { ParseJson(); } } void MRUListHandler::Save() { json::JsonObject jsonData; jsonData.SetNamedValue(c_maxMRUSize, json::value(size)); jsonData.SetNamedValue(c_insertionIdx, json::value(pushIdx)); jsonData.SetNamedValue(c_mruList, Serialize()); json::to_file(jsonFilePath, jsonData); } json::JsonArray MRUListHandler::Serialize() { json::JsonArray searchMRU{}; std::wstring data{}; for (const std::wstring& item : items) { searchMRU.Append(json::value(item)); } return searchMRU; } void MRUListHandler::MigrateFromRegistry() { std::wstring searchListKeys = GetRegString(c_mruList, registryFilePath); std::sort(std::begin(searchListKeys), std::end(searchListKeys)); for (const wchar_t& key : searchListKeys) { Push(GetRegString(std::wstring(1, key), registryFilePath)); } } void MRUListHandler::ParseJson() { auto json = json::from_file(jsonFilePath); if (json) { const json::JsonObject& jsonObject = json.value(); try { unsigned int oldSize{ size }; if (json::has(jsonObject, c_maxMRUSize, json::JsonValueType::Number)) { oldSize = (unsigned int)jsonObject.GetNamedNumber(c_maxMRUSize); } unsigned int oldPushIdx{ 0 }; if (json::has(jsonObject, c_insertionIdx, json::JsonValueType::Number)) { oldPushIdx = (unsigned int)jsonObject.GetNamedNumber(c_insertionIdx); if (oldPushIdx < 0 || oldPushIdx >= oldSize) { oldPushIdx = 0; } } if (json::has(jsonObject, c_mruList, json::JsonValueType::Array)) { auto jsonArray = jsonObject.GetNamedArray(c_mruList); if (oldSize == size) { for (uint32_t i = 0; i < jsonArray.Size(); ++i) { items[i] = std::wstring(jsonArray.GetStringAt(i)); } pushIdx = oldPushIdx; } else { std::vector temp; for (unsigned int i = 0; i < min(jsonArray.Size(), size); ++i) { int idx = (oldPushIdx + oldSize - (i + 1)) % oldSize; temp.push_back(std::wstring(jsonArray.GetStringAt(idx))); } if (size > oldSize) { std::reverse(std::begin(temp), std::end(temp)); pushIdx = (unsigned int)temp.size(); temp.resize(size); } else { temp.resize(size); std::reverse(std::begin(temp), std::end(temp)); } items = std::move(temp); Save(); } } } catch (const winrt::hresult_error&) { } } } bool MRUListHandler::Exists(const std::wstring& data) { return std::find(std::begin(items), std::end(items), data) != std::end(items); }