1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci
16fb299fa2Sopenharmony_ci#include "updater_ui_config.h"
17fb299fa2Sopenharmony_ci#include "common/screen.h"
18fb299fa2Sopenharmony_ci#include "control/callback_manager.h"
19fb299fa2Sopenharmony_ci#include "language/language_ui.h"
20fb299fa2Sopenharmony_ci#include "layout/layout_parser.h"
21fb299fa2Sopenharmony_ci#include "log/log.h"
22fb299fa2Sopenharmony_ci#include "utils.h"
23fb299fa2Sopenharmony_ci
24fb299fa2Sopenharmony_cinamespace Updater {
25fb299fa2Sopenharmony_cinamespace Fs = std::filesystem;
26fb299fa2Sopenharmony_cinamespace {
27fb299fa2Sopenharmony_ciconstexpr auto UI_CFG_FILE = "/resources/pages/config.json";
28fb299fa2Sopenharmony_ciconstexpr auto UI_CFG_KEY = "config";
29fb299fa2Sopenharmony_ciconstexpr auto WIDTH_KEY = "screenWidth";
30fb299fa2Sopenharmony_ciconstexpr auto HEIGHT_KEY = "screenHeight";
31fb299fa2Sopenharmony_ciconstexpr auto FOCUS_CFG_FIELD = "enableFoucs";
32fb299fa2Sopenharmony_ci
33fb299fa2Sopenharmony_cibool CanonicalPagePath(PagePath &pagePath)
34fb299fa2Sopenharmony_ci{
35fb299fa2Sopenharmony_ci    if (!Utils::PathToRealPath(pagePath.dir, pagePath.dir)) {
36fb299fa2Sopenharmony_ci        LOG(ERROR) << "page path canonical failed, please check your config, dir = " << pagePath.dir;
37fb299fa2Sopenharmony_ci        return false;
38fb299fa2Sopenharmony_ci    }
39fb299fa2Sopenharmony_ci    for (auto &file : pagePath.pages) {
40fb299fa2Sopenharmony_ci        file = pagePath.dir + "/" + file;
41fb299fa2Sopenharmony_ci    }
42fb299fa2Sopenharmony_ci    return true;
43fb299fa2Sopenharmony_ci}
44fb299fa2Sopenharmony_ci
45fb299fa2Sopenharmony_cistd::ostream &operator<<(std::ostream &os, const UxViewCommonInfo &info)
46fb299fa2Sopenharmony_ci{
47fb299fa2Sopenharmony_ci    os << "x=" << info.x << ", y=" << info.y << ", w=" << info.w << ", h=" << info.h << ", id=";
48fb299fa2Sopenharmony_ci    os << info.id << ", type=" << info.type << ", visible=" << info.visible;
49fb299fa2Sopenharmony_ci    return os;
50fb299fa2Sopenharmony_ci}
51fb299fa2Sopenharmony_ci
52fb299fa2Sopenharmony_cistd::ostream &operator<<(std::ostream &os, const UxPageInfo &info)
53fb299fa2Sopenharmony_ci{
54fb299fa2Sopenharmony_ci    LOG(DEBUG) << "page:" << info.id;
55fb299fa2Sopenharmony_ci    for (auto &it : info.viewInfos) {
56fb299fa2Sopenharmony_ci        LOG(DEBUG) << it.commonInfo;
57fb299fa2Sopenharmony_ci    }
58fb299fa2Sopenharmony_ci    return os;
59fb299fa2Sopenharmony_ci}
60fb299fa2Sopenharmony_ci
61fb299fa2Sopenharmony_civoid PrintInfoVec(const std::vector<UxPageInfo> &infoVec)
62fb299fa2Sopenharmony_ci{
63fb299fa2Sopenharmony_ci    LOG(DEBUG) << "=====print start=====";
64fb299fa2Sopenharmony_ci    for (auto &iter : infoVec) {
65fb299fa2Sopenharmony_ci        LOG(DEBUG) << iter;
66fb299fa2Sopenharmony_ci    }
67fb299fa2Sopenharmony_ci    LOG(DEBUG) << "=====print end=====";
68fb299fa2Sopenharmony_ci}
69fb299fa2Sopenharmony_ci
70fb299fa2Sopenharmony_cistd::string SelectConfig(const JsonNode &node)
71fb299fa2Sopenharmony_ci{
72fb299fa2Sopenharmony_ci    using namespace OHOS;
73fb299fa2Sopenharmony_ci    for (const auto &iter : node) {
74fb299fa2Sopenharmony_ci        const JsonNode &subCfgPathNode = iter.get();
75fb299fa2Sopenharmony_ci        auto optStr = subCfgPathNode.As<std::string>();
76fb299fa2Sopenharmony_ci        if (!optStr.has_value()) {
77fb299fa2Sopenharmony_ci            LOG(ERROR) << "config array's element should be string";
78fb299fa2Sopenharmony_ci            return "";
79fb299fa2Sopenharmony_ci        }
80fb299fa2Sopenharmony_ci        std::string subConfigPath = *optStr;
81fb299fa2Sopenharmony_ci        const JsonNode &subCfg = JsonNode { Fs::path { subConfigPath }};
82fb299fa2Sopenharmony_ci        auto screenW = subCfg[WIDTH_KEY].As<int16_t>();
83fb299fa2Sopenharmony_ci        auto screenH = subCfg[HEIGHT_KEY].As<int16_t>();
84fb299fa2Sopenharmony_ci        if (!screenW.has_value() || !screenH.has_value()) {
85fb299fa2Sopenharmony_ci            LOG(ERROR) << "real config file should has screenW and screenH key";
86fb299fa2Sopenharmony_ci            return "";
87fb299fa2Sopenharmony_ci        }
88fb299fa2Sopenharmony_ci        if (screenW != Screen::GetInstance().GetWidth() || screenH != Screen::GetInstance().GetHeight()) {
89fb299fa2Sopenharmony_ci            LOG(INFO) << "screen size not matched" << subConfigPath;
90fb299fa2Sopenharmony_ci            continue;
91fb299fa2Sopenharmony_ci        }
92fb299fa2Sopenharmony_ci        LOG(INFO) << "select config: " << subConfigPath;
93fb299fa2Sopenharmony_ci        return subConfigPath;
94fb299fa2Sopenharmony_ci    }
95fb299fa2Sopenharmony_ci    LOG(ERROR) << "no config matched";
96fb299fa2Sopenharmony_ci    return "";
97fb299fa2Sopenharmony_ci}
98fb299fa2Sopenharmony_ci} // namespace
99fb299fa2Sopenharmony_ci
100fb299fa2Sopenharmony_cibool UpdaterUiConfig::isFocusEnable_ {false};
101fb299fa2Sopenharmony_ci
102fb299fa2Sopenharmony_cibool UpdaterUiConfig::Init()
103fb299fa2Sopenharmony_ci{
104fb299fa2Sopenharmony_ci    JsonNode node { Fs::path { UI_CFG_FILE }};
105fb299fa2Sopenharmony_ci    const JsonNode &cfgNode = node[UI_CFG_KEY];
106fb299fa2Sopenharmony_ci    switch (cfgNode.Type()) {
107fb299fa2Sopenharmony_ci        case NodeType::STRING: {
108fb299fa2Sopenharmony_ci            auto optString = cfgNode.As<std::string>();
109fb299fa2Sopenharmony_ci            if (!optString.has_value()) {
110fb299fa2Sopenharmony_ci                LOG(ERROR) << "config path should be string";
111fb299fa2Sopenharmony_ci                break;
112fb299fa2Sopenharmony_ci            }
113fb299fa2Sopenharmony_ci            JsonNode realNode { Fs::path { *optString }};
114fb299fa2Sopenharmony_ci            return Init(realNode);
115fb299fa2Sopenharmony_ci        }
116fb299fa2Sopenharmony_ci        case NodeType::ARRAY: {
117fb299fa2Sopenharmony_ci            std::string realConfig = SelectConfig(cfgNode);
118fb299fa2Sopenharmony_ci            if (realConfig.empty()) {
119fb299fa2Sopenharmony_ci                break;
120fb299fa2Sopenharmony_ci            }
121fb299fa2Sopenharmony_ci            JsonNode realNode { Fs::path { realConfig }};
122fb299fa2Sopenharmony_ci            return Init(realNode);
123fb299fa2Sopenharmony_ci        }
124fb299fa2Sopenharmony_ci        default:
125fb299fa2Sopenharmony_ci            break;
126fb299fa2Sopenharmony_ci    }
127fb299fa2Sopenharmony_ci    LOG(ERROR) << "config file parse failed: " << UI_CFG_FILE;
128fb299fa2Sopenharmony_ci    return false;
129fb299fa2Sopenharmony_ci}
130fb299fa2Sopenharmony_ci
131fb299fa2Sopenharmony_cibool UpdaterUiConfig::Init(const JsonNode &node)
132fb299fa2Sopenharmony_ci{
133fb299fa2Sopenharmony_ci    static bool res = [&node] () {
134fb299fa2Sopenharmony_ci        return LoadLangRes(node) && LoadStrategy(node) && LoadCallbacks(node) && LoadFocusCfg(node) && LoadPages(node);
135fb299fa2Sopenharmony_ci    } ();
136fb299fa2Sopenharmony_ci    return res;
137fb299fa2Sopenharmony_ci}
138fb299fa2Sopenharmony_ci
139fb299fa2Sopenharmony_ciconst std::unordered_map<std::string, UiStrategyCfg> &UpdaterUiConfig::GetStrategy()
140fb299fa2Sopenharmony_ci{
141fb299fa2Sopenharmony_ci    return UiStrategy::GetStrategy();
142fb299fa2Sopenharmony_ci}
143fb299fa2Sopenharmony_ci
144fb299fa2Sopenharmony_cibool UpdaterUiConfig::GetFocusCfg()
145fb299fa2Sopenharmony_ci{
146fb299fa2Sopenharmony_ci    return isFocusEnable_;
147fb299fa2Sopenharmony_ci}
148fb299fa2Sopenharmony_ci
149fb299fa2Sopenharmony_cibool UpdaterUiConfig::LoadPages(const JsonNode &node)
150fb299fa2Sopenharmony_ci{
151fb299fa2Sopenharmony_ci    PagePath pagePath {};
152fb299fa2Sopenharmony_ci    if (!Visit<SETVAL>(node, pagePath)) {
153fb299fa2Sopenharmony_ci        LOG(ERROR) << "parse page path error: " << pagePath.dir;
154fb299fa2Sopenharmony_ci        return false;
155fb299fa2Sopenharmony_ci    }
156fb299fa2Sopenharmony_ci
157fb299fa2Sopenharmony_ci    if (!CanonicalPagePath(pagePath)) {
158fb299fa2Sopenharmony_ci        return false;
159fb299fa2Sopenharmony_ci    }
160fb299fa2Sopenharmony_ci
161fb299fa2Sopenharmony_ci    std::vector<UxPageInfo> pageInfos {};
162fb299fa2Sopenharmony_ci    if (!LayoutParser::GetInstance().LoadLayout(pagePath.pages, pageInfos)) {
163fb299fa2Sopenharmony_ci        LOG(ERROR) << "load layout error: " << UI_CFG_FILE;
164fb299fa2Sopenharmony_ci        return false;
165fb299fa2Sopenharmony_ci    }
166fb299fa2Sopenharmony_ci    if (!PageManager::GetInstance().Init(pageInfos, pagePath.entry)) {
167fb299fa2Sopenharmony_ci        LOG(ERROR) << "page manager init error";
168fb299fa2Sopenharmony_ci        return false;
169fb299fa2Sopenharmony_ci    }
170fb299fa2Sopenharmony_ci    PrintInfoVec(pageInfos);
171fb299fa2Sopenharmony_ci    return true;
172fb299fa2Sopenharmony_ci}
173fb299fa2Sopenharmony_ci
174fb299fa2Sopenharmony_cibool UpdaterUiConfig::LoadLangRes(const JsonNode &node)
175fb299fa2Sopenharmony_ci{
176fb299fa2Sopenharmony_ci    return Lang::LanguageUI::GetInstance().LoadLangRes(node);
177fb299fa2Sopenharmony_ci}
178fb299fa2Sopenharmony_ci
179fb299fa2Sopenharmony_cibool UpdaterUiConfig::LoadStrategy(const JsonNode &node)
180fb299fa2Sopenharmony_ci{
181fb299fa2Sopenharmony_ci    return UiStrategy::LoadStrategy(node);
182fb299fa2Sopenharmony_ci}
183fb299fa2Sopenharmony_ci
184fb299fa2Sopenharmony_cibool UpdaterUiConfig::LoadCallbacks(const JsonNode &node)
185fb299fa2Sopenharmony_ci{
186fb299fa2Sopenharmony_ci    return CallbackManager::LoadCallbacks(node);
187fb299fa2Sopenharmony_ci}
188fb299fa2Sopenharmony_ci
189fb299fa2Sopenharmony_cibool UpdaterUiConfig::LoadFocusCfg(const JsonNode &node)
190fb299fa2Sopenharmony_ci{
191fb299fa2Sopenharmony_ci    // disable focus by default
192fb299fa2Sopenharmony_ci    isFocusEnable_ = node[FOCUS_CFG_FIELD].As<bool>().value_or(false);
193fb299fa2Sopenharmony_ci    return true;
194fb299fa2Sopenharmony_ci}
195fb299fa2Sopenharmony_ci} // namespace Updater