sync launcher code

Signed-off-by: zhao-zhiqiang-zzq <zhaozhiqiang21@huawei.com>
This commit is contained in:
zhao-zhiqiang-zzq 2021-07-14 11:49:08 +08:00
parent 74e8c085f2
commit 4174e02d14
111 changed files with 5067 additions and 939 deletions

4
.gitattributes vendored
View File

@ -13,3 +13,7 @@
*.so filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.dat filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.bz filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text

57
OAT.xml Normal file
View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2021 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.
This is the configuration file template for OpenHarmony OSS Audit Tool, please copy it to your project root dir and modify it refer to OpenHarmony/tools_oat/README.
All configurations in this file will be merged to OAT-Default.xml, if you have any questions or concerns, please create issue in OpenHarmony/tools_oat and @jalenchen or chenyaxun.
licensefile:
1.If the project don't have "LICENSE" in root dir, please define all the license files in this project in , OAT will check license files according to this rule.
policylist:
1. policy: If the OAT-Default.xml policies do not meet your requirements, please add policies here.
2. policyitem: The fields type, name, path, desc is required, and the fields rule, group, filefilter is optional,the default value is:
<policyitem type="" name="" path="" desc="" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
3. policyitem type:
"compatibility" is used to check license compatibility in the specified path;
"license" is used to check source license header in the specified path;
"copyright" is used to check source copyright header in the specified path;
"import" is used to check source dependency in the specified path, such as import ... ,include ...
"filetype" is used to check file type in the specified path, supported file types: archive, binary
"filename" is used to check whether the specified file exists in the specified path(projectroot means the root dir of the project), supported file names: LICENSE, README, README.OpenSource
4. policyitem name: This field is used for define the license, copyright, "*" means match all, the "!" prefix means could not match this value. For example, "!GPL" means can not use GPL license.
5. policyitem path: This field is used for define the source file scope to apply this policyitem, the "!" prefix means exclude the files. For example, "!.*/lib/.*" means files in lib dir will be exclude while process this policyitem.
6. policyitem rule and group: These two fields are used together to merge policy results. "may" policyitems in the same group means any one in this group passed, the result will be passed.
7. policyitem filefilter: Used to bind filefilter which define filter rules.
7. policyitem desc: Used to describe the reason of this policy item, committers will check this while merging the code.
8. filefilter: Filter rules, the type filename is used to filter file name, the type filepath is used to filter file path.
Note:If the text contains special characters, please escape them according to the following rules:
" == &gt;
& == &gt;
' == &gt;
< == &gt;
> == &gt;
-->
<configuration>
<oatconfig>
<policylist>
<policy name="projectPolicy" desc="">
<policyitem type="copyright" name="Copyright 2015 the original author or authors." path="gradlew" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc="file generated by development tool"/>
<policyitem type="copyright" name="Copyright 2015 the original author or authors." path="gradlew.bat" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc="file generated by development tool"/>
</policy>
</policylist>
</oatconfig>
</configuration>

View File

@ -39,5 +39,5 @@ The home screen launcher provides a main entry to human-machine interactions. It
System apps
**applications\_launcher**
**applications\_standard\_launcher**

View File

@ -39,4 +39,4 @@
系统应用
**applications\_launcher**
**applications\_standard\_launcher**

View File

