* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "page_manager.h"
#include "common/screen.h"
#include "components/root_view.h"
#include "scope_guard.h"
#include "sub_page.h"
namespace Updater {
using namespace OHOS;
PageManager &PageManager::GetInstance()
{
static PageManager instance;
return instance;
}
bool PageManager::InitImpl(UxPageInfo &pageInfo, std::string_view entry)
{
if (!BasePage::IsPageInfoValid(pageInfo)) {
return false;
}
auto basePage = Page::Create<BasePage>(Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());
if (basePage == nullptr || basePage->GetView() == nullptr) {
LOG(ERROR) << "create base page failed";
return false;
}
if (!basePage->BuildPage(pageInfo)) {
LOG(ERROR) << "Build page failed";
return false;
}
if (!BuildSubPages(basePage->GetPageId(), basePage, pageInfo.subpages, entry)) {
LOG(ERROR) << "Build sub page failed";
return false;
}
basePage->SetVisible(false);
if (OHOS::RootView::GetInstance() == nullptr) {
LOG(ERROR) << "rootview is nullptr!";
return false;
}
OHOS::RootView::GetInstance()->Add(basePage->GetView());
if (!pageMap_.emplace(pageInfo.id, basePage).second) {
LOG(ERROR) << "base page id duplicated:" << pageInfo.id;
return false;
}
pages_.push_back(basePage);
if (pageInfo.id == entry) {
mainPage_ = basePage;
}
return true;
}
bool PageManager::Init(std::vector<UxPageInfo> &pageInfos, std::string_view entry)
{
Reset();
ON_SCOPE_EXIT(reset) {
Reset();
};
for (auto &pageInfo : pageInfos) {
if (!InitImpl(pageInfo, entry)) {
return false;
}
}
if (!IsValidPage(mainPage_)) {
LOG(ERROR) << "entry " << entry << " is invalid ";
return false;
}
CANCEL_SCOPE_EXIT_GUARD(reset);
curPage_ = mainPage_;
return true;
}
bool PageManager::ResizeImpl(UxPageInfo &pageInfo, std::string_view entry)
{
auto it = pageMap_.find(pageInfo.id);
if (it == pageMap_.end() || it->second == nullptr) {
LOG(ERROR) << "find page failed, id = " << pageInfo.id;
return false;
}
auto& basePage = static_cast<BasePage&>(*it->second);
basePage.width_ = Screen::GetInstance().GetWidth();
basePage.height_ = Screen::GetInstance().GetHeight();
basePage.ResizePage(pageInfo);
if (OHOS::RootView::GetInstance() == nullptr) {
LOG(ERROR) << "rootview is nullptr!";
return false;
}
OHOS::RootView::GetInstance()->Add(basePage.GetView());
return true;
}
bool PageManager::Resize(std::vector<UxPageInfo> &pageInfos, std::string_view entry)
{
if (OHOS::RootView::GetInstance() == nullptr) {
LOG(ERROR) << "rootview is nullptr!";
return false;
}
OHOS::RootView::GetInstance()->RemoveAll();
for (auto &pageInfo : pageInfos) {
if (!ResizeImpl(pageInfo, entry)) {
return false;
}
}
return true;
}
bool PageManager::BuildSubPages(const std::string &pageId, const std::shared_ptr<Page> &basePage,
std::vector<UxSubPageInfo> &subPageInfos, std::string_view entry)
{
for (auto &subPageInfo : subPageInfos) {
if (!SubPage::IsPageInfoValid(subPageInfo)) {
return false;
}
const std::string &subPageId = pageId + ":" + subPageInfo.id;
auto subPage = Page::Create<SubPage>(basePage, subPageId);
if (subPage == nullptr) {
LOG(ERROR) << "create sub page failed";
return false;
}
if (!subPage->BuildSubPage(subPageInfo)) {
LOG(ERROR) << "build sub page failed";
return false;
}
if (!pageMap_.emplace(subPageId, subPage).second) {
LOG(ERROR) << "sub page id duplicated:" << subPageId;
return false;
}
pages_.push_back(subPage);
LOG(DEBUG) << subPageId << " builded";
if (subPageId == entry) {
mainPage_ = subPage;
}
}
return true;
}
bool PageManager::IsValidCom(const ComInfo &pageComId) const
{
const std::string &pageId = pageComId.pageId;
const std::string &comId = pageComId.comId;
auto it = pageMap_.find(pageId);
if (it == pageMap_.end() || it->second == nullptr) {
LOG(ERROR) << "page id " << pageId << "not valid";
return false;
}
const Page &page = *(it->second);
return page.IsValidCom(comId);
}
bool PageManager::IsValidPage(const std::shared_ptr<Page> &pg) const
{
return pg != nullptr && pg->IsValid();
}
bool PageManager::ShowPage(const std::string &id)
{
if (!IsValidPage(curPage_)) {
LOG(ERROR) << "cur page is null";
return false;
}
if (id == curPage_->GetPageId()) {
curPage_->SetVisible(true);
LOG(WARNING) << "show cur page again";
return true;
}
auto it = pageMap_.find(id);
if (it == pageMap_.end()) {
LOG(ERROR) << "show page failed, id = " << id;
return false;
}
curPage_->SetVisible(false);
EnQueuePage(curPage_);
curPage_ = it->second;
curPage_->SetVisible(true);
return true;
}
void PageManager::ShowCurPage()
{
ShowPage(GetCurPageId());
}
void PageManager::ShowMainPage()
{
if (!IsValidPage(mainPage_)) {
LOG(ERROR) << "main page invalid, can't show main page";
return;
}
ShowPage(mainPage_->GetPageId());
}
void PageManager::GoBack()
{
if (!IsValidPage(curPage_)) {
LOG(ERROR) << "cur page is null";
return;
}
if (pageQueue_.empty()) {
LOG(ERROR) << "queue empty, can't go back";
return;
}
curPage_->SetVisible(false);
curPage_ = pageQueue_.front();
pageQueue_.pop_front();
curPage_->SetVisible(true);
}
Page &PageManager::operator[](const std::string &id) const
{
static BasePage dummy;
auto it = pageMap_.find(id);
if (it == pageMap_.end() || it->second == nullptr) {
return dummy;
}
return *(it->second);
}
ViewProxy &PageManager::operator[](const ComInfo &comInfo) const
{
return (*this)[comInfo.pageId][comInfo.comId];
}
void PageManager::EnQueuePage(const std::shared_ptr<Page> &page)
{
if (!IsValidPage(page)) {
LOG(ERROR) << "enqueue invalid page";
return;
}
pageQueue_.push_front(page);
if (pageQueue_.size() > MAX_PAGE_QUEUE_SZ) {
pageQueue_.pop_back();
}
}
void PageManager::Reset()
{
OHOS::RootView::GetInstance()->RemoveAll();
pageQueue_.clear();
pageMap_.clear();
pages_.clear();
curPage_ = nullptr;
mainPage_ = nullptr;
}
std::string PageManager::GetCurPageId()
{
if (curPage_ != nullptr) {
return curPage_->GetPageId();
}
return "";
}
bool PageManager::AddExtraCom(const std::string &subPageId, const std::vector<std::string> &extraComs)
{
auto it = pageMap_.find(subPageId);
if (it == pageMap_.end() || it->second == nullptr) {
LOG(ERROR) << "sub page id not found: " << subPageId;
return false;
}
auto *subPage = static_cast<SubPage*>(it->second.get());
if (subPage == nullptr) {
LOG(ERROR) << "page is not a sub page: " << subPageId;
return false;
}
for (const auto &comId : extraComs) {
subPage->AddExtraCom(comId);
}
return true;
}
bool PageManager::SetCurPage(const std::string &id)
{
auto it = pageMap_.find(id);
if (it == pageMap_.end()) {
LOG(ERROR) << "find page failed, id = " << id;
return false;
}
curPage_ = it->second;
return true;
}
std::vector<std::string> PageManager::GetPageQueue()
{
std::vector<std::string> pageQueue;
pageQueue.reserve(pageQueue_.size());
for (auto page = pageQueue_.begin(); page != pageQueue_.end(); ++page) {
auto id = (*page)->GetPageId();
pageQueue.push_back(id);
}
return pageQueue;
}
bool PageManager::SetPageQueue(const std::vector<std::string> &pageQueue)
{
for (auto id = pageQueue.rbegin(); id != pageQueue.rend(); ++id) {
auto page = pageMap_.find(*id);
if (page == pageMap_.end()) {
LOG(ERROR) << "find page failed, id = " << *id;
return false;
}
EnQueuePage(page->second);
}
return true;
}
#ifdef UPDATER_UT
std::vector<std::string> PageManager::Report()
{
std::vector<std::string> result {};
for (auto &[id, pg] : pageMap_) {
if (pg->IsVisible()) {
result.push_back(id);
}
}
std::sort(result.begin(), result.end());
return result;
}
#endif
}