@ -3,7 +3,7 @@
"bundleName": "com.ohos.launcher",
"vendor": "ohos",
"version": {
"code": 1,
"code": 1000000,
"name": "1.0"
},
"apiVersion": {
@ -21,7 +21,8 @@
"distro": {
"deliveryWithInstall": true,
"moduleName": "launcher",
"moduleType": "entry"
"moduleType": "entry",
"installationFree": true
},
"abilities": [
{
@ -57,8 +58,7 @@
"pages": [
"pages/EntryView/EntryView",
"pages/AppGridView/AppGridView",
"pages/AppListView/AppListView",
"pages/SettingsView/SettingsView"
"pages/AppListView/AppListView"
],
"name": "default",
"window": {

View File

@ -15,18 +15,30 @@
import AppModel from './common/model/AppModel.js'
import SettingsModel from './common/model/SettingsModel.js'
import MMIModel from './common/model/MMIModel.js'
import ResourceManager from './common/model/ResourceManager.js'
import AppListInfoCacheManager from './common/cache/AppListInfoCacheManager.js'
export default {
data: {
data:{
appModel: new AppModel(),
settingsModel: new SettingsModel()
settingsModel: new SettingsModel(),
mmiModel: new MMIModel(),
resourceManager: new ResourceManager(),
appListInfoCacheManager: new AppListInfoCacheManager(),
screenHeight: 0,
screenWidth: 0
},
onCreate() {
console.info("Application onCreate");
console.info("Launcher app Application onCreate");
this.data.appModel.registerAppListEvent();
},
onDestroy() {
console.info("Application onDestroy");
console.info("Launcher app Application onDestroy");
this.data.resourceManager.clearCache();
this.data.appListInfoCacheManager.clearCache();
this.data.appModel.unregisterAppListEvent();
}
};

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2021 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.
*/
import LruCache from './LruCache.js';
import DiskLruCache from './DiskLruCache.js';
/**
* A Manager class that provides get/set/clear cache methods for app list data.
*/
export default class AppListInfoCacheManager {
#lruCache;
#diskLruCache;
constructor() {
this.#lruCache = new LruCache();
this.#diskLruCache = new DiskLruCache();
}
/**
* Get cache from disk or memory.
*
* @param {string} key - key of the cache map
* @return {object} - cache get from the memory or disk
*/
getCache(key) {
console.info("Launcher AppListInfoCacheManager getCache key = " + key);
let cache = this.#lruCache.getCache(key);
if (cache == undefined || cache == null || cache == '' || cache == -1) {
return this.#diskLruCache.getCache(key);
} else {
return cache;
}
}
/**
* Set cache to disk or memory.
*
* @param {string} key - key of the cache map
* @param {object} value - value of the cache map
*/
setCache(key, value) {
console.info("Launcher AppListInfoCacheManager setCache key = " + key + " value = " + value);
this.#lruCache.putCache(key, value);
this.#diskLruCache.putCache(key, value);
}
/**
* Clear cache of both disk and memory.
*/
clearCache() {
console.info("Launcher AppListInfoCacheManager clearCache");
this.#lruCache.clear();
this.#diskLruCache.clear();
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2021 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.
*/
import LruCache from './LruCache.js'
import DiskLruCache from './DiskLruCache.js'
const KEY_ICON = "icon";
const DISK_CACHE_MISS = -1;
/**
* A Manager class that provides get/set/clear cache methods for app image data.
*/
export default class AppResourceCacheManager {
#memoryCache;
#diskCache;
constructor() {
this.#memoryCache = new LruCache();
this.#diskCache = new DiskLruCache();
}
/**
* Get cache from disk or memory.
*
* @param {string} key - key of the cache map
* @return {object} - cache get from memory or disk
*/
getCache(bundleName, key) {
console.info("Launcher AppResourceCacheManager getCache bundleName = " + bundleName + " key = " + key);
let cache = this.#getCacheFromMemory(bundleName, key);
if (cache == undefined || cache == null || cache == '') {
if (key === KEY_ICON) {
return this.#getCacheFromDisk(bundleName);
}
return null;
} else {
return cache;
}
}
/**
* Set cache to disk or memory.
*
* @param {string} key - key of the cache map
* @param {object} value - value of the cache map
*/
setCache(bundleName, key, value) {
console.info("Launcher AppResourceCacheManager setCache bundleName = " + bundleName + " key = " + key);
this.#setCacheToMemory(bundleName, key, value);
if (key === KEY_ICON) {
this.#setCacheToDisk(bundleName, key, value);
}
}
/**
* Clear cache of both disk and memory.
*/
clearCache() {
console.info("Launcher AppResourceCacheManager clearCache");
this.#memoryCache.clear();
}
#getCacheFromMemory = (bundleName, key) => {
let cache = this.#memoryCache.getCache(bundleName);
if (cache == undefined || cache == null || cache == '' || cache === -1) {
return null;
} else if (cache[key] == undefined || cache[key] == null || cache[key] == '') {
return null;
} else {
return cache[key];
}
}
#setCacheToMemory = (bundleName, key, value) => {
let cache = this.#memoryCache.getCache(bundleName);
if (cache == undefined || cache == null || cache == '' || cache === -1) {
cache = {};
cache[key] = value;
} else {
cache[key] = value;
}
this.#memoryCache.putCache(bundleName, cache);
}
#getCacheFromDisk = (bundleName, key) => {
let data = this.#diskCache.getCache(bundleName);
return data !== DISK_CACHE_MISS ? data : null;
}
#setCacheToDisk = (bundleName, key, value) => {
this.#diskCache.putCache(bundleName, value);
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2021 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.
*/
import FileUtils from "../utils/FileUtils.js";
/**
* A class provides persistent operation for memory cache.
*/
export default class DiskLruCache {
constructor(capacity = 100) {
this.cache = new Map();
this.capacity = capacity;
this.initMap(); //read cache from local
}
/**
* Init the cache whether the file has data.
*/
initMap() {
console.info("Launcher DiskLruCache initMap start execution");
try {
let arr = FileUtils.readJournal().split("\n").reverse();
let len = arr.length >= this.capacity ? this.capacity : arr.length;
for (let i = 0;i < len; i++) {
this.cache.set(arr[i], arr[i]);
}
} catch (e) {
console.error("Launcher DiskLruCache initMap e " + e);
}
}
/**
* Get cache from disk.
*
* @param {string} key - key of the cache map
* @return {object} - target cache object
*/
getCache(key) {
if (this.cache.has(key)) {
// exist and update
let temp = this.cache.get(key);
//delete the old cache
this.cache.delete(key);
//update the cache to recent use
this.cache.set(key, temp);
//update local cache to recent use
FileUtils.writeJournal(key);
return FileUtils.readJsonObj(key)[key];
}
return -1;
}
/**
* Put cache to disk.
*
* @param {string} key - key of the cache map
* @param {object} value - value of the cache map
*/
putCache(key, value) {
if (this.cache.has(key)) {
// exist and update
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
// if size > capacity ,remove the old
this.remove(this.cache.keys().next().value);
}
//update the cache to recent use
this.cache.set(key, value);
//update local cache to recent use
FileUtils.writeJournal(key);
FileUtils.writeJsonObj({
[key] : value
}, key);
}
/**
* Remove cache of corresponding key.
*
* @param {string} key - key of the cache map
*/
remove(key) {
this.cache.delete(key);
FileUtils.removeFile(key);
}
/**
* Clear cache of disk.
*/
clear() {
this.cache.forEach(function (value, key) {
FileUtils.removeFile(key);
});
this.cache.clear();
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2021 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.
*/
/**
* A class provides memory cache operation.
*/
export default class LruCache {
constructor(capacity = 100) {
this.cache = new Map();
this.capacity = capacity; //the capacity of cache
}
/**
* Get cache from memory.
*
* @param {string} key - key of the cache map
* @return {object} - cache from memory
*/
getCache(key) {
if (this.cache.has(key)) {
// exist and update
let temp = this.cache.get(key);
//delete the old cache
this.cache.delete(key);
//update the cache to recent use
this.cache.set(key, temp);
return temp;
}
return -1;
}
/**
* Put cache to disk.
*
* @param {string} key - key of the cache map
* @param {object} value - value of the cache map
*/
putCache(key, value) {
if (this.cache.has(key)) {
// exist and update
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
// if size > capacity ,remove the old
this.cache.delete(this.cache.keys().next().value);
}
//update the cache to recent use
this.cache.set(key, value);
}
/**
* Remove cache of corresponding key.
*
* @param {string} key - key of the cache map
*/
remove(key) {
this.cache.delete(key);
}
/**
* Clear cache of memory.
*/
clear() {
this.cache.clear();
}
}

View File

@ -13,7 +13,10 @@
* limitations under the License.
*/
var Colors = {
/**
* Description: Color data.
*/
const Colors = {
bgSelectedColor: "#FF008000",
bgUnselectedColor: "white",
fontSelectedColor: "white",

View File

@ -14,9 +14,8 @@
*/
@import '../../css/CommonPageStyle.css';
.image-box{
height: 110px;
width: 110px;
display: flex;
align-items: center;
justify-content: center;

View File

@ -15,6 +15,6 @@
*/
-->
<div class="image-box">
<image class="app-icon-img" src="{{appIcon}}"></image>
<div class="image-box" focusable = "true">
<image class="app-icon-img" src="{{appIcon}}" focusable = "true"></image>
</div>

View File

@ -13,10 +13,12 @@
* limitations under the License.
*/
import ResourceManager from '../../model/ResourceManager.js';
var mResourceManager;
let mResourceManager;
let mDefaultAppIcon;
/**
* A page element that display app icon.
*/
export default {
props: ['itemAppId', 'itemAppIcon', 'itemBundleName'],
@ -30,23 +32,35 @@ export default {
onInit() {
this.$watch('itemBundleName','appIconWatcher');
mResourceManager = new ResourceManager();
mResourceManager.getAppIcon(this.itemAppIcon, this.itemBundleName, this.iconLoadCallback);
},
onShow() {
mDefaultAppIcon = globalThis.$globalR('image.icon_default');
mResourceManager = this.$app.$def.data.resourceManager;
mResourceManager.getAppIcon(this.itemAppIcon, this.itemBundleName, this.iconLoadCallback, mDefaultAppIcon);
},
/**
* Watch the value of appIcon, called when the value changed.
*
* @param {object} newV - New value of appIcon
* @param {object} oldV - Old value of appIcon
*/
appIconWatcher(newV, oldV) {
if (newV != null && newV != undefined) {
mResourceManager.getAppIcon(this.itemAppIcon, this.itemBundleName, this.iconLoadCallback);
}
},
/**
* Callback function when appIcon loaded from the resource manager.
*
* @param {string} image - App icon base64.
*/
iconLoadCallback(image) {
this.appIcon = image;
},
/**
* Reload the app icon base64 from resource manager.
*/
updateIcon() {
console.info("Launcher AppIcon updateIcon in bundleName = " + this.itemBundleName);
mResourceManager.getAppIcon(this.itemAppIcon, this.itemBundleName, this.iconLoadCallback);

View File

@ -17,8 +17,11 @@
.app-name {
text-align: center;
width: 110px;
height: 60px;
width: 100%;
height: 40px;
line-height: 27px;
color: white;
font-size: 27px;
max-lines: 1;
text-overflow: ellipsis;
}

View File

@ -13,10 +13,11 @@
* limitations under the License.
*/
import ResourceManager from '../../model/ResourceManager.js';
var mResourceManager;
let mResourceManager;
/**
* A page element that display app name in GridView.
*/
export default {
props: ['itemAppId', 'itemLabelId', 'itemBundleName', 'itemAppName'],
@ -30,26 +31,37 @@ export default {
},
onInit() {
this.$watch('itemBundleName','appIconWatcher');
mResourceManager = new ResourceManager();
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
this.$watch('itemBundleName','appNameWatcher');
mResourceManager = this.$app.$def.data.resourceManager;
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.appNameLoadCallback);
},
onShow() {
},
appIconWatcher(newV, oldV) {
/**
* Watch the value of appName, called when the value changed.
*
* @param {object} newV - New value of appName.
* @param {object} oldV - Old value of appName.
*/
appNameWatcher(newV, oldV) {
if (newV != null && newV != undefined) {
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.appNameLoadCallback);
}
},
iconLoadCallback(name) {
/**
* Callback function when appName loaded from the resource manager.
*
* @param {string} name - App name.
*/
appNameLoadCallback(name) {
this.appName = name;
},
/**
* Reload the app name from resource manager.
*/
updateName() {
console.info("Launcher AppIcon updateIcon in bundleName = " + this.itemBundleName);
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
console.info("Launcher GridName updateName in bundleName = " + this.itemBundleName);
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.appNameLoadCallback);
}
}

View File

@ -13,10 +13,11 @@
* limitations under the License.
*/
import ResourceManager from '../../model/ResourceManager.js';
var mResourceManager;
let mResourceManager;
/**
* A page element that display app name in ListView.
*/
export default {
props: ['itemAppId', 'itemLabelId', 'itemBundleName', 'itemAppName'],
@ -30,26 +31,37 @@ export default {
},
onInit() {
this.$watch('itemBundleName','appIconWatcher');
mResourceManager = new ResourceManager();
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
this.$watch('itemBundleName','appNameWatcher');
mResourceManager = this.$app.$def.data.resourceManager;
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.appNameLoadCallback);
},
onShow() {
},
appIconWatcher(newV, oldV) {
/**
* Watch the value of appName, called when the value changed.
*
* @param {object} newV - New value of appName
* @param {object} oldV - Old value of appName
*/
appNameWatcher(newV, oldV) {
if (newV != null && newV != undefined) {
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.appNameLoadCallback);
}
},
iconLoadCallback(name) {
/**
* Callback function when appName loaded from the resource manager.
*
* @param {string} name - App name.
*/
appNameLoadCallback(name) {
this.appName = name;
},
/**
* Reload the app name from resource manager.
*/
updateName() {
console.info("Launcher AppIcon updateIcon in bundleName = " + this.itemBundleName);
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
console.info("Launcher AppName updateName in bundleName = " + this.itemBundleName);
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.appNameLoadCallback);
}
}

View File

@ -13,10 +13,14 @@
* limitations under the License.
*/
var DefaultLayoutConfig = {
/**
* Default configuration of page layout and recent.
*/
const DefaultLayoutConfig = {
DefaultAppPageStartConfig: 'Grid',
DefaultGridConfig: 0,
DefaultRecentProcessLimit: 6
DefaultGridConfig: 1,
DefaultRecentProcessLimit: 20,
DefaultRecentProcessLimitArray: [5,10,15,20],
}
export default DefaultLayoutConfig;

View File

@ -13,11 +13,31 @@
* limitations under the License.
*/
var GridLayoutConfigs = {
/**
* Configuration of different layouts.
*/
const GridLayoutConfigs = {
GridLayoutTable: [
{id:0, layout:'5X4', row:5, column:4},
{id:1, layout:'4X4', row:4, column:4},
{id:2, layout:'6X4', row:6, column:4},
{
id: 0,
layout: '4X4',
row: 4,
column: 4
},
{
id: 1,
layout: '5X4',
row: 5,
column: 4
},
{
id: 2,
layout: '6X4',
row: 6,
column: 4
},
]
}

View File

@ -13,7 +13,10 @@
* limitations under the License.
*/
var SystemApplication = {
/**
* Records the system app that will not be displayed in Launcher.
*/
const SystemApplication = {
SystemApplicationName: 'com.ohos.launcher,com.ohos.systemui'
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2021 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.
*/
/**
* Constants of events that will be registered to system.
*/
const EventConstants = {
EVENT_PACKAGE_ADDED : "usual.event.PACKAGE_ADDED",
EVENT_PACKAGE_CHANGED : "usual.event.PACKAGE_CHANGED",
EVENT_PACKAGE_REMOVED : "usual.event.PACKAGE_REMOVED"
}
export default EventConstants;

View File

@ -13,9 +13,12 @@
* limitations under the License.
*/
var LayoutContants = {
/**
* A Constant class includes layout type Strings.
*/
const LayoutConstants = {
Grid: "Grid",
List: "List"
}
export default LayoutContants;
export default LayoutConstants;

View File

@ -13,7 +13,10 @@
* limitations under the License.
*/
var PageData = {
/**
* Pages' uri that will be used as a param of RouterUtil.
*/
const PageData = {
GRID_APP_PAGE: 'pages/AppGridView/AppGridView',
LIST_APP_PAGE: 'pages/AppListView/AppListView'
}

View File

@ -22,17 +22,17 @@
justify-content: center;
}
.app-icon-img{
.app-icon-img {
border-radius: 20px;
width: 110px;
height: 110px;
}
.app-icon-img:active{
.app-icon-img:active {
width: 105px;
height: 105px;
}
.app-name{
.app-name {
color: black;
}

View File

@ -13,187 +13,336 @@
* limitations under the License.
*/
import bundle_mgr from '@ohos.bundle_mgr';
import feature_ability from '@ohos.feature_ability';
import BundleMgr from '@ohos.bundle';
import FeatureAbility from '@ohos.ability.featureability';
import Subscriber from '@ohos.commonevent';
import SystemApplication from '../../common/configs/SystemApplication.js';
import EventConstants from '../../common/constants/EventConstants.js';
import CheckEmptyUtils from '../../common/utils/CheckEmptyUtils.js';
var mBundleInfoList = [];
var mGridBootAppList = [];
const DEFAULT_ICON_URL = 'common/pics/icon_default.png';
var mAppUninstallListener = null;
var mAppInstallListeners = [];
var gridListCallback;
var systemApplicationName = SystemApplication.SystemApplicationName;
var mCommonEventSubscriber = null;
var mCommonEventSubscribeInfo = {
events: ["usual.event.PACKAGE_ADDED", "usual.event.PACKAGE_CHANGED", "usual.event.PACKAGE_REMOVED"]
const UNINSTALL_SUCCESS = "UNINSTALL_SUCCESS";
const UNINSTALL_FAILED = "UNINSTALL_FAILED";
const IF_GET_ABILITY = 1;
let mBundleInfoList = [];
let mAppListInstallListener = [];
let mAppListUninstallListener = [];
let mAppListChangeListener = [];
let installCallback;
let systemApplicationName = SystemApplication.SystemApplicationName;
let mCommonEventSubscriber = null;
let mCommonEventSubscribeInfo = {
events: [EventConstants.EVENT_PACKAGE_ADDED,
EventConstants.EVENT_PACKAGE_CHANGED,
EventConstants.EVENT_PACKAGE_REMOVED]
};
/**
* Model class, get data from system API.
*/
export default class AppModel {
/**
* Get app information list from system by @ohos.bundle
*
* @param {object} callback - callback from presenter
*/
getAppList(callback) {
mBundleInfoList = [];
console.info('Launcher getAppIcon getAppList');
bundle_mgr.getApplicationInfos().then((data) => {
console.info('Launcher getApplicationInfos >' + JSON.stringify(data));
for (var i = 0; i < data.length; i++) {
if (systemApplicationName.indexOf(data[i].bundleName) > -1) {
console.info('Launcher AppModel getAppIcon getAppList');
BundleMgr.getBundleInfos(IF_GET_ABILITY).then((data) => {
if (CheckEmptyUtils.isEmpty(data)) {
console.error("Launcher AppModel getAppList getBundleInfos ERROR");
}
console.info('Launcher AppModel getBundleInfos >' + JSON.stringify(data));
for (let i = 0; i < data.length; i++) {
if (systemApplicationName.indexOf(data[i].name) > -1) {
} else {
mBundleInfoList.push(
{
System: data[i].isSystemApp,
AppName: data[i].label,
AppId: data[i].name,
AppIcon: data[i].iconId,
bundleName: data[i].bundleName,
labelId: data[i].labelId,
System:data[i].appInfo.systemApp,
AppName: data[i].appInfo.label,
AppId: data[i].appId,
AppIcon: data[i].appInfo.iconId,
bundleName:data[i].name,
labelId :data[i].appInfo.labelId,
abilityName: data[i].abilityInfos[0].name,
}
)
}
}
};
let appArrayLength = mBundleInfoList.length;
for (let i = 0; i < appArrayLength; i++) {
var iconUrl = mBundleInfoList[i].AppIcon;
if (iconUrl == null || iconUrl == "" || iconUrl == "undefined") {
mBundleInfoList[i].AppIcon = DEFAULT_ICON_URL;
}
}
console.info('Launcher mBundleInfoList' + JSON.stringify(mBundleInfoList));
console.info('Launcher AppModel mBundleInfoList' + JSON.stringify(mBundleInfoList));
callback(mBundleInfoList);
});
}
installApp() {
}
uninstallApp(appId, callback) {
console.info('Launcher uninstallApp appId' + appId);
var result = bundle_mgr.uninstall(appId).then((data) => {
console.info("Launcher uninstall data [" + data + "]");
callback(true);
/**
* Uninstall app by @ohos.bundle.
*
* @param {string} uninstallBundleName - bundleName of the bundle that will be uninstall
* @param {object} callback - callback from presenter
*/
uninstallApp(uninstallBundleName, callback) {
console.info('Launcher AppModel uninstallApp appId' + uninstallBundleName);
installCallback = callback;
let result = BundleMgr.getBundleInstaller().then((data) => {
if (CheckEmptyUtils.isEmpty(data)) {
console.error("Launcher AppModel uninstallApp getBundleInstaller ERROR");
}
data.uninstall(uninstallBundleName, {
param: {
userId: 0,
isKeepData: false
}
}, this.#OnReceiveinstallEvent);
}).catch(error =>
console.info("Launcher uninstall err " + error));
console.info("Launcher AppModel uninstall err " + error));
}
getGridBootAppList() {
return mGridBootAppList;
/**
* Callback method after uninstall.
*
* @param {object} data - uninstall result data
*/
#OnReceiveinstallEvent = (data) => {
console.info('Launcher AppModel OnReceiveinstallEvent ' + data);
if (data.statusMessage == "SUCCESS") {
installCallback(UNINSTALL_SUCCESS);
} else {
installCallback(UNINSTALL_FAILED);
}
console.info('Launcher AppModel OnReceiveinstallEvent ');
}
getGridPagesAppList(callback) {
gridListCallback = callback;
this.getAppList(this.getGridlist.bind(this));
}
getGridlist(list) {
gridListCallback(this.dealList(list));
}
dealList(appList) {
var gridPagesList = [];
var bootListLength = mGridBootAppList.length;
var appArrayLength = appList.length;
for (var i = 0; i < appArrayLength; i++) {
gridPagesList.push(appList[i]);
for (var j = 0; j < bootListLength; j++) {
if (appList[i].AppName === mGridBootAppList[j].AppName) {
gridPagesList.pop();
}
}
}
return gridPagesList;
}
openApplication(bundleName) {
this.getAbilityName(bundleName, this.startApplication)
}
getAbilityName(bundleName, callback) {
console.info('Launcher getAbilityName bundleName' + bundleName);
bundle_mgr.getBundleInfo(bundleName).then(data => {
console.info('Launcher getBundleInfo ' + data);
callback(data.abilityInfos[0].name, bundleName);
});
}
startApplication(abilityname, bundleName) {
/**
* Start app by bundle name and ability name.
*
* @param {string} abilityName - ability name of target app
* @param {string} bundleName - bundle name of target app
*/
startApplication(abilityName, bundleName) {
let paramBundleName = bundleName;
let paramAbilityname = abilityname;
let paramAbilityName = abilityName;
// promise
console.info('Launcher startApplication abilityname' + abilityname);
var result = feature_ability.startAbility({
bundleName: paramBundleName,
abilityName: paramAbilityname,
requestCode: 1,
abilityType: "PageAbility",
console.info('Launcher AppModel startApplication abilityName ==> ' + abilityName + " bundleName ==> " + bundleName);
let result = FeatureAbility.startAbility({
want: {
action: "action1",
entities: ["entity1"],
type: "PageAbility",
flags: 2,
elementName: {
deviceId: "deviceId",
bundleName: paramBundleName,
abilityName: paramAbilityname,
},
},
syncOption: 1,
abilityName: paramAbilityName
}
}).then(data =>
console.info("Launcher promise::then : " + JSON.stringify(data))
console.info("Launcher AppModel startApplication promise::then : " + JSON.stringify(data))
).catch(error =>
console.info("Launcher promise::catch : " + JSON.stringify(error))
console.info("Launcher AppModel startApplication promise::catch : " + JSON.stringify(error))
);
console.info("Launcher AceApplication : startAbility : " + result);
console.info("Launcher AppModel startApplication AceApplication : startAbility : " + result);
}
reportAppInstallEvent() {
console.info("Launcher AppModel reportAppInstallEvent");
for (let i = 0; i < mAppInstallListeners.length; i++) {
let listener = mAppInstallListeners[i];
/**
* Start app by bundle name and ability name with result.
*
* @param {string} abilityName - ability name of target app
* @param {string} bundleName - bundle name of target app
* @param {number} requestCode - result after start app
*/
startApplicationForResult(abilityName, bundleName, requestCode) {
let paramBundleName = bundleName;
let paramAbilityName = abilityName;
// promise
console.info('Launcher AppModel startApplicationForResult abilityName' + abilityName);
let result = FeatureAbility.startAbilityForResult({
want: {
bundleName: paramBundleName,
abilityName: paramAbilityName
},
requestCode: requestCode,
},
(err, data) => {
console.log("Launcher AppModel startAbilityForResult asyncCallback StartAbilityResult: "
+ err.code + " data: " + data)
}).then(data =>
console.info("Launcher AppModel startApplicationForResult promise::then : " + JSON.stringify(data))
).catch(error =>
console.info("Launcher AppModel startApplicationForResult promise::catch : " + JSON.stringify(error))
);
console.info("Launcher AppModel startApplicationForResult AceApplication : startAbility : " + result);
}
/**
* Dispatch event to corresponding listeners.
*
* @param {string} event: callback event
* @param {object} bundleInfo: data from callback
*/
#reportAppInstallEvent = (event, bundleInfo) => {
console.info("Launcher AppModel reportAppInstallEvent + " + event);
switch (event) {
case EventConstants.EVENT_PACKAGE_ADDED:
this.#notifyEventListener(mAppListInstallListener, bundleInfo);
break;
case EventConstants.EVENT_PACKAGE_CHANGED:
this.#notifyEventListener(mAppListChangeListener, bundleInfo);
break;
case EventConstants.EVENT_PACKAGE_REMOVED:
this.#notifyEventListener(mAppListUninstallListener, bundleInfo);
break;
default:
break;
}
}
/**
* Call the callback method which comes from presenter.
*
* @param {object} eventListener - different listeners for different event
* @param {object} bundleInfo - callback data
*/
#notifyEventListener = (eventListener, bundleInfo) => {
for (let i = 0; i < eventListener.length; i++) {
let listener = eventListener[i];
if (listener != undefined && listener != null) {
listener();
console.info("Launcher AppModel notifyEventListener " + JSON.stringify(bundleInfo));
listener(bundleInfo);
}
}
}
reportAppUninstallEvent(appId) {
if (mAppUninstallListener != null) {
mAppUninstallListener(appId);
/**
* Register install listener.
*
* @param {object} listener - install listener
*/
registerAppListInstallListener(listener) {
if (mAppListInstallListener.indexOf(listener) == -1) {
mAppListInstallListener.push(listener);
}
}
registerAppUninstallListener(listener) {
mAppUninstallListener = listener;
/**
* Unregister install listener.
*
* @param {object} listener - install listener
*/
unregisterAppListInstallListener(listener) {
let index = mAppListInstallListener.indexOf(listener);
if (index != -1) {
mAppListInstallListener.splice(index, 1);
}
}
registerAppInstallListener(listener) {
console.info("Launcher AppModel registerAppInstallListener");
if (mAppInstallListeners.indexOf(listener) == -1) {
mAppInstallListeners.push(listener);
/**
* Register uninstall listener.
*
* @param {object} listener - uninstall listener
*/
registerAppListUninstallListener(listener) {
if (mAppListUninstallListener.indexOf(listener) == -1) {
mAppListUninstallListener.push(listener);
}
}
/**
* Unregister uninstall listener.
*
* @param {object} listener - uninstall listener
*/
unregisterAppListUninstallListener(listener) {
let index = mAppListUninstallListener.indexOf(listener);
if (index != -1) {
mAppListUninstallListener.splice(index, 1);
}
}
/**
* Register change listener.
*
* @param {object} listener - uninstall listener
*/
registerAppListChangeListener(listener) {
if (mAppListChangeListener.indexOf(listener) == -1) {
mAppListChangeListener.push(listener);
}
}
/**
* Unregister change listener.
*
* @param {object} listener - change listener
*/
unregisterAppListChangeListener(listener) {
let index = mAppListChangeListener.indexOf(listener);
if (index != -1) {
mAppListChangeListener.splice(index, 1);
}
}
/**
* Called in app.js, create subscriber for app install/uninstall/update events.
*/
registerAppListEvent() {
Subscriber.createSubscriber(
mCommonEventSubscribeInfo,
this.createInstallationSubscriberCallBack.bind(this)
this.#createInstallationSubscriberCallBack.bind(this)
);
}
unregisterAppInstallListener(listener) {
/**
* Called in app.js, unregister app install/uninstall/update events.
*/
unregisterAppListEvent() {
Subscriber.unsubscribe(mCommonEventSubscriber, () => {
console.info("Launcher AppModel unsubscribe app install listener");
let index = mAppInstallListeners.indexOf(listener);
if (index != -1) {
mAppInstallListeners.splice(index, 1);
}
console.info("Launcher AppModel unregisterAppListEvent");
});
}
createInstallationSubscriberCallBack(err, data) {
/**
* Create subscriber for install/uninstall/update event
*
* @param {object} err - error message of callback
* @param {object} data - callback data
*/
#createInstallationSubscriberCallBack = (err, data) => {
console.info("Launcher AppModel createInstallationSubscriberCallBack");
mCommonEventSubscriber = data;
Subscriber.subscribe(mCommonEventSubscriber, this.installationSubscriberCallBack.bind(this));
Subscriber.subscribe(mCommonEventSubscriber, this.#installationSubscriberCallBack.bind(this));
}
installationSubscriberCallBack(err, data) {
console.info("Launcher AppModel installationSubscriberCallBack");
this.reportAppInstallEvent();
/**
* callback after install/uninstall/update events, reorganize callback data.
*
* @param {object} err - error returns from the caller
* @param {object} data - data returns from the caller
*/
#installationSubscriberCallBack = (err, data) => {
if (err.code == 0) {
if (CheckEmptyUtils.isEmpty(data)) {
console.error("Launcher AppModel installationSubscriberCallBack ERROR! data is empty");
}
console.info("Launcher AppModel installationSubscriberCallBack data = " + JSON.stringify(data));
let callbackData = data;
if (callbackData.event == EventConstants.EVENT_PACKAGE_REMOVED) {
this.#reportAppInstallEvent(callbackData.event, callbackData);
return;
}
BundleMgr.getBundleInfo(callbackData.bundleName, IF_GET_ABILITY).then(data => {
console.info('Launcher AppModel installation subscriber getBundleInfo ' + JSON.stringify(data));
let bundleInfo = {
System:data.appInfo.systemApp,
AppName: data.appInfo.label,
AppId: data.appId,
AppIcon: data.appInfo.iconId,
bundleName:data.name,
labelId :data.appInfo.labelId,
abilityName: data.abilityInfos[0].name,
};
this.#reportAppInstallEvent(callbackData.event, bundleInfo);
});
} else {
console.error("Launcher AppModel app list change failed --- err = " + JSON.stringify(err));
}
}
}

View File

@ -13,49 +13,144 @@
* limitations under the License.
*/
/**
* An abstract class contains methods that can store layout data.
*/
export default class ILayoutConfig {
constructor() {
}
/**
* Get the layout view type.
*
* @return {string} Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
getAppPageStartConfig() {
return this.loadAppPageStartConfig();
}
/**
* Set the layout view type.
*
* @param {string} type - Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
setAppPageStartConfig(type) {
this.saveAppPageStartConfig(type);
}
/**
* Get grid layout config id.
*
* @return {number} grid layout config id.
*/
getGridConfig() {
return this.loadGridConfig();
}
/**
* Set grid layout config id.
*
* @param {number} id - layout config id.
*/
setGridConfig(id) {
this.saveGridConfig(id);
}
/**
* Get recent process max limit.
*
* @return {number} recent process max limit.
*/
getRecentProcessLimit() {
return this.loadRecentProcessLimit();
}
/**
* Set recent process max limit.
*
* @param {number} num - Recent process max limit.
*/
setRecentProcessLimit(num) {
this.saveRecentProcessLimit(num);
}
/**
* Get layout information of grid view.
*
* @return {object} layout information.
*/
getGridLayoutInfo() {
return this.loadGridLayoutInfo();
}
/**
* Set layout information of grid view.
*/
setGridLayoutInfo(layoutInfo) {
this.saveGridLayoutInfo(layoutInfo);
}
/**
* Remove layout information of grid view.
*/
deleteGridLayoutInfo() {
this.removeGridLayoutInfo();
}
/**
* Should overridden by sub-classes , load the launcher layout view type.
*/
loadAppPageStartConfig() {
}
/**
* Should overridden by sub-classes , save the launcher layout view type.
*/
saveAppPageStartConfig(type) {
}
/**
* Should overridden by sub-classes , load the launcher grid view layout config id.
*/
loadGridConfig() {
}
/**
* Should overridden by sub-classes , save the launcher grid view layout config id.
*/
saveGridConfig(id) {
}
/**
* Should overridden by sub-classes , load the recent process max limit.
*/
loadRecentProcessLimit() {
}
/**
* Should overridden by sub-classes , save the recent process max limit.
*/
saveRecentProcessLimit(num) {
}
/**
* Should overridden by sub-classes , load the layout information of grid view.
*/
loadGridLayoutInfo() {
}
/**
* Should overridden by sub-classes , save the layout information of grid view.
*/
saveGridLayoutInfo(layoutInfo) {
}
/**
* Should overridden by sub-classes , remove layout information of grid view.
*/
removeGridLayoutInfo() {
}
}

View File

@ -15,6 +15,11 @@
import StorageLayoutConfig from './StorageLayoutConfig.js'
/**
* The factory function of producing the class to operate layout config.
*
* @return {object} The class to operate layout config.
*/
export function getLayoutConfig() {
return new StorageLayoutConfig();
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021 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.
*/
let mCallbacks = [];
/**
* A manager class support Multi-Mode input events.
*/
export default class MMIEventManager {
/**
* Register the multi mode event callback function.
*
* @param {object} callback - callback function to be registered.
*/
registerEventCallback(callback) {
mCallbacks.push(callback);
}
/**
* Unregister the multi mode event callback function.
*
* @param {object} callback - callback function to be unregistered.
*/
unregisterEventCallback(callback) {
for (let idx = 0; idx < mCallbacks.length; idx++) {
if (mCallbacks[idx] == callback) {
mCallbacks.splice(idx, 1);
break;
}
}
}
/**
* Called when the multi mode event occur.
*/
onMMIEvent() {
for (let callback of mCallbacks) {
if (callback != undefined) {
callback();
}
}
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 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.
*/
import MMIEventManager from './MMIEventManager.js';
let mMMIEventManager = new MMIEventManager();
/**
* A model class provide Multi-Mode input functionality.
*/
export default class MMIModel {
/**
* Register the multi mode event callback function.
*
* @param {object} callback - callback function to be registered.
*/
registerEventCallback(callback) {
mMMIEventManager.registerEventCallback(callback);
}
/**
* Unregister the multi mode event callback function.
*
* @param {object} callback - callback function to be unregistered.
*/
unregisterEventCallback(callback) {
mMMIEventManager.unregisterEventCallback(callback);
}
}

View File

@ -13,45 +13,109 @@
* limitations under the License.
*/
import resmgr from '@ohos.resmgr';
import Resmgr from '@ohos.resmgr';
import AppResourceCacheManager from '../cache/AppResourceCacheManager.js'
import CheckEmptyUtils from '../../common/utils/CheckEmptyUtils.js';
const DEFAULT_ICON_URL = 'common/pics/icon_default.png';
const KEY_ICON = "icon";
const KEY_NAME = "name";
/**
* A manager class provide app icon and name from cache or system API.
*/
export default class ResourceManager {
ResourceManager() {
#appResourceCacheManager;
constructor() {
this.#appResourceCacheManager = new AppResourceCacheManager();
}
getAppIcon(path, bundleName, callback) {
/**
* Get icon image of specific app.
*
* @param {string} path - path of target file
* @param {string} bundleName - bundle name of the app
* @param {object} callback - callback method
*/
getAppIcon(path, bundleName, callback, defaultAppIcon) {
if (path == null || path == undefined || path == "" || path <= 0) {
console.info('Launcher getAppIcon iconid > ' + DEFAULT_ICON_URL);
callback(DEFAULT_ICON_URL);
console.info('Launcher ResourceManager getAppIcon iconId > ' + defaultAppIcon);
callback(defaultAppIcon);
} else {
resmgr.getResourceManager(bundleName).then(item => {
console.info('Launcher getResourceManager data>' + item);
let iconBase64 = this.#appResourceCacheManager.getCache(bundleName, KEY_ICON);
if (iconBase64 == undefined || iconBase64 == null || iconBase64 == '') {
Resmgr.getResourceManager(bundleName).then(item => {
if (CheckEmptyUtils.isEmpty(item)) {
console.error("Launcher ResourceManager getAppIcon getResourceManager ERROR! item is empty");
}
console.info('Launcher ResourceManager getAppIcon data>' + item);
item.getMediaBase64(path, (error, value) => {
console.info('Launcher getMediaBase64 value>' + value);
console.info('Launcher ResourceManager getAppIcon getMediaBase64 value>' + value);
if (value != null) {
this.#appResourceCacheManager.setCache(bundleName, KEY_ICON, value);
callback(value);
}
});
}).catch(e => {
console.error("Launcher ResourceManager getAppIcon error ")
callback(defaultAppIcon);
});
} else {
callback(iconBase64);
}
}
}
/**
* Get app name of specific app.
*
* @param {string} labelId - label id of target app
* @param {string} bundleName - bundle name of the app
* @param {string} appName - app name
* @param {object} callback - callback method
*/
getAppName(labelId, bundleName, appName, callback) {
if (labelId == null || labelId == undefined || labelId == "" || labelId <= 0) {
console.info('Launcher getAppName callback ' + appName);
console.info('Launcher ResourceManager getAppName callback ' + appName);
callback(appName);
} else {
resmgr.getResourceManager(bundleName).then(item => {
console.info('Launcher getResourceManager labelId' + labelId);
let name = this.#appResourceCacheManager.getCache(bundleName, KEY_NAME);
if (name == undefined || name == null || name == '') {
Resmgr.getResourceManager(bundleName).then(item => {
console.info('Launcher ResourceManager getAppName getResourceManager labelId' + labelId);
item.getString(labelId, (error, value) => {
console.info('Launcher getString value>' + value);
if (CheckEmptyUtils.checkStrIsEmpty(value)) {
console.error("Launcher AppModel getAppName getString ERROR! value is empty");
}
console.info('Launcher ResourceManager getAppName getString value>' + value);
if (value != null) {
this.#appResourceCacheManager.setCache(bundleName, KEY_NAME, value);
callback(value);
}
});
}).catch(e => {
console.error("Launcher ResourceManager getAppName error ")
callback(appName);
});
} else {
callback(name);
}
}
}
/**
* Get app resource cache.
*
* @param {string} bundleName - bundleName of target file
* @param {string} key - key of the cache
*/
getAppResourceCache(bundleName, key) {
return this.#appResourceCacheManager.getCache(bundleName, key);
}
/**
* Clear resource cache
*/
clearCache() {
this.#appResourceCacheManager.clearCache();
}
}

View File

@ -15,38 +15,112 @@
import GridLayoutConfigs from '../../common/configs/GridLayoutConfigs.js';
import {getLayoutConfig} from './LayoutConfigManager.js';
import FileUtils from "../../common/utils/FileUtils.js"
var mLayoutConfig = getLayoutConfig();
var mGridConfig = 0;
var gridLayoutTable = GridLayoutConfigs.GridLayoutTable;
const defaultLayoutInfoFilePath = "/data/accounts/account_0/applications/com.ohos.launcher/com.ohos.launcher/assets/launcher/resources/rawfile/layoutInfo.json";
let mLayoutConfig = getLayoutConfig();
let mGridConfig = 0;
let mGridLayoutTable = GridLayoutConfigs.GridLayoutTable;
/**
* A class that manage configuration data of layout and recent task.
*/
export default class SettingsModel {
/**
* Get the grid view presetting collection of layout config information table.
*
* @return {object} Grid view presetting collection object.
*/
getGridLayoutTable() {
return gridLayoutTable;
return mGridLayoutTable;
}
/**
* Get default layout information of grid view.
*
* @return {object} Default layout information of grid view.
*/
getDefaultLayoutInfo() {
return FileUtils.readJsonFile(defaultLayoutInfoFilePath);
}
/**
* Get layout config of grid view.
*
* @return {object} Layout config of grid view.
*/
getGridConfig() {
mGridConfig = mLayoutConfig.getGridConfig();
return gridLayoutTable[mGridConfig];
return mGridLayoutTable[mGridConfig];
}
/**
* Set layout config id of grid view.
*
* @param {string} id - Layout config id of grid view.
*/
setGridConfig(id) {
mLayoutConfig.setGridConfig(id);
}
/**
* Get recent process max limit.
*
* @return {number} recent process max limit.
*/
getRecentProcessLimit() {
return mLayoutConfig.getRecentProcessLimit();
}
/**
* Set recent process max limit.
*
* @param {number} num - Recent process max limit.
*/
setRecentProcessLimit(num) {
mLayoutConfig.setRecentProcessLimit(num);
}
/**
* Get the layout view type.
*
* @return {string} Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
getAppPageStartConfig() {
return mLayoutConfig.getAppPageStartConfig();
}
/**
* Set the layout view type.
*
* @param {string} type - Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
setAppPageStartConfig(type) {
mLayoutConfig.setAppPageStartConfig(type);
}
/**
* Get layout information of grid view.
*
* @return {object} layout information.
*/
getLayoutInfo() {
return mLayoutConfig.getGridLayoutInfo();
}
/**
* Set layout information of grid view.
*/
setLayoutInfo(layoutInfo) {
mLayoutConfig.setGridLayoutInfo(layoutInfo);
}
/**
* Remove layout information of grid view.
*/
deleteLayoutInfo() {
mLayoutConfig.deleteGridLayoutInfo();
}
}

View File

@ -15,26 +15,42 @@
import ILayoutConfig from './ILayoutConfig.js';
import DefaultLayoutConfig from '../../common/configs/DefaultLayoutConfig.js';
import storage from '@ohos.data.storage';
import Storage from '@ohos.data.storage';
const APP_PAGE_START_CONFIG = 'AppStartPageType';
const GRID_CONFIG = "GridConfig";
const RECENT_PROCESS_LIMIT = "RecentProcessLimit";
const GRID_LAYOUT_INFO = "GridLayoutInfo";
const PREFERENCES_PATH = '/data/accounts/account_0/appdata/com.ohos.launcher/sharedPreference/LauncherPreference';
var mPreferences = storage.getStorageSync(PREFERENCES_PATH);
let mPreferences = Storage.getStorageSync(PREFERENCES_PATH);
/**
* A class that stores layout information.
* @extends ILayoutConfig
*/
export default class StorageLayoutConfig extends ILayoutConfig {
constructor() {
super();
}
/**
* Load the launcher layout view type.
*
* @return {string} Layout view type , should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
loadAppPageStartConfig() {
console.info('Launcher mPreferences get APP_PAGE_START_CONFIG');
var data = mPreferences.getSync(APP_PAGE_START_CONFIG, DefaultLayoutConfig.DefaultAppPageStartConfig);
let data = mPreferences.getSync(APP_PAGE_START_CONFIG, DefaultLayoutConfig.DefaultAppPageStartConfig);
console.info('Launcher mPreferences get' + data);
return data;
}
/**
* Save the launcher layout view type.
*
* @param {string} type - View type , should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
saveAppPageStartConfig(type) {
console.info('Launcher mPreferences put type' + type);
mPreferences.putSync(APP_PAGE_START_CONFIG, type);
@ -42,13 +58,23 @@ export default class StorageLayoutConfig extends ILayoutConfig {
console.info('Launcher mPreferences put type flush');
}
/**
* Load the launcher grid view layout config id.
*
* @return {number} id - Config id.
*/
loadGridConfig() {
console.info('Launcher mPreferences get GRID_CONFIG');
var data = mPreferences.getSync(GRID_CONFIG, DefaultLayoutConfig.DefaultGridConfig);
let data = mPreferences.getSync(GRID_CONFIG, DefaultLayoutConfig.DefaultGridConfig);
console.info('Launcher mPreferences get' + data);
return data;
}
/**
* Save the launcher grid view layout config id.
*
* @param {string} id - View type , should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
saveGridConfig(id) {
console.info('Launcher mPreferences put id' + id);
mPreferences.putSync(GRID_CONFIG, id);
@ -56,17 +82,64 @@ export default class StorageLayoutConfig extends ILayoutConfig {
console.info('Launcher mPreferences put id flush');
}
/**
* Load the recent process max limit.
*
* @return {number} Recent process max limit.
*/
loadRecentProcessLimit() {
console.info('Launcher mPreferences get');
var data = mPreferences.getSync(RECENT_PROCESS_LIMIT, DefaultLayoutConfig.DefaultRecentProcessLimit);
let data = mPreferences.getSync(RECENT_PROCESS_LIMIT, DefaultLayoutConfig.DefaultRecentProcessLimit);
console.info('Launcher mPreferences get' + data);
return data;
}
/**
* Save the recent process max limit.
*
* @param {number} num - Recent process max limit.
*/
saveRecentProcessLimit(num) {
console.info('Launcher mPreferences put num' + num);
mPreferences.putSync(RECENT_PROCESS_LIMIT, num);
mPreferences.flushSync();
console.info('Launcher mPreferences put num flush');
}
/**
* Load the layout information of grid view.
*
* @return {object} The layout information data.
*/
loadGridLayoutInfo() {
console.info('Launcher StorageLayoutConfig loadGridLayoutInfo start');
let data = mPreferences.getSync(GRID_LAYOUT_INFO, '');
console.info('Launcher StorageLayoutConfig loadGridLayoutInfo ' + data);
if(data == ''){
return [];
}else{
return JSON.parse(data);
}
}
/**
* Load the layout information of grid view.
*
* @return {object} The layout information data.
*/
saveGridLayoutInfo(layoutInfo) {
console.info('Launcher StorageLayoutConfig saveGridLayoutInfo start');
mPreferences.putSync(GRID_LAYOUT_INFO, JSON.stringify(layoutInfo));
mPreferences.flushSync();
console.info('Launcher StorageLayoutConfig saveGridLayoutInfo end');
}
/**
* Remove layout information of grid view in preferences.
*/
removeGridLayoutInfo() {
console.info('Launcher StorageLayoutConfig removeGridLayoutInfo start');
mPreferences.deleteSync(GRID_LAYOUT_INFO);
console.info('Launcher StorageLayoutConfig removeGridLayoutInfo start');
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 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.
*/
export default {
/**
* Whether the two arraies are equal.
*
* @param {array} arr1 - First array.
* @param {array} arr2 - Second array.
* @return {boolean} Verify result.
*/
arrayEqual(arr1, arr2) {
if (arr1 === arr2) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2021 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.
*/
export default {
/**
* Check obj is empty.
*
* @param {object} obj
* @return {boolean} true(empty)
*/
isEmpty(obj) {
return (typeof obj === 'undefined' || obj == null || obj === '');
},
/**
* Check str is empty.
*
* @param {string} str
* @return {boolean} true(empty)
*/
checkStrIsEmpty(str) {
return str.trim().length == 0;
},
/**
* Check array is empty.
*
* @param {Array}arr
* @return {boolean} true(empty)
*/
isEmptyArr(arr) {
return arr.length == 0;
}
}

View File

@ -0,0 +1,213 @@
/*
* Copyright (c) 2021 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.
*/
/**
* An util that provides io functionality between file and JSON object.
*/
import Fileio from '@ohos.fileio';
const writeFilePath = "/data/accounts/account_0/appdata/com.ohos.launcher/cache/";
const journalPath = "/data/accounts/account_0/appdata/com.ohos.launcher/cache/journal.txt";
const READ_DATA_SIZE = 4096;
export default {
/**
* Read Json file from disk by bundleName.
*
* @param {string} bundleName - bundleName of the target file
* @return {object} - read object from file
*/
readJsonObj(bundleName) {
console.info("Launcher FileUtil readJsonObj start execution");
let filePath = writeFilePath + bundleName + ".json";
return this.readJsonFile(filePath);
},
/**
* Read Json file from disk by file path.
*
* @param {string} path - path of the target file.
* @return {object} - read object from file
*/
readJsonFile(path) {
console.info("Launcher FileUtil readJsonFile start execution");
let readStreamSync = null;
try {
readStreamSync = Fileio.Stream.createStreamSync(path, "r");
let content = this.getContent(readStreamSync);
console.info("Launcher FileUtil readJsonFile finish execution" + content);
return JSON.parse(content);
} catch (e) {
console.info("Launcher FileUtil readJsonFile " + e);
} finally {
readStreamSync.closeSync();
}
},
/**
* Write Json object to a file.
*
* @param {object} jsonObj - target JSON object will be written
* @param {string} bundleName - use bundleName as target file name
*/
writeJsonObj(jsonObj, bundleName) {
console.info("Launcher FileUtil writeJsonObj start execution");
let filePath = writeFilePath + bundleName + ".json";
let content = JSON.stringify(jsonObj);
let writeStreamSync = null;
try {
writeStreamSync = Fileio.Stream.createStreamSync(filePath, "w+");
writeStreamSync.writeSync(content);
} catch (e) {
console.info("Launcher FileUtil writeJsonObj error: " + e);
} finally {
writeStreamSync.closeSync();
console.info("Launcher FileUtil writeJsonObj close sync");
}
},
/**
* Read String from disk by bundleName.
*
* @param {string} bundleName - bundleName as target file name
* @return {string} - read string from file
*/
readStringFromFile(bundleName) {
console.info("Launcher FileUtil readStringFromFile start execution");
let filePath = writeFilePath + bundleName + ".json";
try {
var readStreamSync = fileio.Stream.createStreamSync(filePath, "r");
let content = this.getContent(readStreamSync);
console.info("Launcher FileUtil readStringFromFile finish execution" + content);
return content;
} catch (e) {
console.info("Launcher FileUtil readStringFromFile " + e);
} finally {
readStreamSync.closeSync();
}
},
/**
* Write string to a file.
*
* @param {string} string - target string will be written to file
* @param {string} bundleName - bundleName as target file name
*/
writeStringToFile(string, bundleName) {
console.info("Launcher FileUtil writeStringToFile start execution");
let filePath = writeFilePath + bundleName + ".json";
try {
var writeStreamSync = fileio.Stream.createStreamSync(filePath, "w+");
writeStreamSync.writeSync(string);
} catch (e) {
console.info("Launcher FileUtil writeStringToFile error: " + e);
} finally {
writeStreamSync.closeSync();
console.info("Launcher FileUtil writeStringToFile close sync");
}
},
/**
* Record a key that maps the image as value.
*
* @param {string} content - the key maps the image file
*/
writeJournal(content) {
let writeStreamSync = null;
try {
console.info("Launcher FileUtil writeJournal start");
writeStreamSync = Fileio.Stream.createStreamSync(journalPath, "a+");
writeStreamSync.writeSync(content + "\n");
} catch (e) {
console.info("Launcher FileUtil writeJournal error: " + e);
} finally {
writeStreamSync.closeSync();
console.info("Launcher FileUtil writeJournal close sync");
}
},
/**
* Get the keys that map the images.
*
* @return {object} object read from file
*/
readJournal() {
console.info("Launcher FileUtil readJournal start execution");
let readStreamSync = null;
try {
readStreamSync = Fileio.Stream.createStreamSync(journalPath, "r");
return this.getContent(readStreamSync);
} catch (e) {
console.info("Launcher FileUtil readJournal error: " + e);
} finally {
readStreamSync.closeSync();
console.info("Launcher FileUtil readJournal closeSync");
}
},
/**
* Read JSON object from a file.
*
* @param {object} readStreamSync - stream of target file
* @return {object} - object read from file stream
*/
getContent(readStreamSync) {
console.info("Launcher FileUtil getContent start");
let bufArray = [];
let totalLength = 0;
let buf = new ArrayBuffer(READ_DATA_SIZE);
let len = readStreamSync.readSync(buf);
while (len != 0) {
console.info("Launcher FileUtil getContent FileIO reading " + len);
totalLength += len;
if (len < READ_DATA_SIZE) {
buf = buf.slice(0, len);
bufArray.push(buf);
break;
}
bufArray.push(buf);
buf = new ArrayBuffer(READ_DATA_SIZE);
len = readStreamSync.readSync(buf);
}
console.info("Launcher FileUtil getContent read finished " + totalLength);
let contentBuf = new Uint8Array(totalLength);
let offset = 0;
for (let bufArr of bufArray) {
console.info("Launcher FileUtil getContent collecting " + offset);
let uInt8Arr = new Uint8Array(bufArr);
contentBuf.set(uInt8Arr, offset);
offset += uInt8Arr.byteLength;
}
let content = String.fromCharCode.apply(null, new Uint8Array(contentBuf));
return content;
},
/**
* Remove file.
*
* @param {string} bundleName - bundleName as target file name
*/
removeFile(bundleName) {
try {
console.info("Launcher FileUtil removeFile")
//remove file,key : bundlename
Fileio.unlinkSync(writeFilePath + bundleName + ".json")
} catch (e) {
console.error("Launcher FileUtil removeFile delete has failed for " + e)
}
}
}

View File

@ -13,26 +13,54 @@
* limitations under the License.
*/
import router from '@system.router';
/**
* An util that encapsulates methods from @system.router.
*/
import Router from '@system.router';
var Router = function () {
let RouterUtil = function () {
return {
push: function (uri, papams) {
router.push({
/**
* Push the page into the Router stack.
*
* @param {string} uri - uri of the page
* @param {object} params - params while opening the page
*/
push: function (uri, params) {
Router.push({
uri: uri,
params: papams
params: params
})
}, replace: function (uri, papams) {
router.replace({
},
/**
* Replace original page to the current page.
*
* @param {string} uri - uri of the page
* @param {object} params - params while opening the page
*/
replace: function (uri, params) {
Router.replace({
uri: uri,
params: papams
params: params
})
}, back: function () {
router.back();
}, clear: function () {
router.clear();
},
/**
* Back to previous page and pop current page.
*/
back: function () {
Router.back();
},
/**
* Clear router stack.
*/
clear: function () {
Router.clear();
}
}
}();
export default Router;
export default RouterUtil;

View File

@ -13,6 +13,12 @@
"launcher_settings": "Launcher settings",
"uninstall_app": "Uninstall App",
"layout": "Layout",
"recent_tasks_settings": "Recent tasks settings"
"recent_tasks_settings": "Recent tasks settings",
"layout_style": "Layout style",
"launcher_layout": "Launcher layout",
"layout_grid": "grid",
"layout_list": "list",
"add_blank_page" : "Add blank page",
"delete_blank_page" : "delete blank page"
}
}

View File

@ -13,6 +13,12 @@
"launcher_settings": "桌面设置",
"uninstall_app": "应用卸载",
"layout": "布局",
"recent_tasks_settings": "最近任务设置"
"recent_tasks_settings": "最近任务数",
"layout_style": "布局样式",
"launcher_layout": "桌面布局",
"layout_grid": "网格",
"layout_list": "列表",
"add_blank_page" : "添加空白页",
"delete_blank_page" : "删除空白页"
}
}

View File

@ -16,47 +16,30 @@
@import '../../common/css/CommonPageStyle.css';
.container {
background-image: url("common/pics/img_wallpaper_default.jpg");
background-size: cover;
}
.body {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
.row {
justify-content: space-around;
height: 180px;
height: 170px;
width: 920px;
}
.app-box {
display: flex;
flex-direction: column;
align-items: center;
height: 170px;
width: 110px;
margin-top: 10px;
border-radius: 20px;
}
.image-box {
height: 110px;
width: 110px;
display: flex;
align-items: center;
justify-content: center;
}
.app-name {
text-align: center;
width: 110px;
height: 60px;
height: 40px;
color: white;
font-size: 27px;
}

View File

@ -18,15 +18,35 @@
<element src="../../common/component/AppIcon/AppIcon.hml" name="appicon"></element>
<element src="../../common/component/GridName/GridName.hml" name="appName"></element>
<div class="container" onlongpress="intoSetting()">
<swiper class="pageView" loop="false" index="{{ index }}" onchange="pageChange">
<div class="body" for="{{ appArray }}">
<div for="{{ $item }}" class="row">
<div for="{{ $item }}" style="visibility : {{ $item.visibility }};" class="app-box"
onclick="openApplication({{ $item.bundleName }})"
onlongpress="longPress({{ $item.AppId }},{{ $item.bundleName }},{{ $item.System }})">
<div class="container" style="background-image: {{ $r('image.img_wallpaper_default') }}" onlongpress="onPageLongPress" ontouchstart="touchStart" ontouchmove="touchMove"
ontouchend="touchEnd">
<swiper class="pageView" loop="false" index="{{ index }}" onchange="pageChange" disabled="{{ disabled }}">
<div class="body" for="{{ gridAppsInfos }}" style="display : flex; flex-direction : column;">
<div for="{{ (itmInx,itmVal) in $item }}" style="display : flex; flex-direction : column; position : absolute;
width : {{ itmVal.wPosition }} px; opacity : {{ itmVal.opacity }};
top : {{ itmVal.y }}; left : {{ itmVal.x }}; transform: scale({{ itmVal.scale }}, {{ itmVal.scale}});"
onclick="openApplication({{ itmVal.abilityName }}, {{ itmVal.bundleName }})" onlongpress="longPress({{ itmVal }},{{ itmInx }})" focusable="false" onfocus="focus({{$idx}},{{ itmInx }})"
onkey="onAppGridKeyEvent">
<appicon id="icon-{{ itmVal.bundleName }}" item-app-icon="{{ itmVal.AppIcon }}"
item-app-id="{{ itmVal.AppId }}" item-bundle-name="{{ itmVal.bundleName }}"
style="width : {{ itmVal.wPixel }} px; height : {{ itmVal.wPixel }} px; margin-left: {{ itmVal.marginPosition }} px;">
</appicon>
<appname id="name-{{ itmVal.bundleName }}" item-app-id="{{ itmVal.AppId }}"
item-label-id="{{ itmVal.labelId }}"
item-bundle-name="{{ itmVal.bundleName }}" item-app-name="{{ itmVal.AppName }}">
</appname>
</div>
</div>
</swiper>
<div class="systemApp">
<div class="app-box" for="{{ bottomBar }}" onclick="openApplication({{ $item.abilityName }}, {{ $item.bundleName }})"
onlongpress="longPress({{ $item }},{{ $idx }})" style="position : absolute;
width : {{ $item.wPosition }} px; opacity : {{ $item.opacity }};
left : {{ $item.x }}; transform: scale({{ $item.scale }}, {{ $item.scale}});"
focusable="false" onfocus="focus({{ BOTTOM_BAR_FOCUS_PAGE }},{{ $idx }})">
<appicon id="icon-{{ $item.bundleName }}" item-app-icon="{{ $item.AppIcon }}"
item-app-id="{{ $item.AppId }}" item-bundle-name="{{ $item.bundleName }}">
item-app-id="{{ $item.AppId }}" item-bundle-name="{{ $item.bundleName }}"
style="width : {{ $item.wPixel }} px; height : {{ $item.wPixel }} px; margin-left: {{ $item.marginPosition }} px;">
</appicon>
<appname id="name-{{ $item.bundleName }}" item-app-id="{{ $item.AppId }}"
item-label-id="{{ $item.labelId }}"
@ -34,30 +54,34 @@
</appname>
</div>
</div>
<div style="height : 30px;"></div>
<div style="display : {{ movingAppInfo.display }}; flex-direction : column; left : {{ movingAppInfo.left }} px;
top : {{ movingAppInfo.top }} px; position : absolute; height : {{ pageCoordinateData.cellHeight }} px;
width : {{ pageCoordinateData.cellWidth }} px;" if = 'disabled'>
<appicon id="icon-{{ selectedAppItem.bundleName }}" item-app-icon="{{ selectedAppItem.AppIcon }}"
item-app-id="{{ selectedAppItem.AppId }}" item-bundle-name="{{ selectedAppItem.bundleName }}"
style="width : {{ selectedAppItem.wPixel }} px; height : {{ selectedAppItem.wPixel }} px;">
</appicon>
</div>
</swiper>
<div class="systemApp">
<div class="app-box" for="{{ bottomBar }}" onclick="openApplication({{ $item.AppId }})">
<div class="image-box">
<image class="app-icon-img" src="{{ $item.AppIcon }}"></image>
</div>
<text class="app-name">
{{ $item.AppName }}
</text>
<dialog id="chooseDialog" class="dialog-main">
<div class="dialog-div">
<div class="inner-btn">
<button type="capsule" value="{{$t('strings.launcher_settings')}}" onclick="intoSetting"
class="btn-txt"></button>
<button type="capsule" value="{{chooseDialogRightBtnStr}}" onclick="addOrDeleteBlankPage"
class="btn-txt"></button>
</div>
</div>
</dialog>
<dialog id="simpleDialog" class="dialog-main" oncancel="cancelDialog">
<div class="dialog-div">
<div class="inner-txt">
<text class="txt">{{ $t('strings.do_you_want_to_uninstall_start') }}{{ uninstallAppName }}{{
$t('strings.do_you_want_to_uninstall_end') }}
<text class="txt">{{$t('strings.do_you_want_to_uninstall_start')}}{{$t('strings.do_you_want_to_uninstall_end')}}
</text>
</div>
<div class="inner-btn">
<button type="capsule" value="{{ $t('strings.cancel') }}" onclick="cancelSchedule"
<button type="capsule" value="{{$t('strings.cancel')}}" onclick="cancelSchedule"
class="btn-txt"></button>
<button type="capsule" value="{{ $t('strings.uninstall') }}" onclick="uninstallApplication"
<button type="capsule" value="{{$t('strings.uninstall')}}" onclick="uninstallApplication"
class="btn-txt"></button>
</div>
</div>

View File

@ -14,124 +14,607 @@
*/
import AppGridPresenter from '../../presenter/app/AppGridPresenter.js';
import prompt from '@system.prompt';
import LayoutConstants from '../../common/constants/LayoutConstants.js';
import CheckArray from '../../common/utils/CheckArray.js';
import Prompt from '@system.prompt';
var mAppGridPresenter;
const APP_INFO_REFRESH_DELAY = 500;
const UNINSTALL_SUCCESS = "UNINSTALL_SUCCESS";
const UNINSTALL_FAILED = "UNINSTALL_FAILED";
const UNINSTALL_PROHIBITED = "UNINSTALL_PROHIBITED";
const CELL_WIDTH_RATIO = 0.65;
const COLUMN_SPACING_RATIO = 0.35;
const PROPORTION = 0.85;
const KEY_ICON = "icon";
const KEY_NAME = "name";
const BOTTOM_BAR = 1;
const NO_FOCUS_INDEX = [-1, -1];
const FOCUSED_ITEM_SCALE = 1.05;
const UNFOCUSED_ITEM_SCALE = 1;
const BOTTOM_BAR_FOCUS_PAGE = -1;
const KEY_CODE_CONFIRM_ON_TV_REMOTE = 23;
const KEY_CODE_CONFIRM_ON_KEYBOARD_ENTER = 66;
const KEY_CODE_CONFIRM_ON_NUMERIC_KEYBOARD_ENTER = 160;
const APP_NAME_HEIGHT = 40;
const POSITION_WIDTH_RATIO = 0.85;
let mAppGridPresenter;
let mAppListInfo = [];
let mGridConfig;
let mPageCoordinateData = {
numberOfRows: 0,
numberOfColumns: 0,
columnSpacing: 0,
rowSpacing: 0,
cellHeight: 0,
cellWidth: 0,
x_axis: [],
y_axis: [],
grid_x_axis: [],
grid_y_axis: [],
bottom_x_axis: [],
bottom_y_axis: []
};
let mTouchPointCoordinate = {
startX: 0,
startY: 0,
endX: 0,
endY: 0
};
let mPageCount;
let mScreenBottomBarTop = 0;
let mScreenHeight = 0;
let mScreenWidth = 0;
let mSelectedAppItem;
let mSelectedAppIndex = 0;
let mLongPress = false;
let mResourceManager;
let mDefaultAppIcon;
export default {
data: {
index: 0,
uninstallAppName: "",
uninstallAppId: "",
uninstallSystem: "",
appArray: [[[]]],
disabled: false,
isSwappingPage: false,
bottomBar: [],
pageCoordinateData: {},
gridAppsInfos: [],
chooseDialogRightBtnStr: "",
movingAppInfo: {
appIcon: mDefaultAppIcon,
appName: "APP",
display: "none",
top: 0,
left: 0
},
selectedAppItem: {},
focusItemIndex: NO_FOCUS_INDEX,
BOTTOM_BAR_FOCUS_PAGE: BOTTOM_BAR_FOCUS_PAGE
},
onInit() {
console.info("Launcher AppGridView onInit");
mAppGridPresenter = new AppGridPresenter(this.$app.$def.data.appModel, this.$app.$def.data.settingsModel);
mAppGridPresenter.registerAppUninstallListener(this.onAppUninstallCallback.bind(this));
mAppGridPresenter.registerAppInstallListener(this.onAppInstallCallback.bind(this));
globalThis.$globalR = this.$r.bind(this);
mResourceManager = this.$app.$def.data.resourceManager;
mAppGridPresenter = new AppGridPresenter(this.$app.$def.data.appModel, this.$app.$def.data.mmiModel,
this.$app.$def.data.settingsModel, this.$app.$def.data.appListInfoCacheManager);
mAppGridPresenter.registerAppListChangeCallback(this.getGridListCallback.bind(this));
mScreenHeight = this.$app.$def.data.screenHeight * PROPORTION;
mScreenWidth = this.$app.$def.data.screenWidth;
mScreenBottomBarTop = this.$app.$def.data.screenHeight * PROPORTION;
mDefaultAppIcon = globalThis.$globalR('image.icon_default');
},
onShow() {
console.info("Launcher AppGridView onShow");
mAppGridPresenter.clearRouter();
this.index = mAppGridPresenter.getGridIndex();
mAppGridPresenter.getGridList(this.getGridListCallback.bind(this));
this.bottomBar = mAppGridPresenter.getBootAppList();
},
onDestory() {
mAppGridPresenter.unregisterAppInstallListener(this.onAppInstallCallback.bind(this));
},
openApplication(bundleName) {
mAppGridPresenter.jumpTo(bundleName);
},
longPress(appId, appName, system) {
this.uninstallAppName = appName;
this.uninstallAppId = appId;
this.uninstallSystem = system;
if (system == 0) {
this.$element('simpleDialog').show()
} else{
prompt.showToast({
message: this.$t('strings.prohibited')
})
let isLayoutMigrate = mAppGridPresenter.layoutMigrate(LayoutConstants.Grid);
if (isLayoutMigrate) {
return;
}
let isLayoutConfigUpdated = mAppGridPresenter.updateLayoutConfig();
if (isLayoutConfigUpdated) {
this.loadData();
}
},
/**
* Load application data for grid layout.
*/
loadData() {
console.info("Launcher AppGridView loadData");
mGridConfig = mAppGridPresenter.getGridConfig();
this.pageCoordinateData = getPageCoordinateData();
mAppGridPresenter.getGridList(this.getGridListCallback.bind(this));
},
onDestroy() {
console.info("Launcher AppGridView onDestroy");
mAppGridPresenter.unregisterAppListChangeCallback();
},
/**
* Open the choosen application.
*
* @param {string} abilityName - Abilityname of the application.
* @param {string} bundleName - Bundlename of the application.
*/
openApplication(abilityName, bundleName) {
console.info("Launcher openApplication " + bundleName + " + " + abilityName);
mAppGridPresenter.jumpTo(abilityName, bundleName);
},
/**
* Jump to setting.
*/
intoSetting() {
console.info("Launcher AppGridView intoSetting");
this.$element('chooseDialog').close();
mAppGridPresenter.jumpToSetting();
},
/**
* Open uninstall dialog.
*
* @param {object} e - Event.
*/
cancelDialog(e) {
prompt.showToast({
Prompt.showToast({
message: 'Dialog cancelled'
})
},
/**
* Close uninstall dialog.
*
* @param {object} e - Event.
*/
cancelSchedule(e) {
this.$element('simpleDialog').close();
prompt.showToast({
Prompt.showToast({
message: this.$t('strings.cancelled')
})
},
/**
* Uninstall the choosen application and close the dialog.
*
* @param {object} e - Event.
*/
uninstallApplication(e) {
this.$element('simpleDialog').close()
mAppGridPresenter.uninstallApp(this.uninstallAppId);
prompt.showToast({
message: this.$t('strings.uninstall_succeeded')
})
this.$element('simpleDialog').close();
if (this.selectedAppItem.bundleName != null) {
mAppGridPresenter.uninstallApp(this.selectedAppItem.bundleName, this.selectedAppItem.System, this.getUninstallApp.bind(this));
}
},
/**
* Get the result after uninstall application.
*
* @param {object} callback - Uninstall result.
*/
getUninstallApp(callback) {
console.info("Launcher AppGridView getUninstallApp");
let success = callback;
if (success == UNINSTALL_PROHIBITED) {
Prompt.showToast({
message: this.$t('strings.prohibited')
});
} else if (success == UNINSTALL_SUCCESS) {
Prompt.showToast({
message: this.$t('strings.uninstall_succeeded')
});
mAppListInfo = [];
this.gridAppsInfos = [];
mAppGridPresenter.getGridList(this.getGridListCallback.bind(this));
} else if (success == UNINSTALL_FAILED) {
Prompt.showToast({
message: this.$t('strings.uninstall_failed')
});
}
},
/**
* Change index after swipe page.
*
* @param {object} e - Event.
*/
pageChange(e) {
this.index = e.index;
mAppGridPresenter.setGridIndex(e.index);
},
getGridListCallback(callbackDate) {
this.appArray = callbackDate;
console.info("Launcher AppGridView getGridListCallback this.appList.length = " + this.appArray.length);
},
onAppUninstallCallback(appId) {
mAppGridPresenter.getGridList(this.getGridListCallback.bind(this));
},
onAppInstallCallback(appId) {
console.info("Launcher AppGridView onAppInstallCallback start");
mAppGridPresenter.getGridList(this.applicationInstallCallback.bind(this));
/**
* Get grid applications' information and show them.
*
* @param {object} callbackData - Grid applications' information.
*/
getGridListCallback(callbackData) {
console.info("Launcher AppGridView getGridListCallback");
mAppListInfo = callbackData;
console.info("Launcher AppGridView getGridListCallback this.appList.length = " + mAppListInfo.length);
this.integrateData();
this.initFocus();
this.updateAppInfos();
},
/**
* Update applications' icon and name.
*/
updateAppInfos() {
setTimeout(() => {
console.info("Launcher AppGridView getGridListCallback setTimeout this.appList.length = " + this.appArray.length);
for (let i = 0; i < this.appArray.length; i++) {
let page = this.appArray[i];
console.info("Launcher AppGridView getGridListCallback setTimeout this.appList.length = " + this.gridAppsInfos.length);
for (let i = 0; i < this.gridAppsInfos.length; i++) {
let page = this.gridAppsInfos[i];
console.info("Launcher AppGridView getGridListCallback setTimeout page = " + i);
for (let j = 0; j < page.length; j++) {
let row = page[j];
console.info("Launcher AppGridView getGridListCallback setTimeout row = " + j);
for (let k = 0; k < row.length; k++) {
let element = row[k];
console.info("Launcher AppGridView getGridListCallback setTimeout in page = " + i + " row = " + j + " column = " + k);
let element = page[j];
this.$child('icon-' + element.bundleName).updateIcon();
this.$child('name-' + element.bundleName).updateName();
}
}
console.info("Launcher AppGridView updateAppInfos bottomBar.length = " + this.bottomBar.length);
for (let i = 0; i < this.bottomBar.length; i++) {
let element = this.bottomBar[i];
this.$child('icon-' + element.bundleName).updateIcon();
this.$child('name-' + element.bundleName).updateName();
}
}, APP_INFO_REFRESH_DELAY);
},
applicationInstallCallback(callbackData) {
this.appArray = callbackData;
console.info("Launcher AppGridView applicationIntallCallback this.appList.length = " + this.appArray.length);
/**
* LongPress event for application.
*
* @param {object} appItem - The pressed application.
* @param {number} index - The application's index in the page.
*/
longPress(appItem, index) {
console.info("Launcher AppGridView longPress index: " + index);
mSelectedAppItem = appItem;
this.selectedAppItem = appItem;
this.movingAppInfo.appIcon = mResourceManager.getAppResourceCache(this.selectedAppItem.bundleName, KEY_ICON);
this.movingAppInfo.appName = mResourceManager.getAppResourceCache(this.selectedAppItem.bundleName, KEY_NAME);
mSelectedAppIndex = index;
mLongPress = true;
this.disabled = true;
this.$element('simpleDialog').show();
},
/**
* Touchstart event for launcher.
*
* @param {object} e - Event.
*/
touchStart(e) {
console.info("Launcher AppGridView touchStart globalX = " + e.touches[0].globalX + " globalY = " + e.touches[0].globalY);
mTouchPointCoordinate.startX = e.touches[0].globalX,
mTouchPointCoordinate.startY = e.touches[0].globalY,
this.movingAppInfo.top = e.touches[0].globalY;
this.movingAppInfo.left = e.touches[0].globalX;
},
/**
* Touchmove event for launcher.
*
* @param {object} e - Event.
*/
touchMove(e) {
if(!mLongPress) {
return;
}
this.$element('simpleDialog').close();
this.movingAppInfo.display = 'flex';
if (this.selectedAppItem.bottomBarFlag == BOTTOM_BAR) {
this.bottomBar[mSelectedAppIndex].opacity = 0;
} else {
this.gridAppsInfos[mSelectedAppItem.page][mSelectedAppIndex].opacity = 0;
}
this.movingAppInfo.top = e.touches[0].globalY - mPageCoordinateData.cellWidth / 2;
this.movingAppInfo.left = e.touches[0].globalX - mPageCoordinateData.cellWidth / 2;
if (this.movingAppInfo.left < 0 && !this.isSwappingPage && this.index > 0 && this.movingAppInfo.top < mScreenHeight) {
this.index -= 1;
this.movingIconSwapPageDelay();
} else if (this.movingAppInfo.left + mPageCoordinateData.cellWidth > 720 && !this.isSwappingPage && this.movingAppInfo.top < mScreenHeight) {
if (this.index == mPageCount - 1) {
this.addBlankPage();
} else {
this.index += 1;
}
this.movingIconSwapPageDelay();
}
},
/**
* Touchend event for launcher.
*
* @param {object} e - Event.
*/
touchEnd(e) {
console.info("Launcher AppGridView touchEnd globalX = " + e.changedTouches[0].globalX + " globalY = " + e.changedTouches[0].globalY);
this.movingAppInfo.display = 'none';
mTouchPointCoordinate.endX = e.changedTouches[0].globalX;
mTouchPointCoordinate.endY = e.changedTouches[0].globalY;
let startColumn = 0, startRow = 0, startPage = this.index;
let endColumn = 0, endRow = 0;
let appInfo = mAppListInfo.find(item => {
return item.bundleName == mSelectedAppItem.bundleName;
});
if (appInfo != '' && appInfo != undefined && appInfo != null) {
startColumn = appInfo.column;
startRow = appInfo.row;
startPage = appInfo.page;
}
if (mTouchPointCoordinate.endY > mPageCoordinateData.bottom_y_axis[0]) {
endRow = -1;
} else {
for (let i = 0; i < mPageCoordinateData.numberOfRows; i++) {
if (mTouchPointCoordinate.endY < mPageCoordinateData.grid_y_axis[i]) {
endRow = i - 1;
break;
} else {
endRow = mPageCoordinateData.numberOfRows - 1;
}
}
}
for (let i = 0; i < mPageCoordinateData.numberOfColumns; i++) {
if (mTouchPointCoordinate.endX < mPageCoordinateData.grid_x_axis[i]) {
endColumn = i - 1;
break;
} else {
endColumn = mPageCoordinateData.numberOfColumns - 1;
}
}
if (mLongPress) {
let startInfo = {
page: startPage,
row: startRow,
column: startColumn
}
let endInfo = {
page: this.index,
row: endRow,
column: endColumn
}
mAppListInfo = mAppGridPresenter.layoutAdjustment(startInfo, endInfo);
this.integrateData();
this.initFocus();
this.updateAppInfos();
}
mLongPress = false;
this.disabled = false;
},
/**
* Integrate applications' information.
*/
integrateData() {
console.info("Launcher AppGridView integrateData");
mPageCount = mAppGridPresenter.getGridPageCount();
let pageMax = 0;
for (let i = 0;i < mAppListInfo.length; i++) {
if (pageMax < mAppListInfo[i].page) {
pageMax = mAppListInfo[i].page;
}
}
if (mPageCount < pageMax + 1) {
mPageCount = pageMax + 1;
}
let maxColumn = mGridConfig.column;
this.bottomBar = [];
let page = [];
for (let i = 0;i < mPageCount; i++) {
page.push([]);
}
this.gridAppsInfos = page;
for (let i = 0;i < mAppListInfo.length; i++) {
let iconInfo = {
AppId: mAppListInfo[i].AppId,
labelId: mAppListInfo[i].labelId,
AppName: mAppListInfo[i].AppName,
AppIcon: mAppListInfo[i].AppIcon,
bundleName: mAppListInfo[i].bundleName,
System: mAppListInfo[i].System,
abilityName: mAppListInfo[i].abilityName,
type: 0,
page: mAppListInfo[i].page,
wPixel: mPageCoordinateData.cellWidth,
hPixel: mPageCoordinateData.cellHeight,
wPosition: mPageCoordinateData.positionWidth,
marginPosition: mPageCoordinateData.positionMargin,
x: mPageCoordinateData.x_axis[mAppListInfo[i].column],
y: mPageCoordinateData.y_axis[mAppListInfo[i].row],
opacity: 1,
scale: 1,
bottomBarFlag:0
}
if (mAppListInfo[i].row == -1) {
if (this.bottomBar.length < maxColumn) {
iconInfo.y = mPageCoordinateData.bottom_y_axis[0];
iconInfo.bottomBarFlag = 1;
this.bottomBar.push(iconInfo);
}
continue;
}
this.gridAppsInfos[mAppListInfo[i].page].push(iconInfo);
}
},
/**
* Longpress event for launcher.
*/
onPageLongPress() {
this.chooseDialogRightBtnStr = this.getBlankPageBtnStr();
this.$element('chooseDialog').show();
},
/**
* Get strings for addBlankPageButton.
*
* @return {string} AddBlankPageButton Strings.
*/
getBlankPageBtnStr() {
return this.isBlankPage() ? this.$t('strings.delete_blank_page') : this.$t('strings.add_blank_page');
},
/**
* Detemine whether the page is empty.
*
* @return {boolean} Verify result.
*/
isBlankPage() {
return this.gridAppsInfos[this.index].length == 0;
},
/**
* Add or delete the choosen blank page.
*/
addOrDeleteBlankPage() {
this.$element('chooseDialog').close();
if (this.isBlankPage()) {
this.deleteBlankPage();
} else {
this.addBlankPage();
}
},
/**
* Add a blank page.
*/
addBlankPage() {
console.info("Launcher AppGridView addBlankPage");
mAppGridPresenter.setGridPageCount(mPageCount + 1);
this.integrateData();
this.initFocus();
this.index = mPageCount - 1;
},
/**
* Delete the choosen blank page.
*/
deleteBlankPage() {
console.info("Launcher AppGridView deleteBlankPage");
mAppGridPresenter.deleteGridPage(this.index);
if (this.index == this.gridAppsInfos.length - 1) {
this.index = this.index - 1;
}
mAppGridPresenter.setGridPageCount(mPageCount - 1);
mAppListInfo = mAppGridPresenter.getAppListInfo();
this.integrateData();
this.initFocus();
},
/**
* Delay when swap page with icon.
*/
movingIconSwapPageDelay() {
this.isSwappingPage = true;
setTimeout(() => {
this.isSwappingPage = false;
}, 1000);
},
/**
* Focus event for application icon.
*
* @param {number} page - The index of the page where the focused application is in.
* @param {number} idx - The index of the application in the page.
*/
focus(page, idx) {
if (!(CheckArray.arrayEqual(this.focusItemIndex, NO_FOCUS_INDEX))) {
this.gridAppsInfos[this.focusItemIndex[0]][this.focusItemIndex[1]].scale = UNFOCUSED_ITEM_SCALE;
}
this.focusItemIndex = [page, idx];
if (page == BOTTOM_BAR_FOCUS_PAGE) {
this.bottomBar[idx].scale = FOCUSED_ITEM_SCALE;
} else {
this.gridAppsInfos[page][idx].scale = FOCUSED_ITEM_SCALE;
}
},
/**
* Init the focus status.
*/
initFocus() {
if (!(CheckArray.arrayEqual(this.focusItemIndex, NO_FOCUS_INDEX))) {
if (this.focusItemIndex[0] != BOTTOM_BAR_FOCUS_PAGE) {
if (this.gridAppsInfos[this.focusItemIndex[0]][this.focusItemIndex[1]] != undefined) {
this.gridAppsInfos[this.focusItemIndex[0]][this.focusItemIndex[1]].scale = FOCUSED_ITEM_SCALE;
}
} else {
if (this.bottomBar[this.focusItemIndex[1]] != undefined) {
this.bottomBar[this.focusItemIndex[1]].scale = FOCUSED_ITEM_SCALE;
}
}
}
},
/**
* Key event of the application icon.
*
* @param {object} KeyEvent - Event.
*/
onAppGridKeyEvent(KeyEvent) {
console.info("Launcher AppGridView onAppGridKeyEvent KeyEvent: " + KeyEvent);
switch (KeyEvent.code) {
case KEY_CODE_CONFIRM_ON_TV_REMOTE:
case KEY_CODE_CONFIRM_ON_KEYBOARD_ENTER:
case KEY_CODE_CONFIRM_ON_NUMERIC_KEYBOARD_ENTER:
this.openApplication(mAppListInfo[this.focusItemIndex[0][this.focusItemIndex[1]]].bundleName);
break;
default:
break;
}
},
}
/**
* Calculate the coordinate.
*
* @return {object} Coordinate information.
*/
function getPageCoordinateData() {
let column = mGridConfig.column;
let row = mGridConfig.row;
mPageCoordinateData.numberOfColumns = column;
mPageCoordinateData.numberOfRows = row;
if ((mScreenWidth / column) < (mScreenHeight / row)) {
mPageCoordinateData.cellWidth = (mScreenWidth / column) * CELL_WIDTH_RATIO;
mPageCoordinateData.columnSpacing = ((mScreenWidth / column) * COLUMN_SPACING_RATIO) / 2;
mPageCoordinateData.cellHeight = mPageCoordinateData.cellWidth + APP_NAME_HEIGHT;
mPageCoordinateData.rowSpacing = (mScreenHeight - mPageCoordinateData.cellHeight * row) / (row * 2);
mPageCoordinateData.positionWidth = (mScreenWidth / column) * POSITION_WIDTH_RATIO;
mPageCoordinateData.positionMargin = (mPageCoordinateData.positionWidth - mPageCoordinateData.cellWidth) / 2;
} else {
mPageCoordinateData.cellWidth = (mScreenHeight / row) - APP_NAME_HEIGHT;
mPageCoordinateData.columnSpacing = (mScreenWidth - (mPageCoordinateData.cellWidth * column)) / (column * 2);
mPageCoordinateData.cellHeight = mScreenHeight / row;
mPageCoordinateData.rowSpacing = (mScreenHeight - (mPageCoordinateData.cellHeight * row)) / (row * 2);
mPageCoordinateData.positionWidth = (mScreenWidth / column) * POSITION_WIDTH_RATIO > mPageCoordinateData.cellWidth ? (mScreenWidth / column) * POSITION_WIDTH_RATIO : mPageCoordinateData.cellWidth;
mPageCoordinateData.positionMargin = (mPageCoordinateData.positionWidth - mPageCoordinateData.cellWidth) / 2;
}
mPageCoordinateData.x_axis = [],
mPageCoordinateData.y_axis = [],
mPageCoordinateData.grid_x_axis = [],
mPageCoordinateData.grid_y_axis = [],
mPageCoordinateData.bottom_x_axis = [],
mPageCoordinateData.bottom_y_axis = []
for (let i = 0; i < row; i++) {
let iconPositioningY = (i * 2 + 1) * mPageCoordinateData.rowSpacing + i * mPageCoordinateData.cellHeight;
let touchPositioningY = i * (mPageCoordinateData.rowSpacing * 2 + mPageCoordinateData.cellHeight);
mPageCoordinateData.y_axis.push(iconPositioningY);
mPageCoordinateData.grid_y_axis.push(touchPositioningY);
}
for (let i = 0; i < column; i++) {
let iconPositioningX = (i * 2 + 1) * mPageCoordinateData.columnSpacing + i * mPageCoordinateData.cellWidth - mPageCoordinateData.positionMargin;
let touchPositioningX = i * (mPageCoordinateData.columnSpacing * 2 + mPageCoordinateData.cellWidth);
mPageCoordinateData.x_axis.push(iconPositioningX);
mPageCoordinateData.grid_x_axis.push(touchPositioningX);
mPageCoordinateData.bottom_x_axis.push(iconPositioningX);
}
for (let i = 0; i < column; i++) {
mPageCoordinateData.bottom_y_axis.push(mScreenBottomBarTop);
}
return mPageCoordinateData;
}

View File

@ -16,7 +16,6 @@
@import '../../common/css/CommonPageStyle.css';
.container {
background-image: url("common/pics/img_wallpaper_default.jpg");
background-size: cover;
}
@ -34,6 +33,8 @@
}
.appitem {
background-color: #66123456;
border-radius: 20px;
height: 110px;
width: 90%;
display: flex;

View File

@ -18,12 +18,13 @@
<element src="../../common/component/AppIcon/AppIcon.hml" name="appicon"></element>
<element src="../../common/component/ListName/AppName.hml" name="appName"></element>
<div class="container">
<div class="container" style="background-image: {{ $r('image.img_wallpaper_default') }}">
<list class="list" onlongpress="toSetting">
<list-item class="list-item" for="{{ appList }}" focusable="true" onfocus="focus({{ $idx }})"
<list-item class="list-item" for="{{ appList }}" focusable="false" onfocus="focus({{ $idx }})"
onkey="onAppListKeyEvent"
onlongpress="longPress({{ $item.AppId }},{{ $item.bundleName }},{{ $item.System }})">
<div class="appitem" focusable="true" onclick="openApplication({{ $item.bundleName }})">
<div class="appitem" style="transform : scale({{ listItemScales[$idx] }}, {{ listItemScales[$idx] }});"
focusable="false" onclick="openApplication({{ $item.abilityName}}, {{ $item.bundleName }})">
<appicon id="icon{{ $idx }}" item-app-icon="{{ $item.AppIcon }}" item-app-id="{{ $item.AppId }}"
item-bundle-name="{{ $item.bundleName }}">
</appicon>

View File

@ -14,112 +14,226 @@
*/
import AppListPresenter from '../../presenter/app/AppListPresenter.js';
import prompt from '@system.prompt';
var mAppListPresenter;
import LayoutConstants from '../../common/constants/LayoutConstants.js';
import Prompt from '@system.prompt';
const NO_FOCUS_INDEX = -1;
const FOCUSED_ITEM_SCALE = 1.05;
const UNFOCUSED_ITEM_SCALE = 1;
const KEY_CODE_CONFIRM_ON_TV_REMOTE = 23;
const KEY_CODE_CONFIRM_ON_KEYBOARD_ENTER = 66;
const KEY_CODE_CONFIRM_ON_NUMERIC_KEYBOARD_ENTER = 160;
const UNINSTALL_SUCCESS = "UNINSTALL_SUCCESS";
const UNINSTALL_FAILED = "UNINSTALL_FAILED";
const UNINSTALL_PROHIBITED = "UNINSTALL_PROHIBITED";
const APP_INFO_REFRESH_DELAY = 500;
let mAppListPresenter;
export default {
data: {
appList: [],
uninstallAppId: null,
uninstallAppName: null,
uninstallBundleName: null,
ifSystem: true,
listItemScales: [],
focusItemIndex: NO_FOCUS_INDEX
},
onInit() {
mAppListPresenter = new AppListPresenter(this.$app.$def.data.appModel);
mAppListPresenter.registerAppUninstallListener(this.onAppUninstallCallback);
mAppListPresenter.registerAppInstallListener(this.onAppInstallCallback);
console.info("Launcher AppListView onInit");
globalThis.$globalR = this.$r.bind(this);
mAppListPresenter = new AppListPresenter(this.$app.$def.data.appModel, this.$app.$def.data.mmiModel,
this.$app.$def.data.settingsModel, this.$app.$def.data.appListInfoCacheManager);
mAppListPresenter.registerAppListChangeCallback(this.getListCallback.bind(this));
},
onShow() {
mAppListPresenter.clearRouter();
console.info("Launcher AppListView onShow");
let isLayoutMigrate = mAppListPresenter.layoutMigrate(LayoutConstants.List);
if (isLayoutMigrate) {
return;
}
mAppListPresenter.getAppList(this.getListCallback.bind(this));
},
onDestory() {
mAppListPresenter.unregisterAppInstallListener(this.onAppInstallCallback.bind(this));
onDestroy() {
console.info("Launcher AppListView onDestroy");
mAppListPresenter.unregisterAppListChangeCallback();
},
/**
* Callback function of get application list.
*
* @param {object} list - list of applications.
*/
getListCallback(list) {
if (list == undefined || list == null) {
this.appList = [];
return;
}
this.appList = list;
this.initListFocus();
this.updateAppInfos();
},
openApplication(bundleName) {
mAppListPresenter.jumpTo(bundleName);
/**
* Open application function.
*
* @param {string} abilityName - ability name of the application to be jump to.
* @param {string} bundleName - bundle name of the application to be jump to.
*/
openApplication(abilityName, bundleName) {
console.info("Launcher AppListView openApplication abilityName:" + abilityName);
mAppListPresenter.jumpTo(abilityName, bundleName);
},
/**
* Application list item long press function.
*
* @param {string} appId - appId of long pressed item.
* @param {string} bundleName - bundle name of long pressed item.
* @param {string} System - whether long pressed item is system app or not.
*/
longPress(appId, bundleName, System) {
console.info("Launcher AppListView longPress appId:" + appId);
this.uninstallAppId = appId;
this.uninstallAppName = bundleName;
this.uninstallBundleName = bundleName;
this.ifSystem = System;
this.$element('chooseDialog').show();
},
/**
* Migrate to launcher settings.
*/
toSetting() {
mAppListPresenter.jumpToSetting();
},
/**
* Choose uninstall button when long pressed dialog showed.
*/
chooseUninstall() {
this.$element('simpleDialog').show();
},
/**
* Choose launcher settings button when long pressed dialog showed.
*/
chooseSettings() {
this.$element('chooseDialog').close();
mAppListPresenter.jumpToSetting();
},
/**
* Cancel dialog when long pressed dialog showed.
*
* @param {object} e
*/
cancelDialog(e) {
this.$element('chooseDialog').close();
prompt.showToast({
Prompt.showToast({
message: 'Dialog cancelled'
})
},
/**
* Called when uninstall dialog canceled.
*
* @param {object} e
*/
cancelSchedule(e) {
this.$element('chooseDialog').close();
this.$element('simpleDialog').close();
prompt.showToast({
Prompt.showToast({
message: this.$t('strings.cancelled')
})
},
/**
* Called when uninstall dialog's uninstall dialog button clicked.
*
* @param {object} e
*/
uninstallApplication(e) {
this.$element('chooseDialog').close();
this.$element('simpleDialog').close();
if (this.uninstallAppName != null) {
mAppListPresenter.uninstallApp(this.uninstallAppName,this.ifSystem,this.getUninstallApp.bind(this));
if (this.uninstallBundleName != null) {
mAppListPresenter.uninstallApp(this.uninstallBundleName, this.ifSystem, this.getUninstallApp.bind(this));
}
},
getUninstallApp(callback) {
var success = callback;
if (!success) {
prompt.showToast({
/**
* Callback function of uninstall application.
*
* @param {string} uninstallationResult - the result of uninstallation.
*/
getUninstallApp(uninstallationResult) {
console.info("Launcher AppListView getUninstallApp uninstallationResult:" + uninstallationResult);
if (uninstallationResult == UNINSTALL_PROHIBITED) {
Prompt.showToast({
message: this.$t('strings.prohibited')
})
} else if (success) {
prompt.showToast({
} else if (uninstallationResult == UNINSTALL_SUCCESS) {
Prompt.showToast({
message: this.$t('strings.uninstall_succeeded')
})
});
this.appList = [];
mAppListPresenter.getAppList(this.getListCallback.bind(this));
} else if (uninstallationResult == UNINSTALL_FAILED) {
Prompt.showToast({
message: this.$t('strings.uninstall_failed')
});
}
},
onAppUninstallCallback(appId) {
/**
* Function called when list item focus changed.
*
* @param {string} idx - the index of list item to be focused.
*/
focus(idx) {
if (this.focusItemIndex != NO_FOCUS_INDEX) {
this.listItemScales.splice(this.focusItemIndex, 1, UNFOCUSED_ITEM_SCALE);
}
this.focusItemIndex = idx;
this.listItemScales.splice(idx, 1, FOCUSED_ITEM_SCALE);
},
onAppInstallCallback(appId) {
console.info("Launcher AppListView onAppInstallCallback start");
mAppListPresenter.getAppList(this.applicationInstallCallback.bind(this));
console.info("Launcher AppListView onAppInstallCallback end");
/**
* Function called when key event on list item changed.
*
* @param {object} KeyEvent - key event object.
*/
onAppListKeyEvent(KeyEvent) {
console.info("Launcher AppListView onAppListKeyEvent KeyEvent:" + KeyEvent);
switch (KeyEvent.code) {
case KEY_CODE_CONFIRM_ON_TV_REMOTE:
case KEY_CODE_CONFIRM_ON_KEYBOARD_ENTER:
case KEY_CODE_CONFIRM_ON_NUMERIC_KEYBOARD_ENTER:
this.openApplication(this.appList[this.focusItemIndex].bundleName,
this.appList[this.focusItemIndex].abilityName);
break;
default:
break;
}
},
/**
* Initial list focus status.
*/
initListFocus() {
for (let i = 0; i < this.appList.length; i++) {
this.listItemScales.push(UNFOCUSED_ITEM_SCALE);
}
if (this.focusItemIndex != NO_FOCUS_INDEX) {
this.listItemScales[this.focusItemIndex] = FOCUSED_ITEM_SCALE;
}
},
/**
* Update application icon and name when application data changed.
*/
updateAppInfos() {
console.info("Launcher AppListView getListCallback setTimeout this.appList.length = " + this.appList.length);
setTimeout(() => {
@ -130,15 +244,4 @@ export default {
}
}, APP_INFO_REFRESH_DELAY);
},
applicationInstallCallback(list) {
console.info("Launcher AppListView applicationInstallCallback in ");
if (list == undefined || list == null) {
this.appList = [];
return;
}
this.appList = list;
this.initListFocus();
this.updateAppInfos();
}
}

View File

@ -14,7 +14,6 @@
*/
.container {
background-image: url("common/pics/img_wallpaper_default.jpg");
background-size: cover;
display: flex;
flex-direction: column;

View File

@ -15,6 +15,6 @@
*/
-->
<div class="container">
<div class="container" style="background-image: {{ $r('image.img_wallpaper_default') }}">
<text>{{$t('strings.loading')}}</text>
</div>

View File

@ -14,10 +14,12 @@
*/
import EntryPresenter from '../../presenter/entry/EntryPresenter.js'
import Device from '@system.device';
var mEntryPresenter;
const timeout = 1000;
let mEntryPresenter;
export default {
onInit() {
console.info("Launcher EntryView onInit start");
@ -26,13 +28,27 @@ export default {
},
onShow() {
Device.getInfo({
success: (data) => {
this.$app.$def.data.screenHeight = data.windowHeight;
this.$app.$def.data.screenWidth = data.windowWidth;
setTimeout(() => {
console.info("Launcher EntryView onShow start");
mEntryPresenter.startAppListView();
console.info("Launcher EntryView onShow end");
}, timeout);
},
fun(){}
fail: (data, code) => {
console.info('Launcher Failed to obtain Device information. Error code:'+ code + '; Error information: ' + data);
//Fake data
this.$app.$def.data.screenHeight = 1240;
this.$app.$def.data.screenWidth = 720;
setTimeout(() => {
console.info("Launcher EntryView onShow start");
mEntryPresenter.startAppListView();
console.info("Launcher EntryView onShow end");
}, timeout);
}
})
},
}

View File

@ -1,119 +0,0 @@
/*
* Copyright (c) 2021 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.
*/
.container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
background-color: white;
}
.top-bar {
top:0;
height: 100px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: #F0EEEE;
}
.settings-box {
height: 100%;
width: 90%;
}
text {
font-size: 40px;
}
list {
height: 100%;
width: 100%;
background-color: white;
}
.list-bar {
background-color: white;
border-bottom-width: 3px;
border-color: black;
}
list-item {
height: 100px;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.item-box {
width: 95%;
height: 100%;
border-bottom-width: 3px;
border-color: #ACABAB;
display: flex;
flex-direction: row;
align-items: center;
justify-content:space-around;
}
.layout, .recentProcessLimit {
width: 70%;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
}
.switch, .select {
width: 30%;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.over {
height: 100px;
width: 70%;
background-color: #BE008000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 20px;
}
.over:active {
background-color: green;
}
.layoutButton {
background-color: green;
height: 50%;
width: 15%;
border-radius: 30px;
border-color: #A0A0A0;
border-width: 2px;
margin:3px ;
display: flex;
align-items: center;
justify-content: center;
}

View File

@ -1,88 +0,0 @@
<!--
/*
* Copyright (c) 2021 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.
*/
-->
<div class="container">
<div class = "top-bar">
<text>
{{$t('strings.settings')}}
</text>
</div>
<div class = "settings-box">
<list>
<list-item-group>
<list-item class= "list-bar">
<text>
{{$t('strings.layout')}}
</text>
</list-item>
<list-item>
<div class="item-box">
<div class = "layout">
<text>
{{layout}}
</text>
</div>
<div class = "switch">
<switch checked = "{{checked}}" onchange="changeSwitch"></switch>
</div>
</div>
</list-item>
<list-item if = '{{!checked}}'>
<div class="item-box">
<div for = "{{gridLayoutTable}}" onclick="changeLayout({{$item.id}})" class = "layoutButton" style="background-color: {{layoutButtonStyle[$item.id].color}};">
<text style="font-size: 30px; color:{{layoutButtonStyle[$item.id].fontColor}}" >{{$item.layout}}</text>
</div>
</div>
</list-item>
</list-item-group>
<list-item-group>
<list-item class= "list-bar">
<text>
{{$t('strings.recent_tasks_settings')}}
</text>
</list-item>
<list-item>
<div class="item-box" >
<div class = "recentProcessLimit">
<text>
{{recentProcessLimit}}
</text>
</div>
<div class = "select">
<select onchange="changeSelect" focusable="true">
<option value= "2">2</option>
<option value= "3">3</option>
<option value= "4">4</option>
<option value= "5">5</option>
<option value= "6">6</option>
<option value= "7">7</option>
<option value= "8">8</option>
<option value= "9">9</option>
<option value= "10">10</option>
</select>
</div>
</div>
</list-item>
</list-item-group>
</list>
</div>
<div class = "over" onclick="submit">
<text>
{{$t('strings.carry_out')}}
</text>
</div>
</div>

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2021 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.
*/
import SettingsPresenter from '../../presenter/settings/SettingsPresenter.js';
import Colors from '../../common/colors/Colors.js'
import LayoutConstants from '../../common/constants/LayoutConstants.js'
var mSettingsPresenter;
var mGridConfig;
export default {
data: {
layout: "",
checked: false,
layoutButtonStyle: [],
gridLayoutTable: [],
recentProcessLimit: ''
},
onInit() {
mSettingsPresenter = new SettingsPresenter(this.$app.$def.data.settingsModel);
mGridConfig = mSettingsPresenter.getGridConfig();
this.gridLayoutTable = mSettingsPresenter.getGridLayoutTable()
this.recentProcessLimit = mSettingsPresenter.getRecentProcessLimit();
for (let i = 0; i < this.gridLayoutTable.length; i++) {
this.layoutButtonStyle.push({
color: "",
fontColor: ""
});
}
},
onShow() {
this.layout = mSettingsPresenter.getAppPageStartConfig();
if (this.layout == LayoutConstants.Grid) {
this.checked = false;
this.layout = LayoutConstants.Grid;
} else {
this.checked = true;
this.layout = LayoutConstants.List;
}
for (let i = 0; i < this.gridLayoutTable.length; i++) {
if (i == mGridConfig.id) {
this.layoutButtonStyle[i].color = Colors.bgSelectedColor;
this.layoutButtonStyle[i].fontColor = Colors.fontSelectedColor;
} else {
this.layoutButtonStyle[i].color = Colors.bgUnselectedColor;
this.layoutButtonStyle[i].fontColor = Colors.fontUnselectedColor;
}
}
},
changeSwitch() {
if (this.checked) {
this.checked = false;
this.layout = LayoutConstants.Grid;
} else {
this.checked = true;
this.layout = LayoutConstants.List;
}
},
changeSelect(selected) {
this.recentProcessLimit = Number(selected.newValue)
mSettingsPresenter.setRecentProcessLimit(this.recentProcessLimit);
},
submit() {
mSettingsPresenter.setAppPageStartConfig(this.layout);
mSettingsPresenter.settingUpdate();
mSettingsPresenter.setRecentProcessLimit(this.recentProcessLimit);
},
changeLayout(id) {
for (let i = 0; i < this.gridLayoutTable.length; i++) {
if (i == id) {
this.layoutButtonStyle[i].color = Colors.bgSelectedColor;
this.layoutButtonStyle[i].fontColor = Colors.fontSelectedColor;
} else {
this.layoutButtonStyle[i].color = Colors.bgUnselectedColor;
this.layoutButtonStyle[i].fontColor = Colors.fontUnselectedColor;
}
}
mSettingsPresenter.setGridConfig(id);
}
}

View File

@ -15,82 +15,721 @@
import BaseAppPresenter from './base/BaseAppPresenter.js';
var mSettingsModel;
var mGridConfig;
var mAppGridList = [];
var viewCallback;
var mIndex = 0;
const KEY_APP_LIST = "appListInfo";
let mGridConfig;
let mViewCallback;
let mBundleInfoList;
let mSettingsModel;
/**
* Presenter of launcher grid view
*/
export default class AppGridPresenter extends BaseAppPresenter {
constructor(AppModel, SettingsModel) {
super(AppModel);
this.appModel = AppModel;
constructor(AppModel, MMIModel, SettingsModel, AppListInfoCacheManager) {
super(AppModel, MMIModel, SettingsModel, AppListInfoCacheManager);
mSettingsModel = SettingsModel;
mGridConfig = mSettingsModel.getGridConfig();
}
pagingFiltering(mblist) {
mAppGridList = [];
var listLength = mblist.length;
var column = mGridConfig.column;
var row = mGridConfig.row;
var page = Math.ceil(listLength / column / row);
for (var k = 0; k < page; k++) {
var appPageList = [];
for (var i = 0; i < row; i++) {
var appRowList = [];
for (var j = 0; j < column; j++) {
if ((i * column) + j + k * column * row >= listLength) {
var appInfo = {
System: false,
AppName: '',
AppId: '',
AppIcon: '',
bundleName: '',
labelId: '',
visibility: 'hidden'
};
appRowList.push(appInfo);
} else {
var tmp ={
System: mblist[(i * column) + j + k * column * row].System,
AppName: mblist[(i * column) + j + k * column * row].AppName,
AppId: mblist[(i * column) + j + k * column * row].AppId,
AppIcon: mblist[(i * column) + j + k * column * row].AppIcon,
bundleName: mblist[(i * column) + j + k * column * row].bundleName,
labelId: mblist[(i * column) + j + k * column * row].labelId,
visibility:'visible'
};
appRowList.push(tmp);
}
}
appPageList.push(appRowList);
}
mAppGridList.push(appPageList);
}
return mAppGridList;
/**
* Get application info list.
*
* @return {object} Application layout information.
*/
getAppListInfo() {
mBundleInfoList = this.appListInfoCacheManager.getCache(KEY_APP_LIST);
return this.#pagingFiltering();
}
/**
* Change the application position after move it.
*
* @param {object} startInfo - Starting position.
* @param {object} endInfo - Ending posiition.
* @return {object} Application layout information.
*/
layoutAdjustment(startInfo, endInfo) {
let info = mSettingsModel.getLayoutInfo();
let layoutInfo = info.layoutInfo;
mBundleInfoList = this.appListInfoCacheManager.getCache(KEY_APP_LIST);
if (endInfo.row == -1) {
this.#moveBottomLayout(startInfo, endInfo, layoutInfo);
info.layoutInfo = layoutInfo;
mSettingsModel.setLayoutInfo(info);
return this.#pagingFiltering();
}
this.#moveLayout(startInfo, endInfo, layoutInfo, startInfo);
info.layoutInfo = layoutInfo;
mSettingsModel.setLayoutInfo(info);
return this.#pagingFiltering();
}
/**
* Get application list for grid layout.
*
* @param {array} callback - Application list.
*/
getGridList(callback) {
viewCallback = callback;
this.appModel.getGridPagesAppList(this.getGridListCallback.bind(this));
mViewCallback = callback;
this.appModel.getAppList(this.getGridListCallback.bind(this));
}
/**
* Get application info list and intergrate them.
*
* @param {array} list - Callback data(application info list).
*/
getGridListCallback(list) {
let callbackList = this.pagingFiltering(list);
viewCallback(callbackList);
mBundleInfoList = list;
this.appListInfoCacheManager.setCache(KEY_APP_LIST, mBundleInfoList);
let callbackList = this.#pagingFiltering();
mViewCallback(callbackList);
}
getGridIndex() {
return mIndex;
/**
* Judge whether the current layout config and the setting layout config is consistent,and change the current layout config.
*
* @return {boolean} Verify result.
*/
updateLayoutConfig() {
let result = this.settingModel.getGridConfig();
if(mGridConfig == result) {
return false;
} else {
mGridConfig = result;
return true;
}
}
setGridIndex(index) {
mIndex = index
/**
* Get the current layout config.
*
* @return {object} Layout config information.
*/
getGridConfig() {
return mSettingsModel.getGridConfig();
}
getBootAppList() {
return this.appModel.getGridBootAppList();
/**
* Get pageCount.
*
* @return {number} PageCount.
*/
getGridPageCount() {
let layoutInfo = [];
layoutInfo = mSettingsModel.getLayoutInfo();
return layoutInfo.layoutDescription.pageCount;
}
/**
* Set pageCount.
*
* @param {number} pageCount - PageCount.
*/
setGridPageCount(pageCount) {
let layoutInfo = [];
layoutInfo = mSettingsModel.getLayoutInfo();
layoutInfo.layoutDescription.pageCount = pageCount;
mSettingsModel.setLayoutInfo(layoutInfo);
}
/**
* Delete blank page.
*
* @param {number} pageIndex - Index of the page which is to be deleted.
*/
deleteGridPage(pageIndex) {
let info = mSettingsModel.getLayoutInfo();
let layoutInfo = info.layoutInfo;
for (let element of layoutInfo) {
if (element.page > pageIndex) {
element.page = element.page - 1;
}
}
info.layoutInfo = layoutInfo;
mSettingsModel.setLayoutInfo(info);
}
/**
* Intergrate application list.
*
* @return {object} Application information list.
*/
#pagingFiltering = () => {
let appListInfo = [];
let info = this.#getLayoutInfo();
let layoutInfo = info.layoutInfo;
for (let i = 0;i < layoutInfo.length; i++) {
for (let j = 0; j < mBundleInfoList.length; j++) {
if (layoutInfo[i].bundleName == mBundleInfoList[j].bundleName) {
appListInfo.push(
{
System: mBundleInfoList[j].System,
AppName: mBundleInfoList[j].AppName,
AppId: mBundleInfoList[j].AppId,
AppIcon: mBundleInfoList[j].AppIcon,
bundleName: mBundleInfoList[j].bundleName,
labelId: mBundleInfoList[j].labelId,
abilityName: mBundleInfoList[j].abilityName,
type: 0,
area: layoutInfo[i].area,
page: layoutInfo[i].page,
row: layoutInfo[i].row,
column: layoutInfo[i].column
}
);
}
}
}
return appListInfo;
}
/**
* Verify whether the info is legal.
*
* @param {object} info - The info which is needed to be verify.
* @return {boolean} Verify result.
*/
#ifRationality = (info) => {
let column = mGridConfig.column;
let row = mGridConfig.row;
//verify whether the info is null.
if(this.#ifInfoIsNull(info)) {
return false;
}
let layoutDescription = info.layoutDescription;
//verify whether the layoutDescription is diffrent.
if(this.#ifDescriptionIsDiffrent(layoutDescription, row, column)) {
return false;
}
let layoutInfo = info.layoutInfo;
//verify whether the layoutInfo's row and column is more than standard.
if(this.#ifColumnOrRowAreBigger(layoutInfo, row, column)) {
return false;
}
//verify whether the bottomBar's position is duplicated.
if(this.#ifDuplicateBottomBarPosition(layoutInfo)) {
return false;
}
//verify whether the layoutInfo's position is duplicated.
if(this.#ifDuplicatePosition(layoutInfo)) {
return false;
}
//verify whether the layoutInfo's bundleName is duplicated.
if(this.#ifDuplicateBundleName(layoutInfo)) {
return false;
}
return true;
}
/**
* Verify whether the info is null.
*
* @param {object} info - The info which is needed to be verify.
* @return {boolean} Verify result.
*/
#ifInfoIsNull = (info) => {
if(info == undefined || info == '' || info == {} || info == null) {
return true;
}
return false;
}
/**
* Verify whether the layoutDescription is diffrent.
*
* @param {object} layoutDescription - The layoutDescription which is needed to be verify.
* @param {number} row - Standard row number.
* @param {number} column - Standard column number.
* @return {boolean} Verify result.
*/
#ifDescriptionIsDiffrent = (layoutDescription,row,column) => {
if(row != layoutDescription.row || column != layoutDescription.column) {
return true;
}
return false;
}
/**
* Verify whether the layoutInfo's row and column is more than standard.
*
* @param {object} layoutInfo - The layoutInfo which is needed to be verify.
* @param {number} row - Standard row number.
* @param {number} column - Standard column number.
* @return {boolean} Verify result.
*/
#ifColumnOrRowAreBigger = (layoutInfo, row, column) => {
for (let i = 0; i < layoutInfo.length; i++) {
//column or row are bigger than legal num
if (layoutInfo[i].column >= column || layoutInfo[i].row >= row) {
return true;
}
}
return false;
}
/**
* Verify whether the bottomBar's position is duplicated.
*
* @param {object} layoutInfo - The layoutInfo which is needed to be verify.
* @return {boolean} Verify result.
*/
#ifDuplicateBottomBarPosition = (layoutInfo) => {
for (let i = 0; i < layoutInfo.length; i++) {
if (layoutInfo[i].row < 0) {
for (let j = layoutInfo.length - 1; j > 0 && j > i; j--) {
if (i != j && layoutInfo[j].row < 0) {
if (layoutInfo[i].column == layoutInfo[j].column) {
return true;
}
}
}
}
}
return false;
}
/**
* Verify whether the layoutInfo's position is duplicated.
*
* @param {object} layoutInfo - The layoutInfo which is needed to be verify.
* @return {boolean} Verify result.
*/
#ifDuplicatePosition = (layoutInfo) => {
for (let i = 0; i < layoutInfo.length; i++) {
for (let j = layoutInfo.length - 1; j > 0 && j > i; j--) {
if (layoutInfo[i].row == layoutInfo[j].row && layoutInfo[i].column == layoutInfo[j].column) {
return true;
}
}
}
return false;
}
/**
* Verify whether the layoutInfo's bundleName is duplicated.
*
* @param {object} layoutInfo - The layoutInfo which is needed to be verify.
* @return {boolean} Verify result.
*/
#ifDuplicateBundleName = (layoutInfo) => {
let count = {};
for(let i = 0; i < layoutInfo.length; i++) {
if(count[layoutInfo[i].bundleName] == undefined || count[layoutInfo[i].bundleName] == null || count[layoutInfo[i].bundleName] == '') {
count[layoutInfo[i].bundleName] = 0;
}else{
if(++ count[layoutInfo[i].bundleName] > 1) {
return true;
}
}
}
return false;
}
/**
* Get the latest info position in the page.
*
* @param {object} layoutInfo - Layout information.
* @return {number} The latest information position number.
*/
#getExistNumber = (layoutInfo) => {
let column = mGridConfig.column;
let row = mGridConfig.row;
let existNumber = 0;
for(let i = 0; i < layoutInfo.length ;i++) {
let Page = layoutInfo[i].page;
let Row = layoutInfo[i].row;
let Column = layoutInfo[i].column;
let result = (Page * column * row) + (Row * column) + (Column + 1);
if(result > existNumber) {
existNumber = result;
}
}
return existNumber;
}
/**
* Update layout information.
*
* @param {object} info - The current layout information.
* @return {object} New layout information.
*/
#updateLayoutInfo = (info) => {
let layoutDescription = info.layoutDescription;
let layoutInfo = info.layoutInfo;
let column = mGridConfig.column;
let row = mGridConfig.row;
let newApp = [];
layoutDescription.row = row;
layoutDescription.column = column;
//Detect newly installed apps
for (let i in mBundleInfoList) {
let sign = false;
for (let j in layoutInfo) {
if (mBundleInfoList[i].bundleName == layoutInfo[j].bundleName) {
sign = true;
break;
}
}
if (!sign) {
newApp.push(mBundleInfoList[i]);
}
}
//Detect uninstalled apps
for (let i in layoutInfo) {
let sign = false;
for (let j in mBundleInfoList) {
if (layoutInfo[i].bundleName == mBundleInfoList[j].bundleName) {
sign = true;
break;
}
}
if (!sign) {
layoutInfo.splice(i, 1);
}
}
//The latest info position in the page
let existNumber = this.#getExistNumber(layoutInfo);
//Add new app
for (let i = 0; i < newApp.length; i++) {
layoutInfo.push({
bundleName: newApp[i].bundleName,
type: 0,
area: [1,1],
page: Math.floor((i + existNumber) / (column * row)),
row: Math.floor((i + existNumber) % (column * row) / column),
column: Math.floor((i + existNumber) % (column * row) % column),
});
}
info.layoutDescription = layoutDescription;
info.layoutInfo = layoutInfo;
return info;
}
/**
* Get the current layout information.
*
* @return {object} Layout information.
*/
#getLayoutInfo = () => {
let layoutInfo = [];
layoutInfo = mSettingsModel.getLayoutInfo();
let isLegal = this.#ifRationality(layoutInfo);
if (isLegal) {
layoutInfo = this.#updateLayoutInfo(layoutInfo);
} else if (this.#ifRationality(mSettingsModel.getDefaultLayoutInfo())) {
layoutInfo = this.#updateLayoutInfo(mSettingsModel.getDefaultLayoutInfo());
} else {
layoutInfo = this.#updateLayoutInfo(this.#createNewLayoutInfo());
}
mSettingsModel.setLayoutInfo(layoutInfo);
return layoutInfo;
}
/**
* Create a new layout information.
*
* @return {object} New layout information.
*/
#createNewLayoutInfo = () => {
let layoutInfo = mSettingsModel.getLayoutInfo();
let column = mGridConfig.column;
let row = mGridConfig.row;
let layoutNum = layoutInfo.layoutInfo.length;
let maxPerPage = column * row;
let pageNum = Math.ceil(layoutNum/maxPerPage);
let newLayoutInfo = {};
newLayoutInfo.layoutDescription = {
"pageCount" : pageNum,
"row" : row,
"column" : column,
}
newLayoutInfo.layoutInfo = [];
return newLayoutInfo;
}
/**
* Move application to bottomBar.
*/
#moveBottomLayout = (startInfo, endInfo, layoutInfo) => {
let column = mGridConfig.column;
let bottomBarLayoutInfo = [];
let moveItem = {
bundleName: "",
type: 0,
page: 0,
row: 0,
column: 0,
};
for (let i = layoutInfo.length - 1; i >= 0; i--) {
if (layoutInfo[i].page == startInfo.page && layoutInfo[i].row == startInfo.row && layoutInfo[i].column == startInfo.column) {
moveItem.bundleName = layoutInfo[i].bundleName;
moveItem.type = layoutInfo[i].type;
moveItem.page = layoutInfo[i].page;
moveItem.row = layoutInfo[i].row;
moveItem.column = layoutInfo[i].column;
layoutInfo.splice(i, 1);
}
}
for (let i = layoutInfo.length - 1; i >= 0; i--) {
if (layoutInfo[i].row == -1) {
bottomBarLayoutInfo.push(layoutInfo[i]);
layoutInfo.splice(i, 1);
}
}
if (bottomBarLayoutInfo.length >= column) {
this.#swapAppIcon(moveItem, endInfo, bottomBarLayoutInfo);
} else {
if (this.#isBottomEndPositionEmpty(endInfo, bottomBarLayoutInfo)) {
moveItem.page = endInfo.page;
moveItem.row = endInfo.row;
moveItem.column = endInfo.column;
} else {
if (this.#isBottomEmptyPositionAtForward(endInfo, bottomBarLayoutInfo)) {
this.#moveBottomLayoutForward(moveItem, endInfo, bottomBarLayoutInfo);
} else {
this.#moveBottomLayoutBackward(moveItem, endInfo, bottomBarLayoutInfo);
}
}
}
bottomBarLayoutInfo.push(moveItem);
for (let i = 0;i < bottomBarLayoutInfo.length; i++) {
layoutInfo.push(bottomBarLayoutInfo[i]);
}
}
/**
* Change position of the two application information.
*
* @param {object} moveItem - Started application information.
* @param {object} endInfo - Ended application information.
* @param {object} bottomBarLayoutInfo - BottomBar layout information.
*/
#swapAppIcon = (moveItem, endInfo, bottomBarLayoutInfo) => {
let tmp = {
page: 0,
row: 0,
column: 0
};
for (let i = 0;i < bottomBarLayoutInfo.length; i++) {
if (bottomBarLayoutInfo[i].row == endInfo.row && bottomBarLayoutInfo[i].column == endInfo.column) {
tmp.page = bottomBarLayoutInfo[i].page;
tmp.row = bottomBarLayoutInfo[i].row;
tmp.column = bottomBarLayoutInfo[i].column;
bottomBarLayoutInfo[i].page = moveItem.page;
bottomBarLayoutInfo[i].row = moveItem.row;
bottomBarLayoutInfo[i].column = moveItem.column;
moveItem.page = tmp.page;
moveItem.row = tmp.row;
moveItem.column = tmp.column;
}
}
}
/**
* Verify whether the moveEnd position is null while the moveEnd position is in bottomBar.
*
* @param {object} endInfo - MoveEnd position information.
* @param {object} bottomBarLayoutInfo - BottomBar layout information.
* @return {boolean} Verify result.
*/
#isBottomEndPositionEmpty = (endInfo, bottomBarLayoutInfo) => {
let isEndPositionEmpty = true;
for (let i = 0;i < bottomBarLayoutInfo.length; i++) {
if (bottomBarLayoutInfo[i].row == endInfo.row && bottomBarLayoutInfo[i].column == endInfo.column) {
isEndPositionEmpty = false;
break;
}
}
return isEndPositionEmpty;
}
/**
* Verify whether there is an empty position in front of the moveEnd position.
*
* @param {object} endInfo - MoveEnd position information.
* @param {object} bottomBarLayoutInfo - BottomBar layout information.
* @return {boolean} Verify result.
*/
#isBottomEmptyPositionAtForward = (endInfo, bottomBarLayoutInfo) => {
let isEmptyPositionAtForward = true;
for (let i = endInfo.column;i < mGridConfig.column; i++) {
isEmptyPositionAtForward = true;
for (let j = 0;j < bottomBarLayoutInfo.length; j++) {
if (bottomBarLayoutInfo[j].column == i) {
isEmptyPositionAtForward = false;
}
}
if (isEmptyPositionAtForward) {
break;
}
}
return isEmptyPositionAtForward;
}
/**
* The icons go forwards.
*
* @param {object} moveItem - The moving item.
* @param {object} endInfo - MoveEnd position information.
* @param {object} bottomBarLayoutInfo - BottomBar layout information.
*/
#moveBottomLayoutForward = (moveItem, endInfo, bottomBarLayoutInfo) => {
moveItem.page = endInfo.page;
moveItem.row = endInfo.row;
moveItem.column = endInfo.column;
let cTmp = [];
for (let j = 0;j < bottomBarLayoutInfo.length; j++) {
cTmp.push(bottomBarLayoutInfo[j].column);
}
for (let i = endInfo.column;i < mGridConfig.column; i++) {
let isColumnEmpty = true;
for (let j = 0;j < bottomBarLayoutInfo.length; j++) {
if (cTmp[j] == i) {
isColumnEmpty = false;
bottomBarLayoutInfo[j].column = cTmp[j] + 1;
}
}
if (isColumnEmpty) {
break;
}
}
}
/**
* The icons go backwards.
*
* @param {object} moveItem - Moving item information.
* @param {object} endInfo - MoveEnd position information.
* @param {object} bottomBarLayoutInfo - BottomBar layout information.
*/
#moveBottomLayoutBackward = (moveItem, endInfo, bottomBarLayoutInfo) => {
moveItem.page = endInfo.page;
moveItem.row = endInfo.row;
moveItem.column = endInfo.column;
let cTmp = [];
for (let j = 0;j < bottomBarLayoutInfo.length; j++) {
cTmp.push(bottomBarLayoutInfo[j].column);
}
for (let i = endInfo.column;i >= 0; i--) {
let isColumnEmpty = true;
for (let j = 0;j < bottomBarLayoutInfo.length; j++) {
if (cTmp[j] == i) {
isColumnEmpty = false;
bottomBarLayoutInfo[j].column = cTmp[j] - 1;
}
}
if (isColumnEmpty) {
break;
}
}
}
/**
* Move icon.
*
* @param {object} source - Start position information.
* @param {object} destination - End position information.
* @param {object} layoutInfo - Current layout information.
* @param {object} startInfo - Recursion start position information.
*/
#moveLayout = (source, destination, layoutInfo, startInfo) => {
let couldMoveForward = this.#moveLayoutForward(source, destination, layoutInfo, startInfo);
if (couldMoveForward) return;
this.#moveLayoutBackward(source, destination, layoutInfo, startInfo);
}
/**
* Icons go forwards.
*
* @param {object} source - Start position information.
* @param {object} destination - End position information.
* @param {object} layoutInfo - Current layout information.
* @param {object} startInfo - Recursion start position information.
* @return {boolean} Move result.
*/
#moveLayoutForward = (source, destination, layoutInfo, startInfo) => {
let startLayoutInfo = layoutInfo.find(item => {
return item.page == source.page && item.row == source.row && item.column == source.column;
});
let endLayoutInfo = layoutInfo.find(item => {
return item.page == destination.page && item.row == destination.row && item.column == destination.column;
});
if (endLayoutInfo != undefined && !(endLayoutInfo.page == startInfo.page && endLayoutInfo.row == startInfo.row && endLayoutInfo.column == startInfo.column)) {
if (endLayoutInfo.row == mGridConfig.row - 1 && endLayoutInfo.column == mGridConfig.column - 1) {
return false;
}
let nextPosition = {
page: destination.page,
row: destination.column == mGridConfig.column - 1 ? destination.row + 1 : destination.row,
column: destination.column == mGridConfig.column - 1 ? 0 : destination.column + 1
}
let couldMoveForward = this.#moveLayoutForward(destination, nextPosition, layoutInfo, startInfo);
if (!couldMoveForward) return false;
}
startLayoutInfo.page = destination.page;
startLayoutInfo.row = destination.row;
startLayoutInfo.column = destination.column;
return true;
}
/**
* Icons go backwards.
*
* @param {object} source - Start position information.
* @param {object} destination - End position information.
* @param {object} layoutInfo - Current layout information.
* @param {object} startInfo - Recursion start position information.
* @return {boolean} Move result.
*/
#moveLayoutBackward = (source, destination, layoutInfo, startInfo) => {
let startLayoutInfo = layoutInfo.find(item => {
return item.page == source.page && item.row == source.row && item.column == source.column;
});
let endLayoutInfo = layoutInfo.find(item => {
return item.page == destination.page && item.row == destination.row && item.column == destination.column;
});
if (endLayoutInfo != undefined && !(endLayoutInfo.page == startInfo.page && endLayoutInfo.row == startInfo.row && endLayoutInfo.column == startInfo.column)) {
if (endLayoutInfo.row == 0 && endLayoutInfo.column == 0) {
return false;
}
let nextPosition = {
page: destination.page,
row: (destination.column == 0 && destination.row > 0) ? destination.row - 1 : destination.row,
column: destination.column == 0 ? mGridConfig.column - 1 : destination.column - 1
}
let couldMoveBackward = this.#moveLayoutBackward(destination, nextPosition, layoutInfo, startInfo);
if (!couldMoveBackward) return false;
}
startLayoutInfo.page = destination.page;
startLayoutInfo.row = destination.row;
startLayoutInfo.column = destination.column;
return true;
}
/**
* Integrate layout information after install application.
*
* @return {object} Layout information.
*/
regroupDataAfterInstall(callbackList) {
mBundleInfoList = callbackList;
return this.#pagingFiltering();
}
}

View File

@ -15,8 +15,27 @@
import BaseAppPresenter from './base/BaseAppPresenter.js';
/**
* Presenter of launcher list view.
*
* @extends BaseAppPresenter.
*/
export default class AppListPresenter extends BaseAppPresenter {
constructor(AppModel) {
super(AppModel);
constructor(AppModel, MMIModel, SettingsModel, AppListInfoCacheManager) {
super(AppModel, MMIModel, SettingsModel, AppListInfoCacheManager);
}
/**
* Adapt bundleInfo data to in list view.
*
* @param {object} callbackList - BundleInfo list get from cache.
* @return {object} The regrouped list.
*/
regroupDataAfterInstall(callbackList) {
return callbackList.sort(
function compareFunction(param1, param2) {
return param1.AppName.localeCompare(param2.AppName, "zh");
}
);
}
}

View File

@ -14,70 +14,285 @@
*/
import RouterUtil from '../../../common/utils/RouterUtil.js';
import LayoutConstants from '../../../common/constants/LayoutConstants.js';
import PageData from '../../../common/constants/PageData.js';
const JUMPSETTING='pages/SettingsView/SettingsView';
var viewCallback;
var uninstallCallback;
const UNINSTALL_SUCCESS = true;
const UNINSTALL_PROHIBITED = "UNINSTALL_PROHIBITED";
const SETTING_BUNDLE = 'com.ohos.launcher';
const SETTING_ABILITY = 'com.ohos.launcher.settings.MainAbility';
const KEY_APP_LIST = "appListInfo";
let mViewCallback;
let mUninstallCallback;
let mAppListChangeCallback;
let mAppListInstallListener;
let mAppListUninstallListener;
let mAppListChangeListener;
/**
* Base class of list view presenter and grid view presenter.
*/
export default class BaseAppPresenter {
constructor(AppModel) {
constructor(AppModel, MMIModel, SettingsModel, AppListInfoCacheManager) {
this.appModel = AppModel;
this.mmiModel = MMIModel;
this.settingModel = SettingsModel;
this.appListInfoCacheManager =AppListInfoCacheManager;
mAppListInstallListener = this.appListInstallListener.bind(this);
mAppListUninstallListener = this.appListUninstallListener.bind(this);
mAppListChangeListener = this.appListChangeListener.bind(this);
}
/**
* Get app data function.
*
* @param {object} callback - callback function.
*/
getAppList(callback) {
viewCallback = callback;
mViewCallback = callback;
this.appModel.getAppList(this.getListCallback.bind(this));
}
/**
* Get app data callback function in BaseAppPresenter.
*
* @param {object} list - app data.
*/
getListCallback(list) {
let callbacklist = list.sort(
function compareFunction(param1, param2) {
return param1.AppName.localeCompare(param2.AppName, "zh");
}
);
viewCallback(callbacklist);
this.appListInfoCacheManager.setCache(KEY_APP_LIST, list);
mViewCallback(callbacklist);
}
uninstallApp(uninstallAppName, ifSystem, callback) {
uninstallCallback = callback;
if (ifSystem == true) {
callback(false);
/**
* Uninstall app.
*
* @param {string} uninstallBundleName - bundleName of the app to be uninstall.
* @param {boolean} ifSystem - whether the app is a system app or not.
* @param {object} callback - callback function of uninstall app.
*/
uninstallApp(uninstallBundleName, ifSystem, callback) {
mUninstallCallback = callback;
if (ifSystem == UNINSTALL_SUCCESS) {
callback(UNINSTALL_PROHIBITED);
} else {
this.appModel.uninstallApp(uninstallAppName, this.uninstallAppCallback.bind(this));
this.appModel.uninstallApp(uninstallBundleName, this.uninstallAppCallback.bind(this));
}
}
/**
* Uninstall app callback function in BaseAppPresenter.
*
* @param {object} callback - callback function of uninstall app.
*/
uninstallAppCallback(callback) {
uninstallCallback(callback);
mUninstallCallback(callback);
}
jumpTo(bundleName) {
this.appModel.openApplication(bundleName);
/**
* Jump to another application.
*
* @param {string} abilityName - ability name of the application to be jump to.
* @param {string} bundleName - bundle name of the application to be jump to.
*/
jumpTo(abilityName, bundleName) {
this.appModel.startApplication(abilityName, bundleName);
}
/**
* Jump to launcher settings module.
*/
jumpToSetting() {
RouterUtil.push(JUMPSETTING);
this.appModel.startApplication(SETTING_ABILITY, SETTING_BUNDLE);
}
/**
* Back to front page.
*/
back() {
RouterUtil.back();
}
clearRouter() {
RouterUtil.clear();
/**
* Register multi mode input event listener.
*
* @param {object} listener - the listener to be registered to handle the multi mode input event.
*/
registerMMIEventListener(listener) {
this.mmiModel.registerEventCallback(listener);
}
registerAppUninstallListener(listener) {
this.appModel.registerAppUninstallListener(listener);
/**
* Unregister multi mode input event listener.
*
* @param {object} listener - The listener to be unregistered.
*/
unregisterMMIEventListener(listener) {
this.mmiModel.unregisterEventCallback(listener);
}
registerAppInstallListener(listener) {
console.info("Launcher BaseAppPresenter registerAppInstallListener start");
this.appModel.registerAppInstallListener(listener);
/**
* Get the layout view type.
*
* @return {string} Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
getAppPageStartConfig() {
return this.settingModel.getAppPageStartConfig();
}
unregisterAppInstallListener(listener) {
this.appModel.unregisterAppInstallListener(listener);
/**
* Layout migrate function.
*
* @param {string} currentLayout - Current layout type.
* @return {string} Whether the layout should be migrate or not.
*/
layoutMigrate(currentLayout) {
console.info("Launcher layoutMigrate in currentLayout = " + currentLayout);
let isNeedLayoutMigrate = false;
let destinationLayout = this.getAppPageStartConfig();
if (currentLayout === destinationLayout) {
return isNeedLayoutMigrate;
}
if (destinationLayout === LayoutConstants.Grid) {
RouterUtil.replace(PageData.GRID_APP_PAGE);
isNeedLayoutMigrate = true;
} else if (destinationLayout === LayoutConstants.List) {
RouterUtil.replace(PageData.LIST_APP_PAGE);
isNeedLayoutMigrate = true;
} else {
console.error("Launcher layoutMigrate error");
}
console.info("Launcher layoutMigrate in isNeedLayoutMigrate = " + isNeedLayoutMigrate);
return isNeedLayoutMigrate;
}
/**
* Called in onInit method from view to register listeners.
*
* @param {object} listener - View update listener.
*/
registerAppListChangeCallback(listener) {
mAppListChangeCallback = listener;
this.appModel.registerAppListInstallListener(mAppListInstallListener);
this.appModel.registerAppListUninstallListener(mAppListUninstallListener);
this.appModel.registerAppListChangeListener(mAppListChangeListener);
}
/**
* Called in onDestroy method from view to unregister listeners.
*/
unregisterAppListChangeCallback() {
console.info("Launcher appPresenter unregisterAppListChangeCallback");
this.appModel.unregisterAppListInstallListener(mAppListInstallListener);
this.appModel.unregisterAppListUninstallListener(mAppListUninstallListener);
this.appModel.unregisterAppListChangeListener(mAppListChangeListener);
}
/**
* Call back function of app installation.
*
* @param {object} bundleInfo - BundleInfo of installed application.
*/
appListInstallListener(bundleInfo) {
this.modifyItemList(this.appendItem, bundleInfo);
}
/**
* Append item to list.
*
* @param {object} list - List to be operated.
* @param {object} item - Item to be appended.
* @return {object} The list with appended item.
*/
appendItem(list, item) {
list.push(item);
return list;
}
/**
* Call back function of app uninstallation.
*
* @param {object} bundleInfo - BundleInfo of uninstalled application.
*/
appListUninstallListener(bundleInfo) {
this.modifyItemList(this.removeItem, bundleInfo);
}
/**
* Remove item from list.
*
* @param {object} list - List to be operated.
* @param {object} item - Item to be removed.
* @return {object} The list with removed item.
*/
removeItem(list, item) {
for (let listItem of list) {
if (listItem.bundleName == item.bundleName) {
let index = list.indexOf(listItem);
list.splice(index, 1);
}
}
return list;
}
/**
* Call back function of app package change event.
*
* @param {object} bundleInfo - BundleInfo of changed application.
*/
appListChangeListener(bundleInfo) {
this.modifyItemList(this.replaceItem, bundleInfo);
}
/**
* Replace item from list.
*
* @param {object} list - List to be operated.
* @param {object} item - Item to be replaced.
* @return {object} The list with replaced item.
*/
replaceItem(list, item) {
for (let listItem of list) {
console.info("Launcher replaceCache + " + listItem.bundleName + " + " + item.bundleName);
if (listItem.bundleName == item.bundleName) {
let index = list.indexOf(listItem);
list.splice(index, 1, item);
}
}
return list;
}
/**
* To operate cache and call callback method from view.
*
* @param {object} method - Method that add/modify/remove item in cache.
* @param {object} item - The item that will be operated.
*/
modifyItemList(method, item) {
console.info("Launcher AppListPresenter appListChangeListener + " + JSON.stringify(item));
let currentCacheList = this.appListInfoCacheManager.getCache(KEY_APP_LIST);
method(currentCacheList, item);
this.appListInfoCacheManager.setCache(KEY_APP_LIST, currentCacheList);
let callbackList = this.regroupDataAfterInstall(currentCacheList);
mAppListChangeCallback(callbackList);
}
/**
* To adapt bundleInfo data to different views.
* Will be overridden by sub-classes.
*
* @param {object} callbackList - BundleInfo list get from cache.
*/
regroupDataAfterInstall(callbackList) {
}
}

View File

@ -20,13 +20,20 @@ import PageData from '../../common/constants/PageData.js';
const GRID = LayoutConstants.Grid;
const GRID_APP_VIEW = PageData.GRID_APP_PAGE;
const LIST_APP_VIEW = PageData.LIST_APP_PAGE;
var mSettingsModel;
let mSettingsModel;
/**
* Presenter of entry view.
*/
export default class EntryPresenter {
constructor(settingsModel) {
mSettingsModel = settingsModel;
}
/**
* Entry the launcher grid view or list view.
*/
startAppListView() {
console.info("Launcher EntryPresenter startAppListView start");
let data = mSettingsModel.getAppPageStartConfig();

View File

@ -0,0 +1,8 @@
{
"image": {
"icon_default": "common/pics/icon_default.png",
"img_return": "common/pics/img_return.png",
"img_to_detail": "common/pics/img_to_detail.png",
"img_wallpaper_default": "common/pics/img_wallpaper_default.jpg"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"icon_default": "common/pics/icon_default.png",
"img_return": "common/pics/img_return.png",
"img_to_detail": "common/pics/img_to_detail.png",
"img_wallpaper_default": "common/pics/img_wallpaper_default.jpg"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"icon_default": "common/pics/icon_default.png",
"img_return": "common/pics/img_return.png",
"img_to_detail": "common/pics/img_to_detail.png",
"img_wallpaper_default": "common/pics/img_wallpaper_default.jpg"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"icon_default": "common/pics/icon_default.png",
"img_return": "common/pics/img_return.png",
"img_to_detail": "common/pics/img_to_detail.png",
"img_wallpaper_default": "common/pics/img_wallpaper_default.jpg"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"icon_default": "common/pics/icon_default.png",
"img_return": "common/pics/img_return.png",
"img_to_detail": "common/pics/img_to_detail.png",
"img_wallpaper_default": "common/pics/img_wallpaper_default.jpg"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"icon_default": "common/pics/icon_default.png",
"img_return": "common/pics/img_return.png",
"img_to_detail": "common/pics/img_to_detail.png",
"img_wallpaper_default": "common/pics/img_wallpaper_default.jpg"
}
}

View File

@ -0,0 +1,9 @@
{
"layoutDescription" : {
"pageCount" : 0,
"row" : 5,
"column" : 4
},
"layoutInfo" : [
]
}

View File

@ -3,8 +3,8 @@
"bundleName": "com.ohos.launcher",
"vendor": "ohos",
"version": {
"code": 1,
"name": "1.0"
"code": 1000000,
"name": "1.0.0"
},
"apiVersion": {
"compatible": 5,

View File

@ -14,14 +14,18 @@
*/
import RecentsModel from './common/model/RecentsModel.js'
import ResourceManager from './common/model/ResourceManager.js'
export default {
data: {
recentsModel: new RecentsModel(),
resourceManager: new ResourceManager()
},
onCreate() {
console.info('Launcher recents AceApplication onCreate');
},
onDestroy() {
console.info('Launcher recents AceApplication onDestroy');
}

View File

@ -13,9 +13,8 @@
* limitations under the License.
*/
import ResourceManager from '../../model/ResourceManager.js';
var mResourceManager;
let mResourceManager;
let mDefaultAppIcon;
export default {
props: ['itemAppId', 'itemAppIcon', 'itemBundleName'],
@ -27,21 +26,26 @@ export default {
};
},
onInit() {
console.info("Launcher recents AppIcon onInit start")
this.$watch('itemAppIcon', 'appIconWatcher');
mResourceManager = new ResourceManager();
mResourceManager.getAppIcon(this.itemAppIcon, this.itemBundleName, this.iconLoadCallback);
console.info("Launcher recents AppIcon onInit start");
mDefaultAppIcon = globalThis.$globalR('image.icon_default');
mResourceManager = this.$app.$def.data.resourceManager;
console.info("Launcher recents AppIcon onInit end")
},
onShow() {
},
appIconWatcher(newV, oldV) {
if (newV != null && newV != undefined) {
mResourceManager.getAppIcon(this.itemAppIcon, this.itemBundleName, this.iconLoadCallback);
}
},
/**
* Set image.
*
* @param {object} image - the image.
*/
iconLoadCallback(image) {
this.appIcon = image;
},
/**
* Update icon.
*/
updateIcon() {
console.info("Launcher AppIcon updateIcon in bundleName = " + this.itemBundleName);
mResourceManager.getAppIcon(this.itemAppIcon,this.itemBundleName,this.iconLoadCallback, mDefaultAppIcon);
}
}

View File

@ -13,9 +13,7 @@
* limitations under the License.
*/
import ResourceManager from '../../model/ResourceManager.js';
var mResourceManager;
let mResourceManager;
export default {
props: ['itemAppId', 'itemLabelId', 'itemBundleName', 'itemAppName'],
@ -28,19 +26,25 @@ export default {
};
},
onInit() {
this.$watch('itemLabelId', 'appIconWatcher');
mResourceManager = new ResourceManager();
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
console.info("Launcher recents AppName onInit start");
mResourceManager = this.$app.$def.data.resourceManager;
console.info("Launcher recents AppName onInit end");
},
onShow() {
},
appIconWatcher(newV, oldV) {
if (newV != null && newV != undefined) {
mResourceManager.getAppName(this.itemLabelId, this.itemBundleName, this.itemAppName, this.iconLoadCallback);
}
},
/**
* Set app name.
*
* @param {string} name - the name of app.
*/
iconLoadCallback(name) {
this.appName = name;
},
/**
* Update name.
*/
updateName() {
console.info("Launcher AppName updateName in bundleName = " + this.itemBundleName);
mResourceManager.getAppName(this.itemLabelId,this.itemBundleName,this.itemAppName,this.iconLoadCallback);
}
}

View File

@ -13,32 +13,47 @@
* limitations under the License.
*/
import napiAbilityManager from '@ohos.napi_ability_manager';
import featureAbility from '@ohos.feature_ability';
import storage from '@ohos.data.storage';
import bundle_mgr from '@ohos.bundle_mgr';
import feature_ability from '@ohos.feature_ability';
import NapiAbilityManager from '@ohos.app.abilitymanager';
import Storage from '@ohos.data.storage';
import BundleMgr from '@ohos.bundle';
import FeatureAbility from '@ohos.ability.featureability';
var RECENT_PROCESS_LIMIT_KEY = 'RecentProcessLimit';
const PREFERENCES_PATH = '/data/accounts/account_0/appdata/com.ohos.launcher/sharedPreference/LauncherPreference';
var mRecentList = [];
var DEFAULT_RECENT_PROCESS_LIMIT = 10;
var INCLUDE_SYSTEM_APP = 0;
var EXCLUDE_SYSTEM_APP = 1;
var mIconResultCount = 0;
var mPreferences = storage.getStorageSync(PREFERENCES_PATH);
const MAX_NUM = 20;
const PERMISSION_NUM = 8;
const NON = 0;
const RECENT_PROCESS_LIMIT_KEY = 'RecentProcessLimit';
const DEFAULT_RECENT_PROCESS_LIMIT = 10;
let mRecentList = [];
let mIconResultCount = 0;
let mPreferences = Storage.getStorageSync(PREFERENCES_PATH);
/**
* Class RecentsModel.
*/
export default class RecentsModel {
/**
* Get recent process list.
*
* @param {object} callback - the callback from presenter.
*/
getRecentProcessList(callback) {
console.info("Launcher recents RecentsModel getRecentProcessList start")
console.info("Launcher recents RecentsModel getRecentProcessList start");
mRecentList = [];
mIconResultCount = 0;
console.info("Launcher recents RecentsModel napiAbilityManager.queryRecentAbilityMissionInfos start")
napiAbilityManager.queryRecentAbilityMissionInfos().then((data) => {
console.info("Launcher recents RecentsModel napiAbilityManager.queryRecentAbilityMissionInfos() callback")
console.info("Launcher recents RecentsModel NapiAbilityManager.queryRecentAbilityMissionInfos start")
NapiAbilityManager.queryRunningAbilityMissionInfos(MAX_NUM).then((data) => {
console.info("Launcher recents RecentsModel NapiAbilityManager.queryRecentAbilityMissionInfos() callback")
console.info('Launcher recents queryRecentAbilityMissionInfos data length [' + data.length + ']');
console.info('Launcher recents queryRecentAbilityMissionInfos data = ' + JSON.stringify(data));
for (var i = 0; i < data.length; i++) {
if(data.length == 0) {
console.info('Launcher recents data empty');
callback(mRecentList);
return;
}
for (let i = 0; i < data.length; i++) {
let recentTaskInfo = {
AppName: data[i].missionDescription.label,
AppId: data[i].topAbility.bundleName,
@ -53,10 +68,10 @@ export default class RecentsModel {
console.info('Launcher recents RecentsModel queryRecentAbilityMissionInfos mRecentList = ' + JSON.stringify(mRecentList));
for (let element of mRecentList) {
console.info('Launcher recents RecentsModel bundle_mgr.getApplicationInfo element of mRecentList = ' + JSON.stringify(element));
bundle_mgr.getApplicationInfo(element.AppId).then(data => {
BundleMgr.getApplicationInfo(element.AppId, PERMISSION_NUM, NON).then(data => {
console.info('Launcher recents bundle_mgr.getApplicationInfo data = ' + JSON.stringify(data));
let recentTaskInfo = mRecentList.find((recentItem) => {
if (recentItem.AppId == data.bundleName) return recentItem;
if (recentItem.AppId == data.name) return recentItem;
});
recentTaskInfo.iconId = data.iconId;
recentTaskInfo.labelId = data.labelId;
@ -66,25 +81,32 @@ export default class RecentsModel {
if (mIconResultCount == mRecentList.length) {
callback(mRecentList);
}
});
}).catch(error =>
console.error("Launcher recents RecentsModel getRecentProcessList promise::catch : " + JSON.stringify(error))
);
}
});
}).catch(error =>
console.error("Launcher recents RecentsModel getRecentProcessList promise::catch : " + JSON.stringify(error))
);
console.info("Launcher recents RecentsModel getRecentProcessList end")
}
/**
* Clear recent process list.
*
*/
clearRecentProcess() {
console.info("Launcher recents RecentsModel clearRecentProcess start")
while (mRecentList.length > 0) {
mRecentList.pop();
}
console.info("Launcher recents RecentsModel napiAbilityManager.removeStack start")
napiAbilityManager.removeStack(EXCLUDE_SYSTEM_APP).then((data) => {
console.info('Launcher recents removeStack data [' + data + ']');
console.info("Launcher recents RecentsModel NapiAbilityManager.removeStack start")
NapiAbilityManager.clearMissions().then((data) => {
});
setTimeout(() => {
console.info("Launcher recents RecentsModel feature_ability.terminateAbility start")
feature_ability.terminateAbility()
FeatureAbility.terminateAbility()
.then(data => console.info("Launcher recents terminateAbility promise::then : " + data))
.catch(error => console.info("Launcher recents terminateAbility promise::catch : " + error));
}, 1000);
@ -92,23 +114,28 @@ export default class RecentsModel {
console.info("Launcher recents RecentsModel clearRecentProcess end")
}
/**
* Remove recent process list.
*
* @param {string} missionId - the missionId of recent process.
*/
removeRecentProcess(missionId) {
console.info("Launcher recents RecentsModel removeRecentProcess start")
for (var idx = 0; idx < mRecentList.length; idx++) {
for (let idx = 0; idx < mRecentList.length; idx++) {
if (mRecentList[idx].missionId == missionId) {
mRecentList.splice(idx, 1);
break;
}
}
console.info("Launcher recents RecentsModel napiAbilityManager.removeMission start")
napiAbilityManager.removeMission(missionId).then((data) => {
console.info("Launcher recents RecentsModel NapiAbilityManager.removeMission start")
NapiAbilityManager.removeMission(missionId).then((data) => {
console.info('removeMission data [' + data + ']');
});
if (mRecentList.length == 0) {
setTimeout(() => {
console.info("Launcher recents RecentsModel feature_ability.terminateAbility start")
feature_ability.terminateAbility()
FeatureAbility.terminateAbility()
.then(data => console.info("Launcher recents terminateAbility promise::then : " + data))
.catch(error => console.info("Launcher recents terminateAbility promise::catch : " + error));
}, 1000);
@ -116,6 +143,11 @@ export default class RecentsModel {
console.info("Launcher recents RecentsModel removeRecentProcess end")
}
/**
* Get recent process list.
*
* @return {number} - the number of recent process.
*/
getRecentProcessLimit() {
console.info("Launcher recents RecentsModel getRecentProcessLimit start");
let limit = DEFAULT_RECENT_PROCESS_LIMIT;
@ -126,35 +158,35 @@ export default class RecentsModel {
return limit;
}
/**
* Hot start app.
*
* @param {object} appInfo - the app info.
*/
hotStartUpApp(appInfo) {
console.info('Launcher recents hotStartUpApp start');
this.startAbility(appInfo);
console.info('Launcher recents hotStartUpApp end');
}
/**
* Start ability.
*
* @param {object} appInfo - the app info.
*/
startAbility(appInfo) {
console.info("Launcher recents startAbility start");
console.info("Launcher recents featureAbility.startAbility appId = " + JSON.stringify(appInfo));
featureAbility.startAbility({
bundleName: appInfo.AppId,
abilityName: appInfo.abilityName,
requestCode: 1,
abilityType: "PageAbility",
// promise
console.info('Launcher startApplication abilityname');
let result = FeatureAbility.startAbility({
want: {
action: "action1",
entities: ["entity1"],
type: "PageAbility",
flags: 2,
elementName: {
deviceId: "deviceId",
bundleName: appInfo.AppId,
abilityName: appInfo.abilityName,
},
},
syncOption: 1
abilityName: appInfo.abilityName
}
}).then(data =>
console.info("Launcher recents promise::then : " + data)).catch(error =>
console.info("Launcher recents promise::catch : " + error));
console.info("Launcher recents startAbility end");
console.info("Launcher promise::then : " + JSON.stringify(data))
).catch(error =>
console.info("Launcher promise::catch : " + JSON.stringify(error))
);
console.info("Launcher AceApplication : startAbility : " + result);
}
}

View File

@ -13,22 +13,30 @@
* limitations under the License.
*/
import resmgr from '@ohos.resmgr';
const DEFAULT_ICON_URL = 'common/pics/icon_default.png';
import Resmgr from '@ohos.resmgr';
/**
* A manager class provide app icon and name from cache or system API.
*/
export default class ResourceManager {
ResourceManager() {
constructor() {
}
getAppIcon(path, bundleName, callback) {
/**
* Get icon image of specific app.
*
* @param {string} path - path of target file
* @param {string} bundleName - bundle name of the app
* @param {object} callback - callback method
*/
getAppIcon(path, bundleName, callback, defaultIconUrl) {
console.info("Launcher recents ResourceManager getAppIcon start path = " + path + " bundleName = " + bundleName);
if (path == null || path == undefined || path == "") {
console.info("Launcher recents ResourceManager defaultIcon callback ");
callback(DEFAULT_ICON_URL)
callback(defaultIconUrl)
} else {
console.info("Launcher recents ResourceManager resmgr.getResourceManager called");
resmgr.getResourceManager(bundleName).then(item => {
console.info("Launcher recents ResourceManager Resmgr.getResourceManager called");
Resmgr.getResourceManager(bundleName).then(item => {
console.info("Launcher recents ResourceManager item.getMediaBase64 called");
item.getMediaBase64(path, (error, value) => {
console.info("Launcher recents ResourceManager item.getMediaBase64 callback value = " + value);
@ -36,19 +44,29 @@ export default class ResourceManager {
callback(value);
}
});
});
}).catch(error =>
console.error("Launcher recents ResourceManager getAppIcon promise::catch : " + JSON.stringify(error))
);
}
console.info("Launcher recents ResourceManager getAppIcon end");
}
/**
* Get app name of specific app.
*
* @param {string} labelId - label id of target app
* @param {string} bundleName - bundle name of the app
* @param {string} appName - app name
* @param {object} callback - callback method
*/
getAppName(labelId, bundleName, appName, callback) {
console.info("Launcher recents ResourceManager getAppName start labelId = " + labelId
+ " bundleName = " + bundleName + " appName = " + appName);
if (labelId <= 0) {
callback(appName);
} else {
console.info("Launcher recents ResourceManager resmgr.getResourceManager ");
resmgr.getResourceManager(bundleName).then(item => {
console.info("Launcher recents ResourceManager Resmgr.getResourceManager ");
Resmgr.getResourceManager(bundleName).then(item => {
console.info("Launcher recents ResourceManager item.getString " + JSON.stringify(item));
item.getString(labelId, (error, value) => {
if (value != null) {
@ -56,7 +74,9 @@ export default class ResourceManager {
callback(value);
}
});
});
}).catch(error =>
console.error("Launcher recents ResourceManager getAppName promise::catch : " + JSON.stringify(error))
);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -1,4 +1,5 @@
{
"strings": {
"no_recent": "No recent apps"
}
}

View File

@ -1,4 +1,5 @@
{
"strings": {
"no_recent": "最近无运行应用"
}
}

View File

@ -16,7 +16,6 @@
@import '../../common/css/CommonPageStyle.css';
.container {
background-image: url("common/pics/ic_wallpaper_recent.jpg");
background-size: cover;
}
@ -65,11 +64,25 @@
.piece {
height: 20%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.no-recent {
height: 100%;
width: 100%;
align-items: center;
justify-content: center;
}
.no-recent-text {
color: white;
font-size: 30px;
height: 60px;
line-height: 60px;
align-items: center;
}
.clear {
background-color: black;
opacity: 0.4;

View File

@ -17,31 +17,34 @@
<element src="../../common/component/AppIcon/AppIcon.hml" name="appIcon"></element>
<element src="../../common/component/AppName/AppName.hml" name="appName"></element>
<div class="container">
<div class="body">
<div class="container" style="background-image: {{ $r('image.ic_wallpaper_recent') }}">
<div style="display:{{recentProcessListDisplay}}" class="body">
<list class="list">
<list-item class="list-item" for="{{ recentProcessList }}">
<div class="app-item">
<div class="app-icon">
<appicon item-app-icon="{{ $item.iconId }}" item-app-id="{{ $item.AppId }}"
<appicon id="icon{{$idx}}" item-app-icon="{{ $item.iconId }}" item-app-id="{{ $item.AppId }}"
item-bundle-name="{{ $item.bundleName }}">
</appicon>
<appname item-app-id="{{ $item.AppId }}" item-label-id="{{ $item.labelId }}"
<appname id="name{{$idx}}" item-app-id="{{ $item.AppId }}" item-label-id="{{ $item.labelId }}"
item-bundle-name="{{ $item.bundleName }}" item-app-name="{{ $item.AppName }}">
</appname>
</div>
<image class="app-img" src="/common/pics/img_app_default.png"
<image class="app-img" src="{{ $r('image.img_app_default') }}"
onswipe="clearApp({{ $item.missionId }})" direction="up" onclick="startUp({{ $item }})">
</image>
</div>
</list-item>
</list>
</div>
<div class="piece">
<div style="display:{{recentProcessListDisplay}}" class="piece">
<div class="clear" onclick="clearAll">
<image class="clear-img" src="common/pics/ic_recent_delete.png">
<image class="clear-img" src="{{ $r('image.ic_recent_delete') }}">
</image>
</div>
</div>
<div style="display:{{emptyMsgDisplay}}" class="no-recent">
<text class="no-recent-text" >{{$t('strings.no_recent')}}</text>
</div>
</div>

View File

@ -15,14 +15,21 @@
import RecentsPresenter from '../../presenter/recent/RecentsPresenter.js';
var mRecentsPresenter;
const APP_INFO_REFRESH_DELAY = 500;
const DISPLAY_NONE = 'none';
const DISPLAY_FLEX = 'flex';
let mRecentsPresenter;
export default {
data: {
recentProcessList: []
recentProcessList: [],
recentProcessListDisplay: DISPLAY_NONE,
emptyMsgDisplay: DISPLAY_FLEX
},
onInit() {
console.info("Launcher recents onInit start");
globalThis.$globalR = this.$r.bind(this);
console.info("Launcher recents onInit end");
},
@ -31,13 +38,23 @@ export default {
mRecentsPresenter = new RecentsPresenter(this.$app.$def.data.recentsModel);
mRecentsPresenter.getRecentProcessList((data) => {
this.recentProcessList = data;
if (this.recentProcessList.length == 0) {
this.recentProcessListDisplay = DISPLAY_NONE;
this.emptyMsgDisplay = DISPLAY_FLEX;
return;
}
this.recentProcessListDisplay = DISPLAY_FLEX;
this.emptyMsgDisplay = DISPLAY_NONE;
console.info("Launcher recents onShow getRecentProcessList this.recentProcessList = " + JSON.stringify(this.recentProcessList));
this.updateAppInfos();
});
console.info("Launcher recents onShow end");
},
onHide() {
console.info("Launcher recents onHide start");
this.recentProcessListDisplay = DISPLAY_NONE;
this.emptyMsgDisplay = DISPLAY_NONE;
this.recentProcessList = [];
console.info("Launcher recents onHide end");
},
@ -52,6 +69,12 @@ export default {
console.info("Launcher recents clearAll end");
},
/**
* Remove recent process.
*
* @param {string} missionId - the missionId of recent process.
* @param {object} e - the event form pre page.
*/
clearApp(missionId, e) {
console.info("Launcher recents clearApp start missionId = " + missionId + " e.direction = " + e.direction);
if (e.direction == "up") {
@ -61,9 +84,28 @@ export default {
console.info("Launcher recents clearApp end");
},
/**
* Hot start app.
*
* @param {object} appInfo - the app info.
*/
startUp(appInfo) {
console.info("Launcher recents startUp start appInfo = " + JSON.stringify(appInfo));
mRecentsPresenter.startUpApp(appInfo);
console.info("Launcher recents startUp end");
},
/**
* Update app information.
*/
updateAppInfos() {
console.info("Launcher recents updateAppInfos setTimeout this.recentProcessList.length = " + this.recentProcessList.length);
setTimeout(() => {
for(let i = 0; i < this.recentProcessList.length; i++) {
console.info("Launcher recents updateAppInfos setTimeout in i = " + i);
this.$child('icon' + i).updateIcon();
this.$child('name' + i).updateName();
}
}, APP_INFO_REFRESH_DELAY);
}
}

View File

@ -13,12 +13,20 @@
* limitations under the License.
*/
import router from '@system.router';
import Router from '@system.router';
var mRecentsModel;
var mRecentsLimit;
let mRecentsModel;
let mRecentsLimit;
/**
* Class RecentsPresenter.
*/
export default class RecentsPresenter {
/**
* Constructor of RecentsPresenter.
*
* @param {object} recentsModel - the model of recentPresenter.
*/
constructor(recentsModel) {
console.info("Launcher recents RecentsPresenter constructor start");
mRecentsModel = recentsModel;
@ -26,6 +34,11 @@ export default class RecentsPresenter {
console.info("Launcher recents RecentsPresenter constructor end");
}
/**
* Callback function of getRecentProcessList.
*
* @param {object} callback - the callback from view.
*/
getRecentProcessList(callback) {
console.info("Launcher recents RecentsPresenter getRecentProcessList start")
mRecentsModel.getRecentProcessList((data) => {
@ -46,6 +59,11 @@ export default class RecentsPresenter {
console.info("Launcher recents RecentsPresenter clearRecentProcess end");
}
/**
* Remove recent process.
*
* @param {string} missionId - the missionId of recent process.
*/
removeRecentProcess(missionId) {
console.info("Launcher recents RecentsPresenter removeRecentProcess start missionId = " + missionId);
mRecentsModel.removeRecentProcess(missionId);
@ -54,10 +72,15 @@ export default class RecentsPresenter {
back() {
console.info("Launcher recents RecentsPresenter back start");
router.back();
Router.back();
console.info("Launcher recents RecentsPresenter back end");
}
/**
* Hot start app.
*
* @param {object} appInfo - the app info .
*/
startUpApp(appInfo) {
console.info("Launcher recents RecentsPresenter startUpApp start appInfo = " + JSON.stringify(appInfo));
mRecentsModel.hotStartUpApp(appInfo);

View File

@ -0,0 +1,8 @@
{
"image": {
"ic_recent_delete": "common/pics/ic_recent_delete.png",
"ic_wallpaper_recent": "common/pics/ic_wallpaper_recent.jpg",
"img_app_default": "common/pics/img_app_default.png",
"icon_default": "common/pics/icon_default.png"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"ic_recent_delete": "common/pics/ic_recent_delete.png",
"ic_wallpaper_recent": "common/pics/ic_wallpaper_recent.jpg",
"img_app_default": "common/pics/img_app_default.png",
"icon_default": "common/pics/icon_default.png"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"ic_recent_delete": "common/pics/ic_recent_delete.png",
"ic_wallpaper_recent": "common/pics/ic_wallpaper_recent.jpg",
"img_app_default": "common/pics/img_app_default.png",
"icon_default": "common/pics/icon_default.png"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"ic_recent_delete": "common/pics/ic_recent_delete.png",
"ic_wallpaper_recent": "common/pics/ic_wallpaper_recent.jpg",
"img_app_default": "common/pics/img_app_default.png",
"icon_default": "common/pics/icon_default.png"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"ic_recent_delete": "common/pics/ic_recent_delete.png",
"ic_wallpaper_recent": "common/pics/ic_wallpaper_recent.jpg",
"img_app_default": "common/pics/img_app_default.png",
"icon_default": "common/pics/icon_default.png"
}
}

View File

@ -0,0 +1,8 @@
{
"image": {
"ic_recent_delete": "common/pics/ic_recent_delete.png",
"ic_wallpaper_recent": "common/pics/ic_wallpaper_recent.jpg",
"img_app_default": "common/pics/img_app_default.png",
"icon_default": "common/pics/icon_default.png"
}
}

View File

@ -13,5 +13,5 @@
* limitations under the License.
*/
include ':launcher', ':recents'
include ':launcher', ':recents', ':settings'

22
settings/build.gradle Normal file
View File

@ -0,0 +1,22 @@
apply plugin: 'com.huawei.ohos.hap'
ohos {
compileSdkVersion 6
defaultConfig {
compatibleSdkVersion 6
}
supportSystem "standard"
buildTypes {
release {
proguardOpt {
proguardEnabled false
rulesFiles 'proguard-rules.pro'
}
}
}
entryModules "launcher"
}
dependencies {
entryImplementation project(':launcher')
}

1
settings/package.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,53 @@
{
"app": {
"bundleName": "com.ohos.launcher",
"vendor": "ohos",
"version": {
"code": 1000000,
"name": "1.0.0"
},
"apiVersion": {
"compatible": 5,
"target": 5,
"releaseType": "Beta1"
}
},
"deviceConfig": {},
"module": {
"package": "com.ohos.launcher.settings",
"name": ".MyApplication",
"mainAbility": "com.ohos.launcher.settings.MainAbility",
"deviceType": [
"phone"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "settings",
"moduleType": "feature",
"installationFree": true
},
"abilities": [
{
"visible": true,
"name": "com.ohos.launcher.settings.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:app_name",
"type": "page",
"launchType": "singleton"
}
],
"js": [
{
"name": "default",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"pages": [
"pages/settings/settings"
]
}
]
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 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.
*/
import SettingsModel from './common/model/SettingsModel.js'
export default {
data: {
settingsModel: new SettingsModel()
},
onCreate() {
console.info('Launcher settings AceApplication onCreate');
},
onDestroy() {
console.info('Launcher settings AceApplication onDestroy');
}
};

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2021 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.
*/
const DefaultLayoutConfig = {
DefaultAppPageStartConfig: 'Grid',
DefaultGridConfig: 1,
DefaultRecentProcessLimit: 20,
DefaultRecentProcessLimitArray: [5,10,15,20],
}
export default DefaultLayoutConfig;

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2021 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.
*/
const GridLayoutConfigs = {
GridLayoutTable: [
{
id: 0,
layout: '4X4',
row: 4,
column: 4
},
{
id: 1,
layout: '5X4',
row: 5,
column: 4
},
{
id: 2,
layout: '6X4',
row: 6,
column: 4
},
]
}
export default GridLayoutConfigs;

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2021 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.
*/
const LayoutContants = {
Grid: "Grid",
List: "List"
}
export default LayoutContants;

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2021 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.
*/
const PageData = {
GRID_APP_PAGE: 'pages/AppGridView/AppGridView',
LIST_APP_PAGE: 'pages/AppListView/AppListView'
}
export default PageData;

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2021 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.
*/
/**
* Class ILayoutConfig.
*/
export default class ILayoutConfig {
/**
* constructor.
*
*/
constructor() {
}
/**
* Get the layout view type.
*
* @return {string} Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
getAppPageStartConfig() {
return this.loadAppPageStartConfig();
}
/**
* Set the layout view type.
*
* @param {String} type - Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
setAppPageStartConfig(type) {
this.saveAppPageStartConfig(type);
}
/**
* Get grid layout config id.
*
* @return {object} grid layout config id.
*/
getGridConfig() {
return this.loadGridConfig();
}
/**
* Set grid layout config id.
*
* @param {number} id - layout config id.
*/
setGridConfig(id) {
this.saveGridConfig(id);
}
/**
* Get recent process max limit.
*
* @return {number} recent process max limit.
*/
getRecentProcessLimit() {
return this.loadRecentProcessLimit();
}
/**
* Set recent process max limit.
*
* @param {number} num - Recent process max limit.
*/
setRecentProcessLimit(num) {
this.saveRecentProcessLimit(num);
}
/**
* Should overridden by sub-classes , load the launcher layout view type.
*/
loadAppPageStartConfig() {
}
/**
* Should overridden by sub-classes , save the launcher layout view type.
*/
saveAppPageStartConfig(type) {
}
/**
* Should overridden by sub-classes , save the launcher layout view type.
*/
loadGridConfig() {
}
/**
* Should overridden by sub-classes , save the launcher grid view layout config id.
*/
saveGridConfig(id) {
}
/**
* Should overridden by sub-classes , load the recent process max limit.
*/
loadRecentProcessLimit() {
}
/**
* Should overridden by sub-classes , save the recent process max limit.
*/
saveRecentProcessLimit(num) {
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2021 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.
*/
import StorageLayoutConfig from './StorageLayoutConfig.js'
/**
* The factory function of producing the class to operate layout config.
*
* @return {object} The class to operate layout config.
*/
export function getLayoutConfig() {
return new StorageLayoutConfig();
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2021 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.
*/
import GridLayoutConfigs from '../../common/configs/GridLayoutConfigs.js';
import {getLayoutConfig} from './LayoutConfigManager.js';
import FeatureAbility from '@ohos.ability.featureability';
let mLayoutConfig = getLayoutConfig();
let mGridConfig = 0;
let mGridLayoutTable = GridLayoutConfigs.GridLayoutTable;
/**
* Class settingsModel.
*/
export default class SettingsModel {
/**
* Get the grid view presetting collection of layout config information table.
*
* @return {object} Grid view presetting collection object.
*/
getGridLayoutTable() {
return mGridLayoutTable;
}
/**
* Get layout config of grid view.
*
* @return {object} Layout config of grid view.
*/
getGridConfig() {
mGridConfig = mLayoutConfig.getGridConfig();
return mGridLayoutTable[mGridConfig];
}
/**
* Set layout config id of grid view.
*
* @param {string} id - Layout config id of grid view.
*/
setGridConfig(id) {
mLayoutConfig.setGridConfig(id);
}
/**
* Get recent process max limit.
*
* @return {number} recent process max limit.
*/
getRecentProcessLimit() {
return mLayoutConfig.getRecentProcessLimit();
}
/**
* Set recent process max limit.
*
* @param {number} num - Recent process max limit.
*/
setRecentProcessLimit(num) {
mLayoutConfig.setRecentProcessLimit(num);
}
/**
* Get the layout view type.
*
* @return {string} Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
getAppPageStartConfig() {
return mLayoutConfig.getAppPageStartConfig();
}
/**
* Set the layout view type.
*
* @param {string} type - Layout view type, should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
setAppPageStartConfig(type) {
mLayoutConfig.setAppPageStartConfig(type);
}
/**
* Close settings.
*/
closeSettings() {
console.info("Launcher settings SettingsModel closeSettings start")
FeatureAbility.terminateAbility()
.then(data => console.info("Launcher settings SettingsModel closeSettings promise::then : " + data))
.catch(error => console.info("Launcher settings SettingsModel closeSettings promise::catch : " + error));
console.info("Launcher settings SettingsModel closeSettings end ");
}
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2021 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.
*/
import ILayoutConfig from './ILayoutConfig.js';
import DefaultLayoutConfig from '../../common/configs/DefaultLayoutConfig.js';
import Storage from '@ohos.data.storage';
const APP_PAGE_START_CONFIG = 'AppStartPageType';
const GRID_CONFIG = "GridConfig";
const RECENT_PROCESS_LIMIT = "RecentProcessLimit";
const PREFERENCES_PATH = '/data/accounts/account_0/appdata/com.ohos.launcher/sharedPreference/LauncherPreference';
let mPreferences = Storage.getStorageSync(PREFERENCES_PATH);
/**
* A class that stores layout information.
* @extends ILayoutConfig
*/
export default class StorageLayoutConfig extends ILayoutConfig {
constructor() {
super();
}
/**
* Load the launcher layout view type.
*
* @return {string} Layout view type , should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
loadAppPageStartConfig() {
console.info('Launcher setttings StorageLayoutConfig loadAppPageStartConfig start');
let data = mPreferences.getSync(APP_PAGE_START_CONFIG, DefaultLayoutConfig.DefaultAppPageStartConfig);
console.info('Launcher setttings StorageLayoutConfig loadAppPageStartConfig mPreferences end' + data);
return data;
}
/**
* Save the launcher layout view type.
*
* @param {string} type - View type , should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
saveAppPageStartConfig(type) {
console.info('Launcher settings StorageLayoutConfig saveAppPageStartConfig mPreferences put type ' + type);
mPreferences.putSync(APP_PAGE_START_CONFIG, type);
mPreferences.flushSync();
console.info('Launcher settings StorageLayoutConfig saveAppPageStartConfig mPreferences put type flush');
}
/**
* Load the launcher grid view layout config id.
*
* @return {number} id - Config id.
*/
loadGridConfig() {
console.info('Launcher settings StorageLayoutConfig loadGridConfig mPreferences get GRID_CONFIG');
let data = mPreferences.getSync(GRID_CONFIG, DefaultLayoutConfig.DefaultGridConfig);
console.info('Launcher settings StorageLayoutConfig loadGridConfig mPreferences get' + data);
return data;
}
/**
* Save the launcher grid view layout config id.
*
* @param {string} id - View type , should one of 'Grid' or 'List' which is stored in LayoutConstants class.
*/
saveGridConfig(id) {
console.info('Launcher settings StorageLayoutConfig saveGridConfig mPreferences put id' + id);
mPreferences.putSync(GRID_CONFIG, id);
mPreferences.flushSync();
console.info('Launcher settings StorageLayoutConfig saveGridConfig mPreferences put id flush');
}
/**
* Load the recent process max limit.
*
* @return {number} Recent process max limit.
*/
loadRecentProcessLimit() {
console.info('Launcher settings StorageLayoutConfig loadRecentProcessLimit mPreferences get');
let data = mPreferences.getSync(RECENT_PROCESS_LIMIT, DefaultLayoutConfig.DefaultRecentProcessLimit);
console.info('Launcher settings StorageLayoutConfig loadRecentProcessLimit mPreferences get' + data);
return data;
}
/**
* Save the recent process max limit.
*
* @param {number} num - Recent process max limit.
*/
saveRecentProcessLimit(num) {
console.info('Launcher settings StorageLayoutConfig saveRecentProcessLimit mPreferences put num' + num);
mPreferences.putSync(RECENT_PROCESS_LIMIT, num);
mPreferences.flushSync();
console.info('Launcher settings StorageLayoutConfig saveRecentProcessLimit mPreferences put num flush');
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

View File

@ -0,0 +1,22 @@
{
"strings": {
"loading": "Loading...",
"cancelled": "Cancelled",
"uninstall_succeeded": "Successfully uninstalled",
"uninstall": "Uninstall",
"cancel": "Cancel",
"prohibited": "Uninstall prohibited ",
"settings": "Settings",
"carry_out": "Finish",
"do_you_want_to_uninstall_start": "Are you sure uninstall",
"do_you_want_to_uninstall_end": "?",
"launcher_settings": "Launcher settings",
"uninstall_app": "Uninstall App",
"layout": "Layout",
"recent_tasks_settings": "Recent tasks settings",
"layout_style": "Layout style",
"launcher_layout": "Launcher layout",
"layout_grid": "grid",
"layout_list": "list"
}
}

View File

@ -0,0 +1,22 @@
{
"strings": {
"loading": "加载中...",
"cancelled": "已取消",
"uninstall_succeeded": "卸载成功",
"uninstall": "卸载",
"cancel": "取消",
"prohibited": "禁止卸载",
"settings": "设置",
"carry_out": "完成",
"do_you_want_to_uninstall_start": "确定卸载",
"do_you_want_to_uninstall_end": "吗?",
"launcher_settings": "桌面设置",
"uninstall_app": "应用卸载",
"layout": "布局",
"recent_tasks_settings": "最近任务数",
"layout_style": "布局样式",
"launcher_layout": "桌面布局",
"layout_grid": "网格",
"layout_list": "列表"
}
}

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2021 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.
*/
.container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
background-color: #F0EEEE;
}
.return-icon {
margin-right: 20px;
margin-left: 20px;
width: 40px;
height: 40px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.top-bar {
top: 10px;
height: 80px;
width: 90%;
align-items: center;
display: flex;
justify-content: flex-start;
background-color: #F0EEEE;
padding-bottom: 10px;
}
.top-bar-text {
font-size: 35px;
}
.settings-box {
margin-top: 10px;
display: flex;
flex-direction: column;
align-items: center;
width: 90%;
background-color: #F0EEEE;
}
.settings-box-bar-text {
font-size: 25px;
color: #696969;
margin-left: 20px;
}
.settings-list-box {
display: flex;
top: 10px;
flex-direction: column;
align-items: center;
width: 100%;
line-height: 40px;
padding: 20px 30px 20px 30px;
background-color: white;
border-radius: 30px;
}
.settings-list-bar {
display: flex;
flex-direction: row;
width: 100%;
height: 70px;
padding: 10px 0;
align-items: center;
justify-content: flex-start;
position: relative;
}
.settings-list-title {
display: flex;
width: 70%;
height: 40px;
font-size: 30px;
line-height: 40px;
justify-content: flex-start;
align-items: center;
}
.settings-list-title-text {
font-size: 30px;
height: 40px;
line-height: 40px;
align-items: center;
}
.settings-list-layout {
display: flex;
width: 30%;
font-size: 28px;
height: 40px;
line-height: 40px;
justify-content: space-between;
align-items: center;
align-content: center;
}
.settings-list-layout-text {
font-size: 25px;
height: 40px;
line-height: 40px;
align-items: center;
}
.to-setting-detail-icon {
display: flex;
align-items: center;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
width: 30px;
height: 30px;
}
.dialog-setting-detail {
width: 90%;
margin-bottom: 0;
}
.dialog-setting-box {
width: 100%;
padding: 30px 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.dialog-setting-bar {
width: 100%;
font-size: 35px;
align-items: center;
}
.dialog-setting-bar-text {
font-size: 35px;
margin-top: 0px;
align-items: center;
}
.dialog-setting-options-box {
display: flex;
justify-content: space-between;
flex-direction: row;
align-items: center;
margin-top: 10px;
}
.dialog-setting-option-text {
display: flex;
height: 40px;
line-height: 40px;
font-size: 25px;
align-items: center;
color: #696969;
}
.dialog-setting-option-radio {
display: flex;
align-items: center;
}
.dialog-settings-cancel-bar {
width: 100%;
display: flex;
color: #3366ff;
align-items: center;
}
.dialog-settings-cancel-text {
width: 100%;
color: #3366ff;
font-size: 25px;
margin-top: 10px;
text-align: center;
}

Some files were not shown because too many files have changed in this diff Show More