Update manager and add features for App Installer.

This commit is contained in:
Bruce
2026-01-31 22:03:03 +08:00
parent 0c87a2cdcd
commit d91948eaff
37 changed files with 3645 additions and 923 deletions
+29
View File
@@ -0,0 +1,29 @@
.statusbar {
overflow-x: hidden;
overflow-y: hidden;
}
.statusbar.x {
width: 0;
}
.statusbar.y {
height: 0;
}
.statusbar.both {
width: 0;
height: 0;
}
.statusbar.fast {
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.statusbar.medium {
transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.statusbar.slow {
transition: all 0.7s cubic-bezier(0.1, 0.9, 0.2, 1);
}
+14
View File
@@ -312,9 +312,15 @@
function hideTouchHide() {
touchHide.style.display = "none";
}
var timerHide = null;
this.show = function() {
try {
if (!_enable) return;
if (timerHide) {
clearTimeout(timerHide);
timerHide = null;
}
this.element.style.display = "";
if (!this.element.classList.contains("show"))
this.element.classList.add("show");
waitTimer(500);
@@ -323,8 +329,16 @@
};
this.hide = function() {
try {
if (timerHide) {
clearTimeout(timerHide);
timerHide = null;
}
if (this.element.classList.contains("show"))
this.element.classList.remove("show");
timerHide = setTimeout(function() {
timerHide = null;
self.element.style.display = "none";
}, 500);
waitTimer(500);
hideTouchHide();
} catch (e) {}
+16
View File
@@ -102,4 +102,20 @@
get: function() { return ext.System.UI.SplashImage; },
});
} catch (e) {}
// 下面是有关 String 方法的补充
if (typeof String.prototype.trim !== "function") {
String.prototype.trim = function() {
return Bridge.String.trim(this);
};
}
if (typeof String.prototype.toLowerCase !== "function") {
String.prototype.toLowerCase = function() {
return Bridge.String.tolower(this);
};
}
if (typeof String.prototype.toUpperCase !== "function") {
String.prototype.toUpperCase = function() {
return Bridge.String.toupper(this);
};
}
})(this);
+357 -27
View File
@@ -13,6 +13,7 @@
var childAnimeDuration = 120;
var parentAnimeDuration = 400;
function showItemAmine(node) {
return Windows.UI.Animation.runAsync(node, [
Windows.UI.Animation.Keyframes.Scale.up,
@@ -27,6 +28,23 @@
], childAnimeDuration);
}
function noAnime(node) {
return Promise.resolve(node);
}
function runShowAnime(node, enable) {
if (enable === void 0) enable = true;
if (!enable) return noAnime(node);
return showItemAmine(node);
}
function runHideAnime(node, enable) {
if (enable === void 0) enable = true;
if (!enable) return noAnime(node);
return hideItemAmine(node);
}
function updateItemAmine(node, updateCallback) {
return Windows.UI.Animation.runAsync(node, [
Windows.UI.Animation.Keyframes.Opacity.hidden,
@@ -53,6 +71,43 @@
function PMDataSource() {
var _list = [];
var _listeners = [];
var _keySelector = null;
var _autoKeySeed = 1;
this.setKeySelector = function(fn) {
_keySelector = (typeof fn === "function") ? fn : null;
};
function getKey(item) {
if (!item) return null;
// 用户提供
if (_keySelector) {
return _keySelector(item);
}
// 自动注入(对象)
if (typeof item === "object") {
if (item.__pm_key !== void 0) {
return item.__pm_key;
}
try {
Object.defineProperty(item, "__pm_key", {
value: "pm_" + (_autoKeySeed++),
enumerable: false
});
} catch (e) {
// IE10 兜底
item.__pm_key = "pm_" + (_autoKeySeed++);
}
return item.__pm_key;
}
// 原始类型兜底
return typeof item + ":" + item;
}
this.subscribe = function(fn) {
if (typeof fn === "function") {
_listeners.push(fn);
@@ -64,26 +119,47 @@
_listeners[i](evt);
}
}
this.indexOf = function(item) {
var key = getKey(item);
for (var i = 0; i < _list.length; i++) {
if (getKey(_list[i]) === key) {
return i;
}
}
return -1;
};
this.add = function(item) {
_list.push(item);
emit(new PMChangeEvent(
DataView.ChangeType.add, [item], { index: _list.length - 1 }
DataView.ChangeType.add, [{ item: item, index: _list.length - 1, key: getKey(item) }]
));
};
this.removeAt = function(index) {
if (index < 0 || index >= _list.length) return;
var item = _list.splice(index, 1)[0];
emit(new PMChangeEvent(
DataView.ChangeType.remove, [item], { index: index }
DataView.ChangeType.remove, [{ item: item, index: index, key: getKey(item) }]
));
};
this.remove = function(item) {
var index = this.indexOf(item);
if (index >= 0) {
this.removeAt(index);
}
};
this.changeAt = function(index, newItem) {
if (index < 0 || index >= _list.length) return;
_list[index] = newItem;
emit(new PMChangeEvent(
DataView.ChangeType.change, [newItem], { index: index }
DataView.ChangeType.change, [{ item: newItem, index: index, key: getKey(newItem) }]
));
};
this.change = function(oldItem, newItem) {
var index = this.indexOf(oldItem);
if (index >= 0) {
this.changeAt(index, newItem);
}
};
this.clear = function() {
_list.length = 0;
emit(new PMChangeEvent(
@@ -224,7 +300,6 @@
var changed = [];
var removed = [];
// 1️⃣ 找 remove
for (i = oldList.length - 1; i >= 0; i--) {
var oldItem = oldList[i];
var oldKey = getKey(oldItem);
@@ -238,7 +313,6 @@
}
}
// 2️⃣ 找 add / change
for (i = 0; i < newList.length; i++) {
var newItem = newList[i];
var newKey = getKey(newItem);
@@ -263,7 +337,6 @@
}
}
// 3️⃣ 执行 remove(从后往前)
if (removed.length > 0) {
for (i = 0; i < removed.length; i++) {
_list.splice(removed[i].index, 1);
@@ -274,7 +347,6 @@
));
}
// 4️⃣ 执行 add / change(重建顺序)
_list = newList.slice(0);
if (added.length > 0) {
@@ -291,25 +363,50 @@
));
}
};
this._getKey = getKey;
}
var MAX_ANIMATE_COUNT = 100;
function PMDataListView(container, templateFn) {
this.container = container;
this.templateFn = templateFn;
this.listViewControl = this;
this._emptyView = null;
// === 新增 ===
this._filter = null;
this._searchHandler = null;
this._searchText = null;
this._searchSuggestProvider = null;
this.onSearchSuggest = null; // function(text, list)
this._isSearching = false;
this.onsearchstart = null;
this.onsearchend = null;
}
PMDataListView.prototype.bind = function(ds) {
var self = this;
var items = ds.get();
this._ds = ds;
self.container.innerHTML = "";
var items = ds.get();
// 动画队列,保证异步操作不会乱序
var queue = Promise.resolve();
function renderItem(data, index) {
var el = self.templateFn(data, index);
var key = ds && ds._getKey ? ds._getKey(data) : null;
el.__pm_item = data;
el.__pm_key = key;
if (key != null) {
el.setAttribute("data-pm-key", key);
}
el.addEventListener("click", function() {
self._toggleSelect(el);
});
@@ -317,10 +414,13 @@
return el;
}
// 初始化渲染
for (var i = 0; i < items.length; i++) {
self.container.appendChild(renderItem(items[i], i));
}
// 初始化 emptyView 状态
self._updateEmptyView();
ds.subscribe(function(evt) {
@@ -337,37 +437,58 @@
var nodes = [];
for (var i = 0; i < datas.length; i++) {
var n = renderItem(datas[i].item, datas[i].index);
n.style.display = "none";
nodes.push(n);
self.container.appendChild(n);
}
// 如果数量>=20,动画并行,否则串行
if (datas.length >= 20) {
var enableAnime = datas.length <= MAX_ANIMATE_COUNT;
if (!enableAnime) {
return Promise.resolve();
}
// 如果数量>=20,动画串行,否则并行
if (datas.length <= 20) {
var promises = [];
for (var j = 0; j < nodes.length; j++) {
promises.push(showItemAmine(nodes[j]));
promises.push((function(node) {
node.style.display = "";
return showItemAmine(node);
})(nodes[j]));
}
return Promise.all(promises);
} else {
// 串行
var p = Promise.resolve();
var group = [];
for (var k = 0; k < nodes.length; k++) {
(function(node) {
p = p.then(function() {
group.push((function(node) {
node.style.display = "";
return showItemAmine(node);
});
})(nodes[k]);
})
(nodes[k]));
if (group.length === 20 || k === nodes.length - 1) {
(function(g) {
p = p.then(function() {
return Promise.join(g);
});
})(group);
group = [];
}
}
(function(g) {
p = p.then(function() {
return Promise.join(g);
});
})(group);
return p;
}
}
case DataView.ChangeType.remove:
{
var node = self.container.children[evt.detail.index];
var info = evt.datas[0];
var node = self._findNodeByKey(info.key);
if (!node) return;
// 隐藏动画完成后再移除
return hideItemAmine(node).then(function() {
self.container.removeChild(node);
});
@@ -375,29 +496,30 @@
case DataView.ChangeType.change:
{
var oldNode = self.container.children[evt.detail.index];
var info = evt.datas[0];
var oldNode = self._findNodeByKey(info.key);
if (!oldNode) return;
// 先淡出旧节点
return hideItemAmine(oldNode).then(function() {
// 替换节点
var newNode = renderItem(evt.datas[0], evt.detail.index);
var newNode = renderItem(info.item);
self.container.replaceChild(newNode, oldNode);
// 再淡入新节点
return showItemAmine(newNode);
});
}
case DataView.ChangeType.clear:
self.container.innerHTML = "";
return Promise.resolve();
case DataView.ChangeType.move:
{
var node = self.container.children[evt.detail.from];
var info = evt.datas[0];
var node = self._findNodeByKey(info.key);
if (!node) return;
var ref = self.container.children[evt.detail.to] || null;
if (node) self.container.insertBefore(node, ref);
self.container.insertBefore(node, ref);
return Promise.resolve();
}
@@ -410,9 +532,22 @@
return Promise.resolve();
}
}
promises.push(self._refreshVisibility());
return Promise.join(promises);
});
});
};
PMDataListView.prototype._findNodeByKey = function(key) {
if (key == null) return null;
var children = this.container.children;
for (var i = 0; i < children.length; i++) {
if (children[i].__pm_key === key) {
return children[i];
}
}
return null;
};
PMDataListView.prototype._toggleSelect = function(ele) {
// 如果选择模式为 none,则不处理
@@ -472,7 +607,202 @@
return Array.prototype.slice.call(this.container.querySelectorAll(".selected"));
}
});
PMDataListView.prototype._updateEmptyView = function() {
if (!this._emptyView) return;
// container 中是否还有 item
var hasItem = this.container.children.length > 0;
if (hasItem) {
if (this._emptyView.parentNode) {
this._emptyView.style.display = "none";
}
} else {
if (!this._emptyView.parentNode) {
this.container.appendChild(this._emptyView);
}
this._emptyView.style.display = "";
}
};
Object.defineProperty(PMDataListView.prototype, "emptyView", {
get: function() {
return this._emptyView;
},
set: function(value) {
// 只接受 HTMLElement 或 null / undefined
if (value !== null && value !== void 0 && !(value instanceof HTMLElement)) {
return;
}
// 移除旧的
if (this._emptyView && this._emptyView.parentNode) {
this._emptyView.parentNode.removeChild(this._emptyView);
}
this._emptyView = value || null;
// 设置后立刻刷新一次
this._updateEmptyView();
}
});
PMDataListView.prototype._isItemVisible = function(item) {
// 1️⃣ filter
if (this._filter) {
if (!this._filter(item)) return false;
}
// 2️⃣ search(自动启用 / 禁用)
var handler = this._searchHandler;
var text = this._searchText;
if (typeof handler === "function") {
if (text != null) {
text = ("" + text).replace(/^\s+|\s+$/g, "");
}
if (text && text.length > 0) {
if (!handler(text, item)) {
return false;
}
}
}
return true;
};
PMDataListView.prototype._refreshVisibility = function() {
var self = this;
var children = self.container.children;
var animes = [];
for (var i = 0; i < children.length; i++) {
(function(node) {
var item = node.__pm_item;
if (!item) return;
var visible = self._isItemVisible(item);
var enableAnime = animes.length < MAX_ANIMATE_COUNT;
if (visible) {
if (node.style.display === "none") {
node.style.display = "";
animes.push(runShowAnime(node, enableAnime));
}
} else {
if (node.style.display !== "none") {
// 移除选择状态
node.classList.remove("selected");
animes.push(runHideAnime(node, enableAnime).then(function() {
node.style.display = "none";
}));
}
}
})(children[i]);
}
return Promise.join(animes);
};
Object.defineProperty(PMDataListView.prototype, "filter", {
get: function() {
return this._filter;
},
set: function(fn) {
this._filter = (typeof fn === "function") ? fn : null;
this._refreshVisibility();
}
});
Object.defineProperty(PMDataListView.prototype, "searchHandler", {
get: function() {
return this._searchHandler;
},
set: function(fn) {
this._searchHandler = (typeof fn === "function") ? fn : null;
this._refreshVisibility();
}
});
Object.defineProperty(PMDataListView.prototype, "searchText", {
get: function() {
return this._searchText;
},
set: function(text) {
var oldText = this._searchText;
this._searchText = text;
var oldActive = !!(oldText && oldText.trim());
var newActive = !!(text && ("" + text).trim());
//if (!oldActive && newActive) {
this._isSearching = true;
this._emitSearchEvent("searchstart");
//}
var handler = this._searchHandler;
var provider = this._searchSuggestProvider;
var cb = this.onSearchSuggest;
var t = text;
if (t != null) {
t = ("" + t).replace(/^\s+|\s+$/g, "");
}
// 搜索建议
if (
typeof handler === "function" &&
t &&
t.length > 0 &&
typeof provider === "function" &&
typeof cb === "function"
) {
var list = provider(t);
if (list && list.length) {
cb(t, list.slice(0, 10));
}
}
var self = this;
var func = function() {
//if (oldActive && !newActive) {
self._isSearching = false;
self._emitSearchEvent("searchend");
//}
};
this._refreshVisibility().done(func, func);
}
});
Object.defineProperty(PMDataListView.prototype, "searchSuggestProvider", {
get: function() {
return this._searchSuggestProvider;
},
set: function(fn) {
this._searchSuggestProvider = (typeof fn === "function") ? fn : null;
}
});
Object.defineProperty(PMDataListView.prototype, "findItemLength", {
get: function() {
var count = 0;
var children = this.container.children;
for (var i = 0; i < children.length; i++) {
var item = children[i].__pm_item;
if (this._isItemVisible(item)) {
count++;
}
}
return count;
}
});
PMDataListView.prototype._emitSearchEvent = function(type) {
if (typeof this["on" + type] === "function") {
try {
this["on" + type].call(this);
} catch (e) {}
}
try {
var ev = document.createEvent("Event");
ev.initEvent(type, true, true);
this.container.dispatchEvent(ev);
} catch (e) {}
};
PMDataListView.prototype.refresh = function() {
this._refreshVisibility();
};
global.DataView.ChangeEvent = PMChangeEvent;
global.DataView.DataSource = PMDataSource;
global.DataView.ListView = PMDataListView;
+81 -3
View File
@@ -1,6 +1,7 @@
(function(global) {
"use strict";
var pkg_ns = external.Package;
var strres = external.StringResources;
function archsToStr(archs) {
var arr = [];
@@ -28,9 +29,23 @@
}
return arr.join(", ");
}
var showAppDetailTimer = null;
function updateAppDataSource(page, result, bar) {
try {
var json = result.json;
console.log(json);
page.appDataSource.updateList(json.applications);
} catch (e) {}
showAppDetailTimer = setTimeout(function() {
showAppDetailTimer = null;
bar.hide();
}, 3000);
}
function setAppInfoPageContent(info) {
var page = document.getElementById("page-appinfo");
page.data = info;
page.querySelector(".display-name").textContent = info.Properties.DisplayName;
page.querySelector(".publisher-display-name").textContent = info.Properties.Publisher;
page.querySelector(".version").textContent = info.Identity.Version.Expression;
@@ -42,9 +57,72 @@
page.querySelector(".identity .full-name").textContent = info.Identity.FullName;
page.querySelector(".identity .architecture").textContent = archsToStr(info.Identity.ProcessArchitecture);
var il = info.InstallLocation;
var pkg = pkg_ns.fromInstallLocation(il);
var json = pkg.jsonText;
console.log(JSON.parse(json));
try { page.appDataSource.clear(); } catch (e) {}
var appLoading = page.querySelector("#appinfo-loading");
appLoading.classList.remove("noloading");
if (showAppDetailTimer) clearTimeout(showAppDetailTimer);
if (typeof appLoading.bar === "undefined") {
appLoading.bar = new TransitionPanel(appLoading, {
axis: 'y',
duration: 500,
});
}
appLoading.bar.show();
var appLoadingStatus = page.querySelector(".title");
appLoadingStatus.textContent = strres.get("MANAGER_APP_INSTALLEDAPPS_LOADING");
return Package.reader.readFromInstallLocation(il, true).then(
function(result) {
try {
var displayNameNode = page.querySelector(".display-name");
displayNameNode.textContent = displayNameNode.textContent || result.json.properties.display_name;
if ((displayNameNode.textContent || "").indexOf("ms-resource:") === 0) {
displayNameNode.textContent = "";
}
if (result.json.applications.length === 1) {
displayNameNode.textContent = displayNameNode.textContent || result.json.applications[0].DisplayName || result.json.applications[0].ShortName;
}
if ((displayNameNode.textContent || "").indexOf("ms-resource:") === 0) {
displayNameNode.textContent = "";
}
if (result.json.applications.length === 1) {
displayNameNode.textContent = displayNameNode.textContent || result.json.applications[0].ShortName;
}
if ((displayNameNode.textContent || "").indexOf("ms-resource:") === 0) {
displayNameNode.textContent = "";
}
displayNameNode.textContent = displayNameNode.textContent || info.Identity.FamilyName;
} catch (e) {}
appLoadingStatus.textContent = strres.get("MANAGER_APP_INSTALLEDAPPS_SUCCEED");
appLoading.classList.add("noloading");
updateAppDataSource(page, result, appLoading.bar);
},
function(result) {
try {
var displayNameNode = page.querySelector(".display-name");
displayNameNode.textContent = displayNameNode.textContent || result.json.properties.display_name;
if ((displayNameNode.textContent || "").indexOf("ms-resource:") === 0) {
displayNameNode.textContent = "";
}
if (result.json.applications.length === 1) {
displayNameNode.textContent = displayNameNode.textContent || result.json.applications[0].DisplayName || result.json.applications[0].ShortName;
}
if ((displayNameNode.textContent || "").indexOf("ms-resource:") === 0) {
displayNameNode.textContent = "";
}
if (result.json.applications.length === 1) {
displayNameNode.textContent = displayNameNode.textContent || result.json.applications[0].ShortName;
}
if ((displayNameNode.textContent || "").indexOf("ms-resource:") === 0) {
displayNameNode.textContent = "";
}
displayNameNode.textContent = displayNameNode.textContent || info.Identity.FamilyName;
} catch (e) {}
var msg = result.message;
appLoadingStatus.textContent = external.String.format(strres.get("MANAGER_APP_INSTALLEDAPPS_FAILED"), msg);
appLoading.classList.add("noloading");
updateAppDataSource(page, result, appLoading.bar);
}
);
}
global.setAppInfoPageContent = setAppInfoPageContent;
})(this);
+441 -420
View File
@@ -1,369 +1,5 @@
(function(global) {
function _createImage(src, onload, onerror) {
var img = new Image();
img.onload = function() {
onload(img);
};
img.onerror = function() {
onerror && onerror();
};
img.src = src;
}
function getSolidOpaqueBackgroundColor(source, callback) {
function processImage(img) {
if (!img || !img.complete) {
callback(null);
return;
}
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.naturalWidth || img.width;
canvas.height = img.naturalHeight || img.height;
ctx.drawImage(img, 0, 0);
try {
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// 跨域导致的安全异常
callback(null);
return;
}
var data = imageData.data;
var w = canvas.width;
var h = canvas.height;
var colors = {};
var total = 0;
function pushColor(r, g, b, a) {
if (a !== 255) return;
var key = r + "," + g + "," + b;
colors[key] = (colors[key] || 0) + 1;
total++;
}
// top + bottom
for (var x = 0; x < w; x++) {
var topIndex = (0 * w + x) * 4;
var botIndex = ((h - 1) * w + x) * 4;
pushColor(data[topIndex], data[topIndex + 1], data[topIndex + 2], data[topIndex + 3]);
pushColor(data[botIndex], data[botIndex + 1], data[botIndex + 2], data[botIndex + 3]);
}
// left + right
for (var y = 1; y < h - 1; y++) {
var leftIndex = (y * w + 0) * 4;
var rightIndex = (y * w + (w - 1)) * 4;
pushColor(data[leftIndex], data[leftIndex + 1], data[leftIndex + 2], data[leftIndex + 3]);
pushColor(data[rightIndex], data[rightIndex + 1], data[rightIndex + 2], data[rightIndex + 3]);
}
if (total === 0) {
callback(null);
return;
}
var bestKey = null;
var bestCount = 0;
for (var key in colors) {
if (colors.hasOwnProperty(key)) {
if (colors[key] > bestCount) {
bestCount = colors[key];
bestKey = key;
}
}
}
// 95% 纯色阈值
if (bestCount / total < 0.95) {
callback(null);
return;
}
callback(bestKey);
}
// 如果传入的是 img 元素
if (source && source.tagName && source.tagName.toLowerCase() === "img") {
processImage(source);
return;
}
// 如果传入的是 data url 或普通 url
if (typeof source === "string") {
_createImage(source, processImage, function() {
callback(null);
});
return;
}
callback(null);
}
function getHamonyColor(source, callback) {
function _createImage(src, onload, onerror) {
var img = new Image();
img.onload = function() { onload(img); };
img.onerror = function() { onerror && onerror(); };
img.src = src;
}
function _toKey(r, g, b) {
return r + "," + g + "," + b;
}
function _rgbToHsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return { h: h, s: s, l: l };
}
function _hslToRgb(h, s, l) {
var r, g, b;
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
if (s === 0) {
r = g = b = l;
} else {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255)
};
}
function _lum(r, g, b) {
function f(x) {
x = x / 255;
return x <= 0.03928 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
}
function _contrast(a, b) {
var L1 = _lum(a.r, a.g, a.b);
var L2 = _lum(b.r, b.g, b.b);
var lighter = Math.max(L1, L2);
var darker = Math.min(L1, L2);
return (lighter + 0.05) / (darker + 0.05);
}
function _tryPureBackground(data, w, h) {
var edgeColors = {};
var edgeTotal = 0;
function push(r, g, b, a) {
if (a !== 255) return;
var k = _toKey(r, g, b);
edgeColors[k] = (edgeColors[k] || 0) + 1;
edgeTotal++;
}
for (var x = 0; x < w; x++) {
var top = (0 * w + x) * 4;
var bot = ((h - 1) * w + x) * 4;
push(data[top], data[top + 1], data[top + 2], data[top + 3]);
push(data[bot], data[bot + 1], data[bot + 2], data[bot + 3]);
}
for (var y = 1; y < h - 1; y++) {
var left = (y * w + 0) * 4;
var right = (y * w + (w - 1)) * 4;
push(data[left], data[left + 1], data[left + 2], data[left + 3]);
push(data[right], data[right + 1], data[right + 2], data[right + 3]);
}
if (edgeTotal === 0) return null;
var best = null,
bestCount = 0;
for (var k in edgeColors) {
if (edgeColors.hasOwnProperty(k) && edgeColors[k] > bestCount) {
bestCount = edgeColors[k];
best = k;
}
}
if (best && bestCount / edgeTotal >= 0.95) return best;
return null;
}
function _process(img) {
if (!img || !img.complete) { callback(null); return; }
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.naturalWidth || img.width;
canvas.height = img.naturalHeight || img.height;
ctx.drawImage(img, 0, 0);
var imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
callback(null);
return;
}
var data = imageData.data;
var w = canvas.width,
h = canvas.height;
// 1) 尝试纯色背景
var pure = _tryPureBackground(data, w, h);
if (pure) { callback(pure); return; }
// 2) 统计不透明像素(抽样)
var sumR = 0,
sumG = 0,
sumB = 0,
count = 0;
var samples = 0;
var step = 4; // 4x抽样,减少性能消耗
for (var y = 0; y < h; y += step) {
for (var x = 0; x < w; x += step) {
var i = (y * w + x) * 4;
var a = data[i + 3];
if (a === 255) {
sumR += data[i];
sumG += data[i + 1];
sumB += data[i + 2];
count++;
}
samples++;
}
}
if (count === 0) { callback(null); return; }
var avgR = sumR / count,
avgG = sumG / count,
avgB = sumB / count;
// 3) 生成候选色(借鉴流行配色)
var base = _rgbToHsl(avgR, avgG, avgB);
function clamp(v, min, max) { return Math.max(min, Math.min(max, v)); }
var candidates = [];
// 中性色(低饱和)
candidates.push(_hslToRgb(base.h, 0.05, 0.5));
candidates.push(_hslToRgb(base.h, 0.1, 0.6));
candidates.push(_hslToRgb(base.h, 0.1, 0.4));
// 平均色去饱和
candidates.push(_hslToRgb(base.h, clamp(base.s * 0.4, 0.05, 0.2), clamp(base.l, 0.2, 0.8)));
// 互补色(活泼)
candidates.push(_hslToRgb((base.h + 0.5) % 1, clamp(base.s * 0.6, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
// 类似色
candidates.push(_hslToRgb((base.h + 0.083) % 1, clamp(base.s * 0.5, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
candidates.push(_hslToRgb((base.h - 0.083 + 1) % 1, clamp(base.s * 0.5, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
// 三分色
candidates.push(_hslToRgb((base.h + 0.333) % 1, clamp(base.s * 0.6, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
candidates.push(_hslToRgb((base.h - 0.333 + 1) % 1, clamp(base.s * 0.6, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
// 4) 计算最小对比度(与所有不透明像素)
function minContrastWithImage(bg) {
var bgObj = { r: bg.r, g: bg.g, b: bg.b };
var minC = Infinity;
for (var y = 0; y < h; y += step) {
for (var x = 0; x < w; x += step) {
var i = (y * w + x) * 4;
if (data[i + 3] !== 255) continue;
var px = { r: data[i], g: data[i + 1], b: data[i + 2] };
var c = _contrast(bgObj, px);
if (c < minC) minC = c;
}
}
return minC;
}
var best = null;
for (var i = 0; i < candidates.length; i++) {
var c = candidates[i];
var minC = minContrastWithImage(c);
if (minC >= 4.5) {
best = c;
break;
}
}
if (best) {
callback(_toKey(best.r, best.g, best.b));
} else {
callback(null);
}
}
if (source && source.tagName && source.tagName.toLowerCase() === "img") {
_process(source);
} else if (typeof source === "string") {
_createImage(source, _process, function() { callback(null); });
} else {
callback(null);
}
}
function getSuitableBackgroundColor(source, callback) {
getSolidOpaqueBackgroundColor(source, function(color) {
if (color) {
callback(color);
} else {
getHamonyColor(source, callback);
}
});
}
var strres = external.StringResources;
function createLocalizedCompare(locale) {
return function(a, b) {
@@ -383,9 +19,17 @@
var mgr = Package.manager;
var nstr = Bridge.NString;
var datasrc = new DataView.DataSource();
datasrc.setKeySelector(function(item) {
if (item === null || item === void 0) return null;
return Bridge.String.tolower(Bridge.String.trim(item.Identity.FullName));
});
var themeColor = Bridge.UI.themeColor;
var loadingDisplay = document.getElementById("applist-loading");
var loadingStatus = loadingDisplay.querySelector(".title");
var emptyDisplay = document.createElement("div");
var dataLengthDisplay = document.getElementById("applist-datalen");
var appSearchList = document.getElementById("applist-search");
emptyDisplay.textContent = strres.get("MANAGER_MANAGE_LISTEMPTY");
var listView = new DataView.ListView(listContainer, function(item) {
var appItem = appItemTemplate.cloneNode(true);
appItem.id = "";
@@ -407,17 +51,102 @@
appItem.setAttribute("data-version", item.Identity.Version.Expression);
appItem.setAttribute("data-users", item.Users);
appItem.setAttribute("data-publisher-id", item.Identity.PublisherId);
setTimeout(function(a, b) {
getSolidOpaqueBackgroundColor(a, function(color) {
try {
var pipes = color.split(",");
var colorobj = new Color(parseInt(pipes[0]), parseInt(pipes[1]), parseInt(pipes[2]));
if (colorobj.hex == "#ffffff" || colorobj.hex == "#000000") throw "too white or black";
var rgbstr = colorobj.RGB.toString();
b.style.backgroundColor = rgbstr;
} catch (e) {}
});
}, 0, item.Properties.LogoBase64, logoimg.parentElement);
logoimg.parentElement.style.backgroundColor = item.BackgroundColor;
if (item.BackgroundColor === "transparent") {
logoimg.parentElement.style.backgroundColor = themeColor;
}
var uninstallButton = appItem.querySelector("div[role=control] .uninstall");
Windows.UI.Event.Util.addEvent(uninstallButton, "click", function(e) {
e.stopPropagation();
this.disabled = true;
var itemNode = this.parentNode.parentNode.parentNode;
var flyout = document.getElementById("app-uninstall-flyout");
if (typeof flyout.appDataSource !== "undefined") flyout.appDataSource.clear();
if (typeof flyout.appDataSource !== "undefined") {
Package.reader.readFromInstallLocation(this.parentNode.parentNode.parentNode.data.InstallLocation, true).then(function(result) {
try {
if (typeof result.json.applications === "undefined" || result.json.applications.length === 0) {
result.json.applications = [{
DisplayName: item.Properties.DisplayName || item.Identity.Name,
SmallLogo_Base64: item.Properties.LogoBase64,
}];
}
flyout.appDataSource.updateList(result.json.applications);
} catch (e) {}
}, function(result) {
try { flyout.appDataSource.updateList(result.json.applications); } catch (e) {}
});
}
var self = this;
var confirm = flyout.querySelector(".confirm");
confirm.onclick = null;
confirm.onclick = function() {
self.disabled = true;
flyout.winControl.hide();
var fullName = itemNode.getAttribute("data-full-name");
itemNode.classList.add("uninstalling");
var progressPart = itemNode.querySelector("div[role=progress]");
var statusDisplay = progressPart.querySelector(".status");
statusDisplay.textContent = strres.get("MANAGER_APP_UNINSTALL_ING");
var progressDisplay = progressPart.querySelector(".progress");
progressDisplay.removeAttribute("value");
self.disabled = true;
(function(itemNode, statusDisplay, progressDisplay, self) {
mgr.remove(fullName).then(function(_s) {
itemNode.classList.remove("uninstalling");
itemNode.classList.add("uninstalled");
if (_s.succeeded) {
statusDisplay.textContent = strres.get("MANAGER_APP_UNINSTALL_SUCCEED");
datasrc.remove(itemNode.data);
} else {
statusDisplay.textContent = _s.message;
setTimeout(function(iNode, uButton) {
iNode.classList.remove("uninstalled");
uButton.disabled = false;
}, 5000, itemNode, self);
}
}, function(_f) {
itemNode.classList.remove("uninstalling");
itemNode.classList.add("uninstalled");
try {
if (_f.succeeded) {
statusDisplay.textContent = strres.get("MANAGER_APP_UNINSTALL_SUCCEED");
datasrc.remove(itemNode.data);
} else {
statusDisplay.textContent = _f.message;
setTimeout(function(iNode, uButton) {
iNode.classList.remove("uninstalled");
uButton.disabled = false;
}, 5000, itemNode, self);
}
} catch (e) {
statusDisplay.textContent = e.message;
setTimeout(function(iNode, uButton) {
iNode.classList.remove("uninstalled");
uButton.disabled = false;
}, 5000, itemNode, self);
}
self.disabled = false;
}, function(_p) {
statusDisplay.textContent = Bridge.String.format(
strres.get("MANAGER_APP_UNINSTALL_PROGRESSING"),
_p
);
progressDisplay.value = _p;
});
})(itemNode, statusDisplay, progressDisplay, self);
};
var winFlyout = flyout.winControl;
if (winFlyout._beforehideHandler) {
winFlyout.removeEventListener("beforehide", winFlyout._beforehideHandler);
}
winFlyout._beforehideHandler = function() {
self.disabled = false;
};
winFlyout.addEventListener("beforehide", winFlyout._beforehideHandler);
flyout.winControl.show(this);
});
Windows.UI.Event.Util.addEvent(appItem.querySelector("div[role=advance] a"), "click", function(e) {
e.stopPropagation();
try {
@@ -428,93 +157,385 @@
});
listView.selectionMode = "single";
listView.bind(datasrc);
listView.emptyView = emptyDisplay;
listView.searchHandler = function(text, item) {
return ((item.Properties.DisplayName || item.Identity.Name || "") + (item.Properties.Publisher || "")).indexOf(text) >= 0;
};
appSearchList.control = new Search.Box(appSearchList, {
placeholderText: strres.get("MANAGER_MANAGE_SEARCHPLACEHOLDER"),
chooseSuggestionOnEnter: false
});
appSearchList.control.ontextchanged = function(ev) {
console.log(ev.text);
listView.searchText = ev.detail.text;
};
listView.onsearchend = function() {
dataLengthDisplay.textContent = external.String.format(strres.get("MANAGER_MANAGE_FINDAPPS"), listView.findItemLength);
};
var timer = null;
function refreshAppList() {
dataLengthDisplay.textContent = "";
function processData(manifest, dataitem) {
//if (dataitem.Identity.FamilyName = "Microsoft.MicrosoftEdge.Stable_8wekyb3d8bbwe") debugger;
dataitem.Properties.DisplayName = dataitem.Properties.DisplayName || manifest.properties.display_name || dataitem.Properties.DisplayName;
if ((dataitem.Properties.DisplayName || "").indexOf("ms-resource:") === 0) {
dataitem.Properties.DisplayName = "";
}
if (manifest.applications.length === 1) {
dataitem.Properties.DisplayName = dataitem.Properties.DisplayName || manifest.applications[0].DisplayName || "";
}
if ((dataitem.Properties.DisplayName || "").indexOf("ms-resource:") === 0) {
dataitem.Properties.DisplayName = "";
}
if (manifest.applications.length === 1) {
dataitem.Properties.DisplayName = dataitem.Properties.DisplayName || manifest.applications[0].ShortName || "";
}
if ((dataitem.Properties.DisplayName || "").indexOf("ms-resource:") === 0) {
dataitem.Properties.DisplayName = "";
}
dataitem.Properties.DisplayName = dataitem.Properties.DisplayName || dataitem.Identity.FamilyName;
dataitem.Properties.Puvlisher = dataitem.Properties.Publisher || manifest.properties.publisher_display_name || dataitem.Properties.Publisher;
dataitem.Properties.Framework = dataitem.Properties.Framework || manifest.properties.framework;
dataitem.Properties.Logo = dataitem.Properties.Logo || manifest.properties.logo;
dataitem.Properties.LogoBase64 = dataitem.Properties.LogoBase64 || manifest.properties.logo_base64;
if (manifest.applications.length === 1) {
dataitem.Properties.LogoBase64 = dataitem.Properties.LogoBase64 || manifest.applications[0].Square44x44Logo_Base64 || manifest.applications[0].SmallLogo_Base64;
}
dataitem.Properties.ResourcePackage = dataitem.Properties.ResourcePackage || manifest.properties.resource_package;
dataitem.Properties.Description = dataitem.Properties.Description || manifest.properties.description;
try {
dataitem.BackgroundColor = manifest.applications[0].BackgroundColor || "transparent";
} catch (e) {
dataitem.BackgroundColor = "transparent";
}
return dataitem;
}
function update(datas) {
var newDatas = [];
var promises = [];
for (var i = 0; i < datas.length; i++) {
var data = datas[i];
if (data.Properties.Framework) continue; // 过滤依赖项
var isfind = false; // 过滤系统应用
for (var j = 0; data && data.Users && j < data.Users.length; j++) {
if (Bridge.NString.equals(data.Users[j], "NT AUTHORITY\\SYSTEM")) {
isfind = true;
break;
if (external.System.isWindows10) {
if (data.Properties.DisplayName === null || data.Properties.DisplayName === "" || data.Properties.DisplayName === void 0 ||
data.Properties.LogoBase64 === null || data.Properties.LogoBase64 === "" || data.Properties.LogoBase64 === void 0
) {
promises.push(function(item, arr) {
return Package.reader.readFromInstallLocation(item.InstallLocation, true).then(function(result) {
try {
arr.push(processData(result.json, item));
} catch (e) {
item.BackgroundColor = "transparent";
arr.push(item);
}
}, function(result) {
try {
arr.push(processData(result.json, item));
} catch (e) {
item.BackgroundColor = "transparent";
arr.push(item);
}
});
}(data, newDatas));
} else {
promises.push(function(item, arr) {
return Package.reader.readFromInstallLocation(item.InstallLocation, false).then(function(result) {
try {
item.BackgroundColor = result.json.applications[0].BackgroundColor;
arr.push(item);
} catch (e) {
item.BackgroundColor = "transparent";
arr.push(item);
}
}, function(result) {
try {
item.BackgroundColor = result.json.applications[0].BackgroundColor;
arr.push(item);
} catch (e) {
item.BackgroundColor = "transparent";
arr.push(item);
}
});
}(data, newDatas));
}
} else {
promises.push(function(item, arr) {
return Package.reader.readFromInstallLocation(item.InstallLocation, true).then(function(result) {
try {
arr.push(processData(result.json, item));
} catch (e) {
item.BackgroundColor = "transparent";
arr.push(item);
}
}, function(result) {
try {
arr.push(processData(result.json, item));
} catch (e) {
item.BackgroundColor = "transparent";
arr.push(item);
}
});
}(data, newDatas));
}
}
function updateDatas() {
datasrc.updateList(newDatas, function(item) {
return item.Identity.FullName || "";
});
var compare = function(a, b) { return a - b; };
try {
compare = createLocalizedCompare(external.System.Locale.currentLocale);
} catch (e) {
try {
compare = createLocalizedCompare(navigator.language);
} catch (e) {
compare = function(a, b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
};
}
}
if (isfind) continue;
newDatas.push(data);
datasrc.sort(function(a, b) {
return compare(a.Properties.DisplayName, b.Properties.DisplayName);
});
dataLengthDisplay.textContent = external.String.format(strres.get("MANAGER_MANAGE_FINDAPPS"), listView.findItemLength);
}
datasrc.updateList(newDatas, function(item) {
return item.Identity.FullName || "";
});
var compare = function(a, b) { return a - b; };
try {
compare = createLocalizedCompare(external.System.Locale.currentLocale);
} catch (e) {
try {
compare = createLocalizedCompare(navigator.language);
} catch (e) {
compare = function(a, b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
};
}
}
datasrc.sort(function(a, b) {
return compare(a.Properties.DisplayName, b.Properties.DisplayName);
});
return Promise.join(promises).then(updateDatas, updateDatas);
}
if (timer) clearTimeout(timer);
timer = null;
loadingDisplay.style.display = "";
loadingDisplay.classList.remove("noloading");
loadingDisplay.bar.show();
function waitAndHide() {
if (timer) clearTimeout(timer);
timer = null;
timer = setTimeout(function() {
loadingDisplay.style.display = "none";
}, 10000);
return new Promise(function(resolve, reject) {
if (timer) clearTimeout(timer);
timer = null;
timer = setTimeout(function(rs, rj) {
//loadingDisplay.style.display = "none";
loadingDisplay.bar.hide();
rs();
}, 5000, resolve, reject);
});
}
loadingStatus.textContent = "正在加载数据...";
loadingStatus.textContent = strres.get("MANAGER_APP_INSTALLEDAPPS_LOADING");
return mgr.get().then(function(result) {
loadingDisplay.classList.add("noloading");
loadingStatus.textContent = "已经加载了所有数据";
update(result.list);
waitAndHide();
return update(result.list).then(function() {
loadingDisplay.classList.add("noloading");
loadingStatus.textContent = strres.get("MANAGER_APP_INSTALLEDAPPS_SUCCEED");
setTimeout(function(lv) {
lv.refresh();
}, 500, listView);
}).then(waitAndHide);
}, function(error) {
loadingDisplay.classList.add("noloading");
loadingStatus.textContent = "更新时出错: " + (error.result ? (error.result.message || error.result.ErrorCode || "获取失败") : (error.message || error.error || error));
var errmsg = (error.result ? (error.result.message || error.result.ErrorCode || "获取失败") : (error.message || error.error || error));
loadingStatus.textContent = external.String.format(strres.get("MANAGER_APP_INSTALLEDAPPS_FAILED"), errmsg);
try { update(error.list); } catch (e) {}
waitAndHide();
})
setTimeout(function(lv) {
lv.refresh();
}, 500, listView);
return waitAndHide();
});
}
var appbar = document.getElementById("appBar");
var appbarControl = new AppBar.AppBar(appbar);
var refreshButton = new AppBar.Command();
refreshButton.icon = "&#57623;";
refreshButton.label = "刷新";
refreshButton.label = strres.get("MANAGER_APP_REFRESH");
global.refreshAppList2 = function refreshAppList2() {
appbarControl.hide();
refreshButton.disabled = true;
refreshAppList().done(function() {
return refreshAppList().then(function() {
refreshButton.disabled = false;
}, function(error) {
refreshButton.disabled = false;
});
}
var showSystemApps = document.getElementById("applist-showsystemapp");
var showFrameworks = document.getElementById("applist-showframework");
listView.filter = function(item) {
try {
if (!showFrameworks.checked && item.Properties.Framework) return false;
if (!showSystemApps.checked && item.Users.indexOf("NT AUTHORITY\\SYSTEM") !== -1) return false;
return true;
} catch (e) {
return false;
}
};
Windows.UI.Event.Util.addEvent(showSystemApps, "change", function() {
listView.refresh();
dataLengthDisplay.textContent = external.String.format(strres.get("MANAGER_MANAGE_FINDAPPS"), listView.findItemLength);
});
Windows.UI.Event.Util.addEvent(showFrameworks, "change", function() {
listView.refresh();
dataLengthDisplay.textContent = external.String.format(strres.get("MANAGER_MANAGE_FINDAPPS"), listView.findItemLength);
});
refreshButton.addEventListener("click", refreshAppList2);
appbarControl.add(refreshButton);
refreshAppList2();
var appDetailPage = document.getElementById("page-appinfo");
pagemgr.register("manager", document.getElementById("tag-manager"), document.getElementById("page-manager"));
pagemgr.register("appinfo", document.getElementById("tag-appinfo"), document.getElementById("page-appinfo"), setAppInfoPageContent);
var appinfoBackPage = document.getElementById("page-appinfo").querySelector(".win-backbutton");
var appinfoBackPage = appDetailPage.querySelector(".win-backbutton");
Windows.UI.Event.Util.addEvent(appinfoBackPage, "click", function(e) {
pagemgr.back();
});
appDetailPage.appDataSource = new DataView.DataSource();
var appListView = new DataView.ListView(appDetailPage.querySelector(".apps"), function(item) {
var appItem = appItemTemplate.cloneNode(true);
appItem.id = "";
appItem.style.display = "";
var logoimg = appItem.querySelector("img");
logoimg.src = item.Square44x44Logo_Base64 || item.SmallLogo_Base64;
if (logoimg.src == "" || logoimg.src == null || logoimg.src == void 0) logoimg.removeAttribute("src");
logoimg.parentElement.style.backgroundColor = item.BackgroundColor;
if (Bridge.NString.equals(item.BackgroundColor, "transparent")) logoimg.parentElement.style.backgroundColor = themeColor;
var appName = appItem.querySelector(".displayName");
appName.textContent = item.DisplayName || item.ShortName;
var appPub = appItem.querySelector(".publisher");
appPub.style.display = "none";
appItem.querySelector("div[role=advance]").style.display = "none";
var ctrls = appItem.querySelector("div[role=control]");
ctrls.innerHTML = "";
appItem.data = item;
var launchButton = document.createElement("button");
launchButton.textContent = strres.get("MANAGER_APP_LAUNCH");
launchButton.setAttribute("data-app-user-model-id", item.AppUserModelID);
var createShortcutButton = document.createElement("button");
createShortcutButton.textContent = strres.get("MANAGER_APP_CREATESHORTCUT");
createShortcutButton.style.marginRight = "10px";
Windows.UI.Event.Util.addEvent(launchButton, "click", function(e) {
e.stopPropagation();
Package.manager.active(this.getAttribute("data-app-user-model-id"));
});
ctrls.appendChild(launchButton);
ctrls.appendChild(createShortcutButton);
return appItem;
});
appListView.selectionMode = "single";
appListView.bind(appDetailPage.appDataSource);
appListView.emptyView = emptyDisplay.cloneNode(true);
var appDetailUninstall = appDetailPage.querySelector("#detail-uninstall-btn");
var appDetailUninstallStatusBlock = appDetailPage.querySelector("#appinfo-uninstallstatus");
var appDetailUninstallProgress = appDetailUninstallStatusBlock.querySelector(".progress");
var appDetailUninstallProgressStatus = appDetailUninstallStatusBlock.querySelector(".status");
appDetailUninstallStatusBlock.bar = new TransitionPanel(appDetailUninstallStatusBlock, {
axis: 'y',
duration: 500,
});
Windows.UI.Event.Util.addEvent(appDetailUninstall, "click", function(e) {
e.stopPropagation();
appinfoBackPage.disabled = true;
appDetailUninstallProgress.removeAttribute("value");
var item = appDetailPage.data;
var flyout = document.getElementById("app-uninstall-flyout");
if (typeof flyout.appDataSource !== "undefined") flyout.appDataSource.clear();
if (typeof flyout.appDataSource !== "undefined") {
flyout.appDataSource.updateList(appDetailPage.appDataSource.get());
}
var self = this;
var confirm = flyout.querySelector(".confirm");
confirm.onclick = null;
confirm.onclick = function() {
self.disabled = true;
flyout.winControl.hide();
var fullName = item.Identity.FullName;
var progressPart = appDetailUninstallStatusBlock;
var statusDisplay = appDetailUninstallProgressStatus;
statusDisplay.textContent = strres.get("MANAGER_APP_UNINSTALL_ING");
var progressDisplay = appDetailUninstallProgress;
progressDisplay.style.display = "";
self.disabled = true;
progressPart.bar.show();
(function(statusDisplay, progressDisplay, self, item) {
mgr.remove(fullName).then(function(_s) {
if (_s.succeeded) {
statusDisplay.textContent = strres.get("MANAGER_APP_UNINSTALL_SUCCEED");
datasrc.remove(item);
appinfoBackPage.disabled = false;
} else {
statusDisplay.textContent = _s.message;
}
setTimeout(function(uButton, isSuccess) {
appinfoBackPage.disabled = false;
uButton.disabled = isSuccess;
progressPart.bar.hide();
}, 5000, self, _s.succeeded);
progressDisplay.style.display = "none";
}, function(_f) {
try {
if (_f.succeeded) {
statusDisplay.textContent = strres.get("MANAGER_APP_UNINSTALL_SUCCEED");
datasrc.remove(item);
appinfoBackPage.disabled = false;
} else {
statusDisplay.textContent = _f.message;
}
setTimeout(function(uButton, isSuccess) {
appinfoBackPage.disabled = false;
uButton.disabled = isSuccess;
progressPart.bar.hide();
}, 5000, self, _f.succeeded);
} catch (e) {
statusDisplay.textContent = e.message;
appinfoBackPage.disabled = false;
setTimeout(function(uButton, isSuccess) {
appinfoBackPage.disabled = false;
uButton.disabled = isSuccess;
progressPart.bar.hide();
}, 5000, self, _f.succeeded);
}
self.disabled = false;
progressDisplay.style.display = "none";
}, function(_p) {
statusDisplay.textContent = Bridge.String.format(
strres.get("MANAGER_APP_UNINSTALL_PROGRESSING"),
_p
);
progressDisplay.value = _p;
});
})(statusDisplay, progressDisplay, self, item);
};
var winFlyout = flyout.winControl;
if (winFlyout._beforehideHandler) {
winFlyout.removeEventListener("beforehide", winFlyout._beforehideHandler);
}
winFlyout._beforehideHandler = function() {
self.disabled = false;
};
winFlyout.addEventListener("beforehide", winFlyout._beforehideHandler);
flyout.winControl.show(this);
});
var uninstallFlyout = document.getElementById("app-uninstall-flyout");
uninstallFlyout.appListView = new DataView.ListView(uninstallFlyout.querySelector(".applist"), function(item) {
var appItem = appItemTemplate.cloneNode(true);
appItem.id = "";
appItem.style.display = "";
var logoimg = appItem.querySelector("img");
logoimg.src = item.Square44x44Logo_Base64 || item.SmallLogo_Base64;
if (logoimg.src == "" || logoimg.src == null || logoimg.src == void 0) logoimg.removeAttribute("src");
logoimg.parentElement.style.backgroundColor = item.BackgroundColor;
if (Bridge.NString.equals(item.BackgroundColor, "transparent")) logoimg.parentElement.style.backgroundColor = themeColor;
var appName = appItem.querySelector(".displayName");
appName.style.wordBreak = "normal";
appName.style.wordWrap = "normal";
appName.textContent = item.DisplayName || item.ShortName;
var appPub = appItem.querySelector(".publisher");
appPub.style.display = "none";
appItem.querySelector("div[role=advance]").style.display = "none";
var ctrls = appItem.querySelector("div[role=control]");
ctrls.innerHTML = "";
appItem.data = item;
return appItem;
});
uninstallFlyout.appDataSource = new DataView.DataSource();
uninstallFlyout.appListView.bind(uninstallFlyout.appDataSource);
pagemgr.addEventListener("load", function(e) {
appbarControl.enabled = e == "manager";
refreshButton.style.display = e == "manager" ? "" : "none";
+40 -33
View File
@@ -16,7 +16,44 @@
if (callback) callback(ret);
}
global.Package = {
reader: function(pkgPath) { return external.Package.reader(pkgPath); },
reader: {
package: function(pkgPath) { return external.Package.Reader.package(pkgPath); },
manifest: function(swManifestPath) { return external.Package.Reader.manifest(swManifestPath); },
manifestFromInstallLocation: function(swInstallLocation) { return external.Package.Reader.fromInstallLocation(swInstallLocation); },
readFromPackage: function(swPkgPath, bUsePri) {
if (bUsePri === null || bUsePri === void 0) bUsePri = false;
return new Promise(function(resolve, reject) {
external.Package.Reader.readFromPackageAsync(swPkgPath, bUsePri, function(result) {
parseJsonCallback(result, resolve);
}, function(error) {
parseJsonCallback(error, reject);
});
});
},
readFromManifest: function(swManifestPath, bUsePri) {
if (bUsePri === null || bUsePri === void 0) bUsePri = false;
return new Promise(function(resolve, reject) {
external.Package.Reader.readFromManifestAsync(swManifestPath, bUsePri, function(result) {
parseJsonCallback(result, resolve);
}, function(error) {
parseJsonCallback(error, reject);
});
});
},
readFromInstallLocation: function(swInstallLocation, bUsePri) {
if (bUsePri === null || bUsePri === void 0) bUsePri = false;
return new Promise(function(resolve, reject) {
external.Package.Reader.readFromInstallLocationAsync(swInstallLocation, bUsePri, function(result) {
parseJsonCallback(result, resolve);
}, function(error) {
parseJsonCallback(error, reject);
});
});
},
cancelAll: function() { external.Package.Reader.cancelAll(); },
addApplicationReadItem: function(swItemName) { return external.Package.Reader.addApplicationItem(swItemName); },
removeApplicationReadItem: function(swItemName) { return external.Package.Reader.removeApplicationItem(swItemName); }
},
manager: {
add: function(swPkgPath, uOptions) {
return new Promise(function(resolve, reject, progress) {
@@ -129,38 +166,8 @@
});
});
},
},
manifest: function(swManifestPath) { return external.Package.manifest(swManifestPath); },
manifestFromInstallLocation: function(swInstallLocation) { return external.Package.fromInstallLocation(swInstallLocation); },
readFromPackage: function(swPkgPath, bUsePri) {
if (bUsePri === null || bUsePri === void 0) bUsePri = false;
return new Promise(function(resolve, reject) {
external.Package.readFromPackageAsync(swPkgPath, bUsePri, function(result) {
parseJsonCallback(result, resolve);
}, function(error) {
parseJsonCallback(error, reject);
});
});
},
readFromManifest: function(swPkgPath, bUsePri) {
if (bUsePri === null || bUsePri === void 0) bUsePri = false;
return new Promise(function(resolve, reject) {
external.Package.readFromManifestAsync(swPkgPath, bUsePri, function(result) {
parseJsonCallback(result, resolve);
}, function(error) {
parseJsonCallback(error, reject);
});
});
},
readFromInstallLocation: function(swPkgPath, bUsePri) {
if (bUsePri === null || bUsePri === void 0) bUsePri = false;
return new Promise(function(resolve, reject) {
external.Package.readFromInstallLocationAsync(swPkgPath, bUsePri, function(result) {
parseJsonCallback(result, resolve);
}, function(error) {
parseJsonCallback(error, reject);
});
});
cancelAll: function() { mgr.cancelAll(); },
active: function(swAppUserModelID, swArgs) { return mgr.activeApp(swAppUserModelID, swArgs || null); }
},
};
})(this);
+15 -1
View File
@@ -13,7 +13,11 @@
var byName = el.getAttribute('data-res-byname');
var byId = el.getAttribute('data-res-byid');
var fromFile = el.getAttribute('data-res-fromfile');
if ((byName && !Bridge.NString.empty(byName)) || (byId && parseInt(byId, 10) > 0) || (fromFile && !Bridge.NString.empty(fromFile))) {
var byXml = el.getAttribute('data-res-resxml');
if ((byName && !Bridge.NString.empty(byName)) ||
(byId && parseInt(byId, 10) > 0) ||
(fromFile && !Bridge.NString.empty(fromFile)) ||
(byXml && !Bridge.NString.empty(byXml))) {
result.push(el);
}
}
@@ -47,6 +51,16 @@
} catch (e) {
nodes[i].textContent = "";
}
} else if (nodes[i].hasAttribute('data-res-resxml')) {
try {
var obj = nodes[i].getAttribute('data-res-resxml');
var strres = external.StringResources;
if (strres && strres.isValid) {
nodes[i].textContent = strres.get(obj);
}
} catch (e) {
nodes[i].textContent = "";
}
} else {
nodes[i].textContent = "";
}
+720
View File
@@ -0,0 +1,720 @@
/*!
* Search.Box - standalone SearchBox control (ES5, IE10 compatible)
* Exposes constructor as global.Search.Box
*
* Features:
* - API compatible-ish with WinJS.UI.SearchBox: properties (placeholderText, queryText, chooseSuggestionOnEnter, disabled)
* - Events: querychanged, querysubmitted, resultsuggestionchosen, suggestionsrequested
* - supports both `element.addEventListener("querychanged", handler)` and `instance.onquerychanged = handler`
* - Methods: setSuggestions(array), clearSuggestions(), dispose(), setLocalContentSuggestionSettings(settings) (noop)
* - Suggestions kinds: Query (0), Result (1), Separator (2) OR string names 'query'/'result'/'separator'
* - Hit highlighting: uses item.hits if provided, otherwise simple substring match of current input
* - No WinRT / WinJS dependency
*
* Usage:
* var box = new Search.Box(hostElement, options);
* box.setSuggestions([{ kind: 0, text: "hello" }, ...]);
*/
(function(global) {
"use strict";
// Ensure namespace
if (!global.Search) {
global.Search = {};
}
// Suggestion kinds
var SuggestionKind = {
Query: 0,
Result: 1,
Separator: 2
};
// Utility: create id
function uniqueId(prefix) {
return prefix + Math.random().toString(36).slice(2);
}
// Simple CustomEvent fallback for IE10
function createCustomEvent(type, detail) {
var ev;
try {
ev = document.createEvent("CustomEvent");
ev.initCustomEvent(type, true, true, detail || {});
} catch (e) {
ev = document.createEvent("Event");
ev.initEvent(type, true, true);
ev.detail = detail || {};
}
return ev;
}
// Constructor
function SearchBox(element, options) {
element = element || document.createElement("div");
if (element.__searchBoxInstance) {
throw new Error("Search.Box: duplicate construction on same element");
}
element.__searchBoxInstance = this;
// DOM elements
this._root = element;
this._input = document.createElement("input");
this._input.type = "search";
this._button = document.createElement("div");
this._button.tabIndex = -1;
this._flyout = document.createElement("div");
this._repeater = document.createElement("div"); // container for suggestion items
this._flyout.style.display = "none";
// state
this._suggestions = [];
this._currentSelectedIndex = -1; // fake focus/selection index
this._currentFocusedIndex = -1; // navigation focus index
this._prevQueryText = "";
this._chooseSuggestionOnEnter = false;
this._disposed = false;
this._lastKeyPressLanguage = "";
// classes follow WinJS naming where convenient (so your existing CSS can still be used)
this._root.className = (this._root.className ? this._root.className + " " : "") + "win-searchbox";
this._input.className = "win-searchbox-input";
this._button.className = "win-searchbox-button";
this._flyout.className = "win-searchbox-flyout";
this._repeater.className = "win-searchbox-repeater";
// assemble
this._flyout.appendChild(this._repeater);
this._root.appendChild(this._input);
this._root.appendChild(this._button);
this._root.appendChild(this._flyout);
// accessibility basics
this._root.setAttribute("role", "group");
this._input.setAttribute("role", "textbox");
this._button.setAttribute("role", "button");
this._repeater.setAttribute("role", "listbox");
if (!this._repeater.id) {
this._repeater.id = uniqueId("search_repeater_");
}
this._input.setAttribute("aria-controls", this._repeater.id);
this._repeater.setAttribute("aria-live", "polite");
// user-assignable event handlers (older style)
this.onquerychanged = null;
this.onquerysubmitted = null;
this.onresultsuggestionchosen = null;
this.onsuggestionsrequested = null;
// wire events
this._wireEvents();
// options
options = options || {};
if (options.placeholderText) this.placeholderText = options.placeholderText;
if (options.queryText) this.queryText = options.queryText;
if (options.chooseSuggestionOnEnter) this.chooseSuggestionOnEnter = !!options.chooseSuggestionOnEnter;
if (options.disabled) this.disabled = !!options.disabled;
// new events
this.ontextchanged = null;
}
// Prototype
SearchBox.prototype = {
// Properties
get element() {
return this._root;
},
get placeholderText() {
return this._input.placeholder;
},
set placeholderText(value) {
this._input.placeholder = value || "";
},
get queryText() {
return this._input.value;
},
set queryText(value) {
this._input.value = value == null ? "" : value;
},
get chooseSuggestionOnEnter() {
return this._chooseSuggestionOnEnter;
},
set chooseSuggestionOnEnter(v) {
this._chooseSuggestionOnEnter = !!v;
this._updateButtonClass();
},
get disabled() {
return !!this._input.disabled;
},
set disabled(v) {
var val = !!v;
if (val === this.disabled) return;
this._input.disabled = val;
try { this._button.disabled = val; } catch (e) {}
if (val) {
this._root.className = (this._root.className + " win-searchbox-disabled").trim();
this.hideFlyout();
} else {
this._root.className = this._root.className.replace(/\bwin-searchbox-disabled\b/g, "").trim();
}
},
// Public methods
setSuggestions: function(arr) {
// Expect array of objects with keys: kind (0/1/2 or 'query'/'result'/'separator'), text, detailText, tag, imageUrl, hits
this._suggestions = (arr && arr.slice(0)) || [];
this._currentSelectedIndex = -1;
this._currentFocusedIndex = -1;
this._renderSuggestions();
if (this._suggestions.length) this.showFlyout();
else this.hideFlyout();
},
clearSuggestions: function() {
this.setSuggestions([]);
},
showFlyout: function() {
if (!this._suggestions || this._suggestions.length === 0) return;
this._flyout.style.display = "block";
this._updateButtonClass();
},
hideFlyout: function() {
this._flyout.style.display = "none";
this._updateButtonClass();
},
dispose: function() {
if (this._disposed) return;
// detach event listeners by cloning elements (simple way)
var newRoot = this._root.cloneNode(true);
if (this._root.parentNode) {
this._root.parentNode.replaceChild(newRoot, this._root);
}
try {
delete this._root.__searchBoxInstance;
} catch (e) {}
this._disposed = true;
},
setLocalContentSuggestionSettings: function(settings) {
// No-op in non-WinRT environment; kept for API compatibility.
},
// Internal / rendering
_wireEvents: function() {
var that = this;
this._input.addEventListener("input", function(ev) {
that._onInputChange(ev);
}, false);
this._input.addEventListener("keydown", function(ev) {
that._onKeyDown(ev);
}, false);
this._input.addEventListener("keypress", function(ev) {
// capture locale if available
try { that._lastKeyPressLanguage = ev.locale || that._lastKeyPressLanguage; } catch (e) {}
}, false);
this._input.addEventListener("focus", function() {
if (that._suggestions.length) {
that.showFlyout();
that._updateFakeFocus();
}
that._root.className = (that._root.className + " win-searchbox-input-focus").trim();
that._updateButtonClass();
}, false);
this._input.addEventListener("blur", function() {
// small timeout to allow suggestion click to process
setTimeout(function() {
if (!that._root.contains(document.activeElement)) {
that.hideFlyout();
that._root.className = that._root.className.replace(/\bwin-searchbox-input-focus\b/g, "").trim();
that._currentFocusedIndex = -1;
that._currentSelectedIndex = -1;
}
}, 0);
}, false);
this._button.addEventListener("click", function(ev) {
that._input.focus();
that._submitQuery(that._input.value, ev);
that.hideFlyout();
}, false);
// delegate click for suggestions: attach on repeater container (works in IE10)
this._repeater.addEventListener("click", function(ev) {
var el = ev.target;
// climb until we find child with data-index
while (el && el !== that._repeater) {
if (el.hasAttribute && el.hasAttribute("data-index")) break;
el = el.parentNode;
}
if (el && el !== that._repeater) {
var idx = parseInt(el.getAttribute("data-index"), 10);
var item = that._suggestions[idx];
if (item) {
that._input.focus();
that._processSuggestionChosen(item, ev);
}
}
}, false);
},
_onInputChange: function(ev) {
if (this.disabled) return;
var v = this._input.value;
this._emit("textchanged", {
text: v
}, this.ontextchanged);
var changed = (v !== this._prevQueryText);
this._prevQueryText = v;
// fire querychanged
var evDetail = {
language: this._getBrowserLanguage(),
queryText: v,
linguisticDetails: { queryTextAlternatives: [], queryTextCompositionStart: 0, queryTextCompositionLength: 0 }
};
this._emit("querychanged", evDetail, this.onquerychanged);
// fire suggestionsrequested - allow client to call setSuggestions
var suggestionsDetail = {
queryText: v,
language: this._getBrowserLanguage(),
setSuggestions: (function(thatRef) {
return function(arr) {
thatRef.setSuggestions(arr || []);
};
})(this)
};
this._emit("suggestionsrequested", suggestionsDetail, this.onsuggestionsrequested);
},
_submitQuery: function(queryText, ev) {
var detail = {
language: this._getBrowserLanguage(),
queryText: queryText,
keyModifiers: this._getKeyModifiers(ev)
};
this._emit("querysubmitted", detail, this.onquerysubmitted);
},
_processSuggestionChosen: function(item, ev) {
// normalize kind
var kind = item.kind;
if (typeof kind === "string") {
if (kind.toLowerCase() === "query") kind = SuggestionKind.Query;
else if (kind.toLowerCase() === "result") kind = SuggestionKind.Result;
else if (kind.toLowerCase() === "separator") kind = SuggestionKind.Separator;
}
this.queryText = item.text || "";
if (kind === SuggestionKind.Query || kind === undefined) {
// choose query -> submit
this._submitQuery(item.text || "", ev);
} else if (kind === SuggestionKind.Result) {
this._emit("resultsuggestionchosen", {
tag: item.tag,
keyModifiers: this._getKeyModifiers(ev),
storageFile: null
}, this.onresultsuggestionchosen);
}
this.hideFlyout();
},
_renderSuggestions: function() {
// clear repeater
while (this._repeater.firstChild) this._repeater.removeChild(this._repeater.firstChild);
var frag = document.createDocumentFragment();
for (var i = 0; i < this._suggestions.length; i++) {
var s = this._suggestions[i];
var itemEl = this._renderSuggestion(s, i);
frag.appendChild(itemEl);
}
this._repeater.appendChild(frag);
this._updateFakeFocus();
},
_renderSuggestion: function(item, index) {
var that = this;
var kind = item.kind;
if (typeof kind === "string") {
kind = kind.toLowerCase() === "query" ? SuggestionKind.Query :
kind.toLowerCase() === "result" ? SuggestionKind.Result :
kind.toLowerCase() === "separator" ? SuggestionKind.Separator : kind;
}
var root = document.createElement("div");
root.setAttribute("data-index", index);
root.id = this._repeater.id + "_" + index;
if (kind === SuggestionKind.Separator) {
root.className = "win-searchbox-suggestion-separator";
if (item.text) {
var textEl = document.createElement("div");
textEl.innerText = item.text;
textEl.setAttribute("aria-hidden", "true");
root.appendChild(textEl);
}
root.insertAdjacentHTML("beforeend", "<hr/>");
root.setAttribute("role", "separator");
root.setAttribute("aria-label", item.text || "");
return root;
}
if (kind === SuggestionKind.Result) {
root.className = "win-searchbox-suggestion-result";
// image
var img = document.createElement("img");
img.setAttribute("aria-hidden", "true");
if (item.imageUrl) {
img.onload = function() {
img.style.opacity = "1";
};
img.style.opacity = "0";
img.src = item.imageUrl;
} else {
img.style.display = "none";
}
root.appendChild(img);
var textDiv = document.createElement("div");
textDiv.className = "win-searchbox-suggestion-result-text";
textDiv.setAttribute("aria-hidden", "true");
this._addHitHighlightedText(textDiv, item, item.text || "");
textDiv.title = item.text || "";
root.appendChild(textDiv);
var detail = document.createElement("span");
detail.className = "win-searchbox-suggestion-result-detailed-text";
detail.setAttribute("aria-hidden", "true");
this._addHitHighlightedText(detail, item, item.detailText || "");
textDiv.appendChild(document.createElement("br"));
textDiv.appendChild(detail);
root.setAttribute("role", "option");
root.setAttribute("aria-label", (item.text || "") + " " + (item.detailText || ""));
return root;
}
// default / query
root.className = "win-searchbox-suggestion-query";
this._addHitHighlightedText(root, item, item.text || "");
root.title = item.text || "";
root.setAttribute("role", "option");
root.setAttribute("aria-label", item.text || "");
return root;
},
_addHitHighlightedText: function(container, item, text) {
// Remove existing children
while (container.firstChild) container.removeChild(container.firstChild);
if (!text) return;
// Build hits from item.hits if present (array of {startPosition, length}), otherwise simple substring matches of current input
var hits = [];
if (item && item.hits && item.hits.length) {
for (var i = 0; i < item.hits.length; i++) {
hits.push({ startPosition: item.hits[i].startPosition, length: item.hits[i].length });
}
} else {
var q = this._input.value || "";
if (q) {
var low = text.toLowerCase();
var lq = q.toLowerCase();
var pos = 0;
while (true) {
var idx = low.indexOf(lq, pos);
if (idx === -1) break;
hits.push({ startPosition: idx, length: q.length });
pos = idx + q.length;
}
}
}
// Merge overlapping hits & sort
hits.sort(function(a, b) { return a.startPosition - b.startPosition; });
var merged = [];
for (var j = 0; j < hits.length; j++) {
if (merged.length === 0) {
merged.push({ startPosition: hits[j].startPosition, length: hits[j].length });
} else {
var cur = merged[merged.length - 1];
var curEnd = cur.startPosition + cur.length;
if (hits[j].startPosition <= curEnd) {
var nextEnd = hits[j].startPosition + hits[j].length;
if (nextEnd > curEnd) {
cur.length = nextEnd - cur.startPosition;
}
} else {
merged.push({ startPosition: hits[j].startPosition, length: hits[j].length });
}
}
}
var last = 0;
for (var k = 0; k < merged.length; k++) {
var h = merged[k];
if (h.startPosition > last) {
var pre = document.createElement("span");
pre.innerText = text.substring(last, h.startPosition);
pre.setAttribute("aria-hidden", "true");
container.appendChild(pre);
}
var hitSpan = document.createElement("span");
hitSpan.innerText = text.substring(h.startPosition, h.startPosition + h.length);
hitSpan.className = "win-searchbox-flyout-highlighttext";
hitSpan.setAttribute("aria-hidden", "true");
container.appendChild(hitSpan);
last = h.startPosition + h.length;
}
if (last < text.length) {
var post = document.createElement("span");
post.innerText = text.substring(last);
post.setAttribute("aria-hidden", "true");
container.appendChild(post);
}
if (merged.length === 0) {
// no hits - append plain text
var whole = document.createElement("span");
whole.innerText = text;
whole.setAttribute("aria-hidden", "true");
container.appendChild(whole);
}
},
_updateFakeFocus: function() {
var firstIndex = -1;
if ((this._flyout.style.display !== "none") && this._chooseSuggestionOnEnter) {
for (var i = 0; i < this._suggestions.length; i++) {
var s = this._suggestions[i];
var kind = s.kind;
if (typeof kind === "string") {
kind = kind.toLowerCase() === "query" ? SuggestionKind.Query :
kind.toLowerCase() === "result" ? SuggestionKind.Result :
kind.toLowerCase() === "separator" ? SuggestionKind.Separator : kind;
}
if (kind === SuggestionKind.Query || kind === SuggestionKind.Result) {
firstIndex = i;
break;
}
}
}
this._selectSuggestionAtIndex(firstIndex);
},
_selectSuggestionAtIndex: function(index) {
for (var i = 0; i < this._repeater.children.length; i++) {
var el = this._repeater.children[i];
if (!el) continue;
if (i === index) {
if (el.className.indexOf("win-searchbox-suggestion-selected") === -1) {
el.className = (el.className + " win-searchbox-suggestion-selected").trim();
}
el.setAttribute("aria-selected", "true");
try {
this._input.setAttribute("aria-activedescendant", el.id);
} catch (e) {}
// ensure visible
try {
var top = el.offsetTop;
var bottom = top + el.offsetHeight;
var scrollTop = this._flyout.scrollTop;
var height = this._flyout.clientHeight;
if (bottom > scrollTop + height) this._flyout.scrollTop = bottom - height;
else if (top < scrollTop) this._flyout.scrollTop = top;
} catch (e) {}
} else {
el.className = el.className.replace(/\bwin-searchbox-suggestion-selected\b/g, "").trim();
el.setAttribute("aria-selected", "false");
}
}
if (index === -1) {
try { this._input.removeAttribute("aria-activedescendant"); } catch (e) {}
}
this._currentSelectedIndex = index;
this._updateButtonClass();
},
_updateButtonClass: function() {
if ((this._currentSelectedIndex !== -1) || (document.activeElement !== this._input)) {
this._button.className = this._button.className.replace(/\bwin-searchbox-button-input-focus\b/g, "").trim();
} else if (document.activeElement === this._input) {
if (this._button.className.indexOf("win-searchbox-button-input-focus") === -1) {
this._button.className = (this._button.className + " win-searchbox-button-input-focus").trim();
}
}
},
_onKeyDown: function(ev) {
// Normalize key
var key = ev.key || "";
if (!key && ev.keyCode) {
if (ev.keyCode === 13) key = "Enter";
else if (ev.keyCode === 27) key = "Esc";
else if (ev.keyCode === 38) key = "Up";
else if (ev.keyCode === 40) key = "Down";
else if (ev.keyCode === 9) key = "Tab";
}
if (key === "Tab") {
// handle tab navigation into suggestions
if (ev.shiftKey) {
// shift+tab: allow default behavior
} else {
if (this._currentFocusedIndex === -1) {
this._currentFocusedIndex = this._findNextSuggestionElementIndex(-1);
}
if (this._currentFocusedIndex !== -1) {
this._selectSuggestionAtIndex(this._currentFocusedIndex);
this._updateQueryTextWithSuggestionText(this._currentFocusedIndex);
ev.preventDefault();
ev.stopPropagation();
}
}
} else if (key === "Esc") {
if (this._currentFocusedIndex !== -1) {
this.queryText = this._prevQueryText;
this._currentFocusedIndex = -1;
this._selectSuggestionAtIndex(-1);
this._updateButtonClass();
ev.preventDefault();
ev.stopPropagation();
} else if (this.queryText !== "") {
this.queryText = "";
// trigger querychanged handlers
this._onInputChange(null);
this._updateButtonClass();
ev.preventDefault();
ev.stopPropagation();
}
} else if (key === "Up") {
var prev;
if (this._currentSelectedIndex !== -1) {
prev = this._findPreviousSuggestionElementIndex(this._currentSelectedIndex);
if (prev === -1) this.queryText = this._prevQueryText;
} else {
prev = this._findPreviousSuggestionElementIndex(this._suggestions.length);
}
this._currentFocusedIndex = prev;
this._selectSuggestionAtIndex(prev);
this._updateQueryTextWithSuggestionText(this._currentFocusedIndex);
this._updateButtonClass();
ev.preventDefault();
ev.stopPropagation();
} else if (key === "Down") {
var next = this._findNextSuggestionElementIndex(this._currentSelectedIndex);
if ((this._currentSelectedIndex !== -1) && (next === -1)) this.queryText = this._prevQueryText;
this._currentFocusedIndex = next;
this._selectSuggestionAtIndex(next);
this._updateQueryTextWithSuggestionText(this._currentFocusedIndex);
this._updateButtonClass();
ev.preventDefault();
ev.stopPropagation();
} else if (key === "Enter") {
if (this._currentSelectedIndex === -1) {
this._submitQuery(this._input.value, ev);
} else {
var chosen = this._suggestions[this._currentSelectedIndex];
if (chosen) this._processSuggestionChosen(chosen, ev);
else this._submitQuery(this._input.value, ev);
}
this.hideFlyout();
ev.preventDefault();
ev.stopPropagation();
} else {
// typing -> clear selection
if (this._currentFocusedIndex !== -1) {
this._currentFocusedIndex = -1;
this._selectSuggestionAtIndex(-1);
this._updateFakeFocus();
}
}
},
_findNextSuggestionElementIndex: function(curIndex) {
var start = curIndex + 1;
if (start < 0) start = 0;
for (var i = start; i < this._suggestions.length; i++) {
var s = this._suggestions[i];
var k = s.kind;
if (typeof k === "string") {
k = k.toLowerCase() === "query" ? SuggestionKind.Query :
k.toLowerCase() === "result" ? SuggestionKind.Result :
k.toLowerCase() === "separator" ? SuggestionKind.Separator : k;
}
if (k === SuggestionKind.Query || k === SuggestionKind.Result) return i;
}
return -1;
},
_findPreviousSuggestionElementIndex: function(curIndex) {
var start = curIndex - 1;
if (start >= this._suggestions.length) start = this._suggestions.length - 1;
for (var i = start; i >= 0; i--) {
var s = this._suggestions[i];
var k = s.kind;
if (typeof k === "string") {
k = k.toLowerCase() === "query" ? SuggestionKind.Query :
k.toLowerCase() === "result" ? SuggestionKind.Result :
k.toLowerCase() === "separator" ? SuggestionKind.Separator : k;
}
if (k === SuggestionKind.Query || k === SuggestionKind.Result) return i;
}
return -1;
},
_updateQueryTextWithSuggestionText: function(idx) {
if ((idx >= 0) && (idx < this._suggestions.length)) {
this.queryText = this._suggestions[idx].text || "";
}
},
_emit: function(type, detail, handler) {
var ev = createCustomEvent(type, detail);
// call handler property first
if (typeof handler === "function") {
try { handler.call(this, ev); } catch (e) { /* swallow */ }
}
try { this._root.dispatchEvent(ev); } catch (e) { /* swallow */ }
return ev;
},
_getBrowserLanguage: function() {
try {
return (navigator && (navigator.language || navigator.userLanguage)) || "";
} catch (e) {
return "";
}
},
_getKeyModifiers: function(ev) {
var m = 0;
if (!ev) return m;
if (ev.ctrlKey) m |= 1;
if (ev.altKey) m |= 2;
if (ev.shiftKey) m |= 4;
return m;
}
};
// export
global.Search.Box = SearchBox;
})(this);
+184
View File
@@ -0,0 +1,184 @@
(function(global) {
"use strict";
/**
* TransitionPanel
* axis: 'x' | 'y' | 'both'
* speed: 'fast' | 'medium' | 'slow'
* el: DOM 元素
*/
function TransitionPanel(el, options) {
if (!el) throw new Error("TransitionPanel requires a DOM element.");
this.el = el;
this.opts = options || {};
this.axis = this.opts.axis || 'y';
this.speed = this.opts.speed || 'medium';
// 初始化状态
this._shown = false;
this._events = {};
// 确保基础类 statusbar
if (!el.classList.contains('statusbar')) el.classList.add('statusbar');
// 确保 axis 类存在(x/y/both
if (this.axis === 'x' && !el.classList.contains('x')) el.classList.add('x');
else if (this.axis === 'y' && !el.classList.contains('y')) el.classList.add('y');
else if (this.axis === 'both' && !el.classList.contains('both')) el.classList.add('both');
// 添加速度类
if (this.speed === 'fast') el.classList.add('fast');
else if (this.speed === 'medium') el.classList.add('medium');
else el.classList.add('slow');
// 内容变化自动刷新
this._bindContentChange();
}
function maxWidth(el) {
var cw = 0;
var ow = 0;
var rw = 0;
var sw = 0;
try { cw = el.clientWidth; } catch (e) {}
try { ow = el.offsetWidth; } catch (e) {}
try { rw = el.getBoundingClientRect().width; } catch (e) {}
try { sw = el.scrollWidth; } catch (e) {}
return Math.max(cw, ow, rw, sw);
}
function maxHeight(el) {
var ch = 0;
var oh = 0;
var rh = 0;
var sh = 0;
try { ch = el.clientHeight; } catch (e) {}
try { oh = el.offsetHeight; } catch (e) {}
try { rh = el.getBoundingClientRect().height; } catch (e) {}
try { sh = el.scrollHeight; } catch (e) {}
return Math.max(ch, oh, rh, sh);
}
// 显示
TransitionPanel.prototype.show = function() {
if (this._shown) return;
this._emit('beforeshow');
this._shown = true;
var el = this.el;
setTimeout(function() {
this._emit('show');
if (this.axis !== 'x') el.style.height = maxHeight(el) + 'px';
if (this.axis !== 'y') el.style.width = maxWidth(el) + 'px';
if (this.axis === 'both') {
el.style.height = maxHeight(el) + 'px';
el.style.width = maxWidth(el) + 'px';
}
this._afterTransition('aftershow');
}.bind(this), 16);
};
// 隐藏
TransitionPanel.prototype.hide = function() {
if (!this._shown) return;
this._emit('beforehide');
this._shown = false;
var el = this.el;
// 锁定当前尺寸
if (this.axis !== 'x') el.style.height = maxHeight(el) + 'px';
if (this.axis !== 'y') el.style.width = maxWidth(el) + 'px';
if (this.axis === 'both') {
el.style.height = maxHeight(el) + 'px';
el.style.width = maxWidth(el) + 'px';
}
setTimeout(function() {
this._emit('hide');
// 回到折叠状态尺寸(依赖 x/y/both 类)
if (this.axis !== 'x') el.style.height = '';
if (this.axis !== 'y') el.style.width = '';
if (this.axis === 'both') {
el.style.height = '';
el.style.width = '';
}
this._afterTransition('afterhide');
}.bind(this), 16);
};
// 刷新尺寸(显示中)
TransitionPanel.prototype.refresh = function() {
if (!this._shown) return;
var el = this.el;
if (this.axis !== 'x') el.style.height = el.scrollHeight + 'px';
if (this.axis !== 'y') el.style.width = el.scrollWidth + 'px';
};
// 内容变化自动刷新
TransitionPanel.prototype._bindContentChange = function() {
if (!global.setTextChangeEvent) return;
var self = this;
global.setTextChangeEvent(this.el, function() {
if (self._shown) self.refresh();
});
};
// transitionend 回调处理
TransitionPanel.prototype._afterTransition = function(evt) {
var el = this.el;
var called = false;
var duration = this.speed === 'fast' ? 300 : (this.speed === 'medium' ? 500 : 700);
function done() {
if (called) return;
called = true;
el.removeEventListener('transitionend', done);
if (evt) this._emit(evt);
}
el.addEventListener('transitionend', done.bind(this));
setTimeout(done.bind(this), duration + 30);
};
// 生命周期事件绑定
TransitionPanel.prototype.on = function(name, fn) {
(this._events[name] || (this._events[name] = [])).push(fn);
};
// 事件触发
TransitionPanel.prototype._emit = function(name) {
var list = this._events[name];
if (!list) return;
for (var i = 0; i < list.length; i++) {
try { list[i].call(this); } catch (e) { console.error(e); }
}
};
// 只读属性 shown
Object.defineProperty(TransitionPanel.prototype, 'shown', {
get: function() { return this._shown; }
});
// 销毁
TransitionPanel.prototype.dispose = function() {
// 移除所有事件回调
this._events = {};
// 清理 el 内联样式
if (this.el) {
this.el.style.height = '';
this.el.style.width = '';
}
this._shown = false;
// 可选:删除内容变化监听(如果使用全局 setTextChangeEvent
if (global.Windows && global.Windows.UI && global.Windows.UI.Event && global.Windows.UI.Event.Monitor) {
// 这里可以 detach 所有回调
// 视具体实现可扩展
}
};
// 全局暴露
global.TransitionPanel = TransitionPanel;
})(this);
+108 -25
View File
@@ -33,6 +33,9 @@
<script type="text/javascript" src="js/datasrc.js"></script>
<script type="text/javascript" src="js/appbar.js"></script>
<script type="text/javascript" src="js/pagemgr.js"></script>
<script type="text/javascript" src="js/search.js"></script>
<link rel="stylesheet" href="css/statusbar.css">
<script type="text/javascript" src="js/statusbar.js"></script>
<script type="text/javascript" src="js/manager/pages.js"></script>
<script type="text/javascript" src="js/mgrinit.js"></script>
</head>
@@ -42,15 +45,39 @@
<div class="page full guide fold">
<main class="main padding">
<div id="page-manager" style="display: none;" class="ispage">
<h2>应用</h2>
<p>在这里,可以对安装的 Windows 商店应用进行管理。</p>
<h3>安装的应用</h3>
<h2 data-res-resxml="MANAGER_APP_TITLE"></h2>
<p data-res-resxml="MANAGER_APP_DESCRIPTION"></p>
<h3 data-res-resxml="MANAGER_APP_INSTALLEDAPPS"></h3>
<br>
<div class="app-loading" id="applist-loading" style="display: none;">
<progress class="win-ring"></progress>
<span class="win-label title">正在加载应用...</span>
<br>
<div class="win-searchbox win-disposable" id="applist-search" role="group" aria-label="搜索框"></div>
<div class="applist-options">
<div class="item">
<input type="checkbox" id="applist-showsystemapp">
<label for="applist-showsystemapp" data-res-resxml="MANAGER_APP_SHOWSYSTEMAPP"></label>
</div>
<div class="item">
<input type="checkbox" id="applist-showframework">
<label for="applist-showframework" data-res-resxml="MANAGER_APP_SHOWFRAMEWORK"></label>
</div>
</div>
<div class="app-loading" id="applist-loading" style="display: none;">
<br>
<div class="container">
<progress class="win-ring"></progress>
<span class="win-label title" data-res-resxml="MANAGER_APP_INSTALLEDAPPS_LOADING"></span>
<br>
</div>
</div>
<p id="applist-datalen"></p>
<script>
(function(global) {
var appLoading = document.getElementById("applist-loading");
appLoading.bar = new TransitionPanel(appLoading, {
axis: 'y',
duration: 500,
});
})(this);
</script>
<div class="appitem" id="appitem-template" style="display: none;">
<div role="img" style="pointer-events: none;">
<img width="" height="" src="images/applogo.default.png" />
@@ -58,14 +85,18 @@
<div role="divide" style="pointer-events: none;"></div>
<div role="excepticon">
<div role="title" class="win-type-x-small" style="pointer-events: none;">
<span class="displayName">App Name</span><br>
<span class="publisher">Publisher</span>
<span class="displayName"></span><br>
<span class="publisher"></span>
</div>
<div role="advance">
<a>高级选项</a>
<a data-res-resxml="MANAGER_APP_ADVANCEOPTIONS"></a>
</div>
<div role="progress">
<span class="status" data-res-resxml="MANAGER_APP_UNINSTALL_ING"></span><br>
<progress class="win-progress progress" min="0" max="100"></progress>
</div>
<div role="control">
<button name="uninstall">卸载</button>
<button class="uninstall" name="uninstall" data-res-resxml="MANAGER_APP_UNINSTALL"></button>
</div>
</div>
</div>
@@ -73,7 +104,7 @@
</div>
<div class="bottom-compensate"></div>
</div>
<div id="page-appinfo" class="ispage app-detailpage">
<div id="page-appinfo" class="ispage app-detailpage" style="display: none;">
<header>
<button class="win-backbutton"></button>
<h2 class="display-name">App DisplayName</h2>
@@ -81,18 +112,37 @@
<span class="publisher-display-name">App PublisherDisplayName</span><br>
<span class="version">App Version</span><br>
<span class="description">App Description</span>
<p><strong>应用身份</strong></p>
<p><strong data-res-resxml="MANAGER_APP_IDENTITY"></strong></p>
<div class="identity win-type-body" style="width: 100%; max-width: 100%; box-sizing: border-box; -ms-user-select: element;">
<span style="font-weight: bold;">名称</span><span>: </span><span class="name"></span><br>
<span style="font-weight: bold;">发布者</span><span>: </span><span class="publisher"></span><br>
<span style="font-weight: bold;">发布者 ID</span><span>: </span><span class="publisher-id"></span><br>
<span style="font-weight: bold;">系列名</span><span>: </span><span class="family-name"></span><br>
<span style="font-weight: bold;">全名</span><span>: </span><span class="full-name"></span><br>
<span style="font-weight: bold;">支持的处理器架构</span><span>: </span><span class="architecture"></span><br>
<span style="font-weight: bold;" data-res-resxml="MANAGER_APP_IDENTITY_NAME"></span><span>: </span><span class="name"></span><br>
<span style="font-weight: bold;" data-res-resxml="MANAGER_APP_IDENTITY_PUBLISHER"></span><span>: </span><span class="publisher"></span><br>
<span style="font-weight: bold;" data-res-resxml="MANAGER_APP_IDENTITY_PUBLISHERID"></span><span>: </span><span class="publisher-id"></span><br>
<span style="font-weight: bold;" data-res-resxml="MANAGER_APP_IDENTITY_FAMILYNAME"></span><span>: </span><span class="family-name"></span><br>
<span style="font-weight: bold;" data-res-resxml="MANAGER_APP_IDENTITY_FULLNAME"></span><span>: </span><span class="full-name"></span><br>
<span style="font-weight: bold;" data-res-resxml="MANAGER_APP_IDENTITY_ARCHITECTURE"></span><span>: </span><span class="architecture"></span><br>
</div>
<p><strong>卸载</strong></p>
<p>卸载此应用及其设置。</p>
<button id="detail-uninstall-btn" data-app-fullname="">卸载</button>
<p><strong data-res-resxml="MANAGER_APP_HASAPPS"></strong></p>
<p data-res-resxml="MANAGER_APP_HASAPPS_DESC"></p>
<div class="loadingstatus" id="appinfo-loading">
<div class="container">
<progress class="win-ring"></progress>
<span class="win-label title" data-res-resxml="MANAGER_APP_INSTALLEDAPPS_LOADING"></span>
<br>
</div>
</div>
<div class="apps">
</div>
<p><strong data-res-resxml="MANAGER_APP_UNINSTALL"></strong></p>
<p data-res-resxml="MANAGER_APP_UNINSTALL_DESC"></p>
<div class="loadingstatus" id="appinfo-uninstallstatus">
<div style="width: 100%;">
<span class="status" data-res-resxml="MANAGER_APP_UNINSTALL_ING"></span><br>
<progress class="win-progress progress" min="0" max="100"></progress>
</div>
<br>
</div>
<button id="detail-uninstall-btn" data-res-resxml="MANAGER_APP_UNINSTALL">卸载</button>
<div class="bottom-compensate"></div>
</div>
</main>
<aside class="win-ui-dark">
@@ -100,8 +150,8 @@
<ul class="list top">
<li class="title">
<div role="img">&#58344;</div>
<div role="placeholder"></div>
<span class="win-type-base">应用管理</span>
<!--<div role="placeholder"></div>-->
<span class="win-type-base" data-res-resxml="MANAGER_APPTITLE"></span>
</li>
<script>
(function($) {
@@ -117,7 +167,7 @@
<ul class="list">
<li id="tag-manager">
<div role="img">&#57587;</div>
<span class="win-type-base">管理</span>
<span class="win-type-base" data-res-resxml="MANAGER_MANAGE"></span>
</li>
<li id="tag-appinfo" class="subitem">
<div role="img">&#57650;</div>
@@ -134,6 +184,39 @@
</div>
<div class="win-overlay win-commandlayout win-appbar win-bottom appbar win-ui-dark" id="appBar" role="menubar">
</div>
<div data-win-control="WinJS.UI.Flyout" id="app-uninstall-flyout" style="position: absolute; width: 336px; padding: 0; max-height: 284px;">
<div class="top" style="padding: 20px 20px 0 20px;">
<span data-res-resxml="MANAGER_APP_UNINSTALL_DESC"></span>
</div>
<div class="sapplist applist"></div>
<style>
#app-uninstall-flyout {
/*min-height: 88px;
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);*/
}
#app-uninstall-flyout .sapplist {
padding: 0 20px;
width: 100%;
box-sizing: border-box;
overflow-x: hidden;
overflow-y: auto;
-ms-overflow-style: -ms-autohiding-scrollbar;
max-height: 160px;
}
</style>
<div class="bottom" style="padding: 20px 20px 20px 20px; height: 32px;">
<button class="confirm" data-res-resxml="MANAGER_APP_UNINSTALL" style="float: right;"></button>
</div>
</div>
<div id="app-deskshortcut-create" style="position: absolute;">
<p>即将在桌面创建快捷方式,这里做一些调整。快捷方式不建议固定到开始菜单中,因为本快捷方式只是一种启动器。不具有其余磁贴功能。</p>
<div>
<div>
<div class="win-radio"></div>
</div>
</div>
</div>
</body>
</html>
+178 -1
View File
@@ -32,6 +32,7 @@
}
.appitem div[role=img] {
position: relative;
width: 40px;
height: 40px;
background-color: #464646;
@@ -58,6 +59,16 @@
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.appitem div[role=img]::after {
border: 1px solid rgba(254, 254, 254, 0.1);
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.appitem div[role=img] img {
width: 30px;
height: 30px;
@@ -113,6 +124,11 @@
width: calc(100% - 40px - 10px);
}
.appitem div[role=excepticon] div[role=progress] {
display: none;
width: 100%;
}
.appitem div[role=excepticon] div[role=control] {
display: none;
/* IE10 */
@@ -136,11 +152,45 @@
height: 0;
}
.appitem div[role=excepticon] div[role=progress] {
width: 100%;
box-sizing: border-box;
}
.appitem.uninstalling,
.appitem.selected {
height: 119px;
background-color: rgba(232, 232, 232, 1);
}
.appitem.uninstalled div[role=excepticon] div[role=progress],
.appitem.uninstalling div[role=excepticon] div[role=progress] {
display: block;
flex: 1 0 auto;
-ms-flex: 1 0 auto;
width: 100%;
}
.appitem.uninstalling div[role=excepticon] div[role=progress] progress {
max-width: 100%;
}
.appitem.uninstalled div[role=excepticon] div[role=progress] progress {
display: none;
}
.appitem.uninstalling div[role=excepticon] div[role=progress],
.appitem.uninstalled div[role=excepticon] div[role=progress],
.appitem.uninstalling div[role=excepticon] div[role=progress] .status,
.appitem.uninstalled div[role=excepticon] div[role=progress] .status {
word-break: break-all;
word-wrap: break-word;
}
.appitem.uninstalled {
height: auto;
}
.appitem.selected div[role=excepticon] div[role=control] {
display: flex;
display: -ms-flexbox;
@@ -148,6 +198,23 @@
height: auto;
}
.appitem.uninstalling div[role=excepticon] div[role=advance],
.appitem.uninstalling div[role=excepticon] div[role=control],
.appitem.uninstalling.selected div[role=excepticon] div[role=advance],
.appitem.uninstalling.selected div[role=excepticon] div[role=control],
.appitem.uninstalled div[role=excepticon] div[role=advance],
.appitem.uninstalled div[role=excepticon] div[role=control],
.appitem.uninstalled.selected div[role=excepticon] div[role=advance],
.appitem.uninstalled.selected div[role=excepticon] div[role=control] {
display: none;
}
.appitem.uninstalling div[role=excepticon] div[role=title],
.appitem.uninstalled div[role=excepticon] div[role=title] {
-ms-flex: none;
flex: none;
}
ul.appitem-list,
ul.appitem-list li {
margin: 0;
@@ -169,6 +236,11 @@ ul.appitem-list li {
}
.app-loading {
width: 100%;
height: auto;
}
.app-loading .container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
@@ -176,7 +248,17 @@ ul.appitem-list li {
justify-content: flex-start;
align-items: center;
width: 100%;
height: auto;
/*****/
display: -ms-flexbox;
/* IE10 */
-ms-flex-direction: row;
/* flex-direction: row */
-ms-flex-wrap: wrap;
/* flex-wrap: wrap */
-ms-flex-pack: start;
/* justify-content: flex-start */
-ms-flex-align: center;
/* align-items: center */
}
.app-loading.noloading progress {
@@ -204,6 +286,13 @@ ul.appitem-list li {
height: 67px;
box-sizing: border-box;
max-width: 100%;
display: -ms-flexbox;
-ms-flex-direction: row;
/* flex-direction: row */
-ms-flex-wrap: nowrap;
/* flex-wrap: nowrap */
-ms-flex-pack: start;
/* justify-content: flex-start */
}
.app-detailpage header .win-backbutton {
@@ -222,4 +311,92 @@ ul.appitem-list li {
overflow-y: hidden;
overflow-x: hidden;
text-overflow: ellipsis;
}
.app-detailpage .identity,
.app-detailpage .publisher-display-name,
.app-detailpage .version,
.app-detailpage .description {
word-break: break-all;
}
.loadingstatus {
width: 100%;
height: auto;
}
.loadingstatus .container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: center;
justify-content: flex-start;
align-items: center;
width: 100%;
/* IE10 */
display: -ms-flexbox;
-ms-flex-direction: row;
/* flex-direction: row */
-ms-flex-wrap: wrap;
/* flex-wrap: wrap */
-ms-flex-pack: start;
/* justify-content: flex-start */
-ms-flex-align: center;
/* align-items: center */
}
.loadingstatus.noloading progress {
display: none;
}
.loadingstatus .title {
margin-left: 10px;
}
.loadingstatus.noloading .title {
margin-left: 0;
}
.applist-options {
margin: 10px 0 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
justify-content: flex-start;
align-items: center;
/* IE10 */
display: -ms-flexbox;
-ms-flex-direction: row;
/* flex-direction: row */
-ms-flex-wrap: wrap;
/* flex-wrap: wrap */
-ms-flex-pack: start;
/* justify-content: flex-start */
-ms-flex-align: center;
/* align-items: center */
}
.applist-options .item {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: flex-start;
justify-content: flex-start;
align-items: center;
margin-right: 20px;
/* IE10 */
display: -ms-flexbox;
-ms-flex-direction: row;
/* flex-direction: row */
-ms-flex-wrap: nowrap;
/* flex-wrap: nowrap */
-ms-flex-pack: start;
/* justify-content: flex-start */
-ms-flex-align: center;
/* align-items: center */
}
.applist-options .item input[type="checkbox"] {
margin-left: 0;
}
+358 -230
View File
@@ -1,233 +1,361 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resource id="ms-resource://Microsoft.WinJS.1.0/ui/off">
<lang name="zh-CN"></lang>
<lang name="en-US">Off</lang>
<lang name="af-ZA">Af</lang>
<lang name="am-ET">አጥፋ</lang>
<lang name="ar-SA">إيقاف التشغيل</lang>
<lang name="as-IN">অফ</lang>
<lang name="az-LATN-AZ">Qeyri-aktiv</lang>
<lang name="be-BY">Выкл.</lang>
<lang name="bg-BG">Изключено</lang>
<lang name="bn-BD">বন্ধ</lang>
<lang name="bn-IN">বন্ধ</lang>
<lang name="bs-LATN-BA">Isključeno</lang>
<lang name="ca-ES">Inactiva</lang>
<lang name="ca-ES-VALENCIA">Inactiva</lang>
<lang name="chr-CHER-US">ᎠᏍᏚᏗ</lang>
<lang name="cs-CZ">Vypnuto</lang>
<lang name="cy-GB">Diffodd</lang>
<lang name="da-DK">Fra</lang>
<lang name="de-DE">Aus</lang>
<lang name="el-GR">Ανενεργό</lang>
<lang name="en-GB">Off</lang>
<lang name="es-ES">Desactivado</lang>
<lang name="et-EE">Väljas</lang>
<lang name="eu-ES">Desaktibatuta</lang>
<lang name="fa-IR">خاموش</lang>
<lang name="fi-FI">Ei käytössä</lang>
<lang name="fil-PH">Naka-off</lang>
<lang name="fr-FR">Inactif</lang>
<lang name="ga-IE">As</lang>
<lang name="gd-GB">Dheth</lang>
<lang name="gl-ES">Desactivado</lang>
<lang name="gu-IN">બંધ</lang>
<lang name="ha-LATN-NG">Kashe</lang>
<lang name="he-IL">לא פעיל</lang>
<lang name="hi-IN">बंद</lang>
<lang name="hr-HR">Isključeno</lang>
<lang name="hu-HU">Kikapcsolva</lang>
<lang name="hy-AM">Անջատ</lang>
<lang name="id-ID">Nonaktif</lang>
<lang name="ig-NG">Gbanyọ</lang>
<lang name="is-IS">Óvirkt</lang>
<lang name="it-IT">Disattivato</lang>
<lang name="iu-LATN-CA">Qaminngajuq</lang>
<lang name="ja-JP">オフ</lang>
<lang name="ka-GE">გამორთვა</lang>
<lang name="kk-KZ">Өшірілген</lang>
<lang name="km-KH">បិទ</lang>
<lang name="kn-IN">ಆಫ್</lang>
<lang name="ko-KR">해제</lang>
<lang name="kok-IN">ऑफ करचें</lang>
<lang name="ku-ARAB-IQ">کوژاوە</lang>
<lang name="ky-KG">Өчүрулгөн</lang>
<lang name="lb-LU">Aus</lang>
<lang name="lt-LT">Išjungta</lang>
<lang name="lv-LV">Izslēgts</lang>
<lang name="mi-NZ">Weto ana</lang>
<lang name="mk-MK">Исклучено</lang>
<lang name="ml-IN">ഓഫ്</lang>
<lang name="mn-MN">Idəvxgüĭ</lang>
<lang name="mr-IN">बंद</lang>
<lang name="ms-MY">Mati</lang>
<lang name="mt-MT">Mitfi</lang>
<lang name="nb-NO">Av</lang>
<lang name="ne-NP">निभाउनुहोस्</lang>
<lang name="nl-NL">Uit</lang>
<lang name="nn-NO">Av</lang>
<lang name="nso-ZA">Timilwe</lang>
<lang name="or-IN">ଅଫ୍</lang>
<lang name="pa-ARAB-PK">بند</lang>
<lang name="pa-IN">ਬੰਦ ਕਰੋ</lang>
<lang name="pl-PL">Wyłączone</lang>
<lang name="prs-AF">خاموش</lang>
<lang name="pt-BR">Desligado</lang>
<lang name="pt-PT">Desativado</lang>
<lang name="qps-PLOC">[3Hcgw][Ǿƒƒ ]</lang>
<lang name="qps-PLOCM">‏أبع[Off]לף</lang>
<lang name="qut-GT">Q'atetalik</lang>
<lang name="quz-PE">Tukuchisqa</lang>
<lang name="ro-RO">Dezactivat</lang>
<lang name="ru-RU">Откл.</lang>
<lang name="rw-RW">Irafunze</lang>
<lang name="sd-ARAB-PK">بند کوليو</lang>
<lang name="si-LK">අක්‍රීය</lang>
<lang name="sk-SK">Vypnuté</lang>
<lang name="sl-SI">Izklopljeno</lang>
<lang name="sq-AL">Joaktiv</lang>
<lang name="sr-CYRL-BA">Искључено</lang>
<lang name="sr-CYRL-CS">Искључено</lang>
<lang name="sr-LATN-CS">Isključeno</lang>
<lang name="sv-SE">Av</lang>
<lang name="sw-KE">Zima</lang>
<lang name="ta-IN">அணை</lang>
<lang name="te-IN">ఆఫ్ చేయి</lang>
<lang name="tg-CYRL-TJ">Хомӯш</lang>
<lang name="th-TH">ปิด</lang>
<lang name="ti-ET">ኣጥፍእ</lang>
<lang name="tk-TM">Öçürilen</lang>
<lang name="tn-ZA">Timilwe</lang>
<lang name="tr-TR">Kapalı</lang>
<lang name="tt-RU">Сүндерелгән</lang>
<lang name="ug-CN">يېپىق</lang>
<lang name="uk-UA">Вимк.</lang>
<lang name="ur-PK">آف</lang>
<lang name="uz-LATN-UZ">Och</lang>
<lang name="vi-VN">Tắt</lang>
<lang name="wo-SN">Fay</lang>
<lang name="xh-ZA">Cimile</lang>
<lang name="yo-NG">Pa</lang>
<lang name="zh-HK">關閉</lang>
<lang name="zh-TW">關閉</lang>
<lang name="zu-ZA">Cishile</lang>
</resource>
<resource id="ms-resource://Microsoft.WinJS.1.0/ui/on">
<lang name="zh-CN"></lang>
<lang name="en-US">On</lang>
<lang name="af-ZA">Aan</lang>
<lang name="am-ET">አብራ</lang>
<lang name="ar-SA">تشغيل</lang>
<lang name="as-IN">অন</lang>
<lang name="az-LATN-AZ">Aktiv</lang>
<lang name="be-BY">Укл.</lang>
<lang name="bg-BG">Включено</lang>
<lang name="bn-BD">চালু</lang>
<lang name="bn-IN">চালু</lang>
<lang name="bs-LATN-BA">Uključeno</lang>
<lang name="ca-ES">Activa</lang>
<lang name="ca-ES-VALENCIA">Activa</lang>
<lang name="chr-CHER-US">ᎠᏍᏚᎢᏍᏗ</lang>
<lang name="cs-CZ">Zapnuto</lang>
<lang name="cy-GB">Ar waith</lang>
<lang name="da-DK">Til</lang>
<lang name="de-DE">Ein</lang>
<lang name="el-GR">Ενεργό</lang>
<lang name="en-GB">On</lang>
<lang name="es-ES">Activado</lang>
<lang name="et-EE">Sees</lang>
<lang name="eu-ES">Aktibatuta</lang>
<lang name="fa-IR">روشن</lang>
<lang name="fi-FI">Käytössä</lang>
<lang name="fil-PH">Naka-on</lang>
<lang name="fr-FR">Actif</lang>
<lang name="ga-IE">Air</lang>
<lang name="gd-GB">Air</lang>
<lang name="gl-ES">Activado</lang>
<lang name="gu-IN">ચાલુ</lang>
<lang name="ha-LATN-NG">Kunna</lang>
<lang name="he-IL">פעיל</lang>
<lang name="hi-IN">चालू</lang>
<lang name="hr-HR">Uključeno</lang>
<lang name="hu-HU">Bekapcsolva</lang>
<lang name="hy-AM">Միաց</lang>
<lang name="id-ID">Aktif</lang>
<lang name="ig-NG">Gbanye</lang>
<lang name="is-IS">Virkt</lang>
<lang name="it-IT">Attivato</lang>
<lang name="iu-LATN-CA">Ikumajuq</lang>
<lang name="ja-JP">オン</lang>
<lang name="ka-GE">ჩართვა</lang>
<lang name="kk-KZ">Қосылған</lang>
<lang name="km-KH">បើក</lang>
<lang name="kn-IN">ಆನ್</lang>
<lang name="ko-KR">설정</lang>
<lang name="kok-IN">ऑन करचें</lang>
<lang name="ku-ARAB-IQ">هەڵکراو</lang>
<lang name="ky-KG">Күйгүзүлгөн</lang>
<lang name="lb-LU">Un</lang>
<lang name="lt-LT">Įjungta</lang>
<lang name="lv-LV">Ieslēgts</lang>
<lang name="mi-NZ">Kā ana</lang>
<lang name="mk-MK">Вклученo</lang>
<lang name="ml-IN">ഓൺ</lang>
<lang name="mn-MN">Идэвхтэй</lang>
<lang name="mr-IN">चालू</lang>
<lang name="ms-MY">Hidup</lang>
<lang name="mt-MT">Mixgħul</lang>
<lang name="nb-NO"></lang>
<lang name="ne-NP">खोल्नुहोस्</lang>
<lang name="nl-NL">Aan</lang>
<lang name="nn-NO"></lang>
<lang name="nso-ZA">Goteditšwe</lang>
<lang name="or-IN">ଅନ୍</lang>
<lang name="pa-ARAB-PK">چالُو</lang>
<lang name="pa-IN">ਚਾਲੂ ਕਰੋ</lang>
<lang name="pl-PL">Włączone</lang>
<lang name="prs-AF">روشن</lang>
<lang name="pt-BR">Ligado</lang>
<lang name="pt-PT">Ativado</lang>
<lang name="qps-PLOC">[Aj8Pp][Őņ ]</lang>
<lang name="qps-PLOCM">‏أبع[On]לף</lang>
<lang name="qut-GT">Tzijtalik</lang>
<lang name="quz-PE">Kawsarichisqa</lang>
<lang name="ro-RO">Activat</lang>
<lang name="ru-RU">Вкл.</lang>
<lang name="rw-RW">Irafunguye</lang>
<lang name="sd-ARAB-PK">شروع ڪريو</lang>
<lang name="si-LK">සක්‍රීය</lang>
<lang name="sk-SK">Zapnuté</lang>
<lang name="sl-SI">Vklopljeno</lang>
<lang name="sq-AL">Aktiv</lang>
<lang name="sr-CYRL-BA">Укључено</lang>
<lang name="sr-CYRL-CS">Укључено</lang>
<lang name="sr-LATN-CS">Uključeno</lang>
<lang name="sv-SE"></lang>
<lang name="sw-KE">Washa</lang>
<lang name="ta-IN">இயக்கு</lang>
<lang name="te-IN">ఆన్ చేయి</lang>
<lang name="tg-CYRL-TJ">Фаъол</lang>
<lang name="th-TH">เปิด</lang>
<lang name="ti-ET">ወልዕ</lang>
<lang name="tk-TM">Açyk</lang>
<lang name="tn-ZA">Tshubilwe</lang>
<lang name="tr-TR">Açık</lang>
<lang name="tt-RU">Кабызылган</lang>
<lang name="ug-CN">ئوچۇق</lang>
<lang name="uk-UA">Увімк.</lang>
<lang name="ur-PK">آن</lang>
<lang name="uz-LATN-UZ">Yoq</lang>
<lang name="vi-VN">Bật</lang>
<lang name="wo-SN">Taal</lang>
<lang name="xh-ZA">Layitile</lang>
<lang name="yo-NG">Tàn</lang>
<lang name="zh-HK">開啟</lang>
<lang name="zh-TW">開啟</lang>
<lang name="zu-ZA">Vuliwe</lang>
</resource>
<resource id="license">
<lang name="zh-CN">license_cn.html</lang>
<lang name="en-US">license_en.html</lang>
</resource>
<resource id="ms-resource://Microsoft.WinJS.1.0/ui/off">
<lang name="zh-CN"></lang>
<lang name="en-US">Off</lang>
<lang name="af-ZA">Af</lang>
<lang name="am-ET">አጥፋ</lang>
<lang name="ar-SA">إيقاف التشغيل</lang>
<lang name="as-IN">অফ</lang>
<lang name="az-LATN-AZ">Qeyri-aktiv</lang>
<lang name="be-BY">Выкл.</lang>
<lang name="bg-BG">Изключено</lang>
<lang name="bn-BD">বন্ধ</lang>
<lang name="bn-IN">বন্ধ</lang>
<lang name="bs-LATN-BA">Isključeno</lang>
<lang name="ca-ES">Inactiva</lang>
<lang name="ca-ES-VALENCIA">Inactiva</lang>
<lang name="chr-CHER-US">ᎠᏍᏚᏗ</lang>
<lang name="cs-CZ">Vypnuto</lang>
<lang name="cy-GB">Diffodd</lang>
<lang name="da-DK">Fra</lang>
<lang name="de-DE">Aus</lang>
<lang name="el-GR">Ανενεργό</lang>
<lang name="en-GB">Off</lang>
<lang name="es-ES">Desactivado</lang>
<lang name="et-EE">Väljas</lang>
<lang name="eu-ES">Desaktibatuta</lang>
<lang name="fa-IR">خاموش</lang>
<lang name="fi-FI">Ei käytössä</lang>
<lang name="fil-PH">Naka-off</lang>
<lang name="fr-FR">Inactif</lang>
<lang name="ga-IE">As</lang>
<lang name="gd-GB">Dheth</lang>
<lang name="gl-ES">Desactivado</lang>
<lang name="gu-IN">બંધ</lang>
<lang name="ha-LATN-NG">Kashe</lang>
<lang name="he-IL">לא פעיל</lang>
<lang name="hi-IN">बंद</lang>
<lang name="hr-HR">Isključeno</lang>
<lang name="hu-HU">Kikapcsolva</lang>
<lang name="hy-AM">Անջատ</lang>
<lang name="id-ID">Nonaktif</lang>
<lang name="ig-NG">Gbanyọ</lang>
<lang name="is-IS">Óvirkt</lang>
<lang name="it-IT">Disattivato</lang>
<lang name="iu-LATN-CA">Qaminngajuq</lang>
<lang name="ja-JP">オフ</lang>
<lang name="ka-GE">გამორთვა</lang>
<lang name="kk-KZ">Өшірілген</lang>
<lang name="km-KH">បិទ</lang>
<lang name="kn-IN">ಆಫ್</lang>
<lang name="ko-KR">해제</lang>
<lang name="kok-IN">ऑफ करचें</lang>
<lang name="ku-ARAB-IQ">کوژاوە</lang>
<lang name="ky-KG">Өчүрулгөн</lang>
<lang name="lb-LU">Aus</lang>
<lang name="lt-LT">Išjungta</lang>
<lang name="lv-LV">Izslēgts</lang>
<lang name="mi-NZ">Weto ana</lang>
<lang name="mk-MK">Исклучено</lang>
<lang name="ml-IN">ഓഫ്</lang>
<lang name="mn-MN">Idəvxgüĭ</lang>
<lang name="mr-IN">बंद</lang>
<lang name="ms-MY">Mati</lang>
<lang name="mt-MT">Mitfi</lang>
<lang name="nb-NO">Av</lang>
<lang name="ne-NP">निभाउनुहोस्</lang>
<lang name="nl-NL">Uit</lang>
<lang name="nn-NO">Av</lang>
<lang name="nso-ZA">Timilwe</lang>
<lang name="or-IN">ଅଫ୍</lang>
<lang name="pa-ARAB-PK">بند</lang>
<lang name="pa-IN">ਬੰਦ ਕਰੋ</lang>
<lang name="pl-PL">Wyłączone</lang>
<lang name="prs-AF">خاموش</lang>
<lang name="pt-BR">Desligado</lang>
<lang name="pt-PT">Desativado</lang>
<lang name="qps-PLOC">[3Hcgw][Ǿƒƒ ]</lang>
<lang name="qps-PLOCM">‏أبع[Off]לף</lang>
<lang name="qut-GT">Q'atetalik</lang>
<lang name="quz-PE">Tukuchisqa</lang>
<lang name="ro-RO">Dezactivat</lang>
<lang name="ru-RU">Откл.</lang>
<lang name="rw-RW">Irafunze</lang>
<lang name="sd-ARAB-PK">بند کوليو</lang>
<lang name="si-LK">අක්‍රීය</lang>
<lang name="sk-SK">Vypnuté</lang>
<lang name="sl-SI">Izklopljeno</lang>
<lang name="sq-AL">Joaktiv</lang>
<lang name="sr-CYRL-BA">Искључено</lang>
<lang name="sr-CYRL-CS">Искључено</lang>
<lang name="sr-LATN-CS">Isključeno</lang>
<lang name="sv-SE">Av</lang>
<lang name="sw-KE">Zima</lang>
<lang name="ta-IN">அணை</lang>
<lang name="te-IN">ఆఫ్ చేయి</lang>
<lang name="tg-CYRL-TJ">Хомӯш</lang>
<lang name="th-TH">ปิด</lang>
<lang name="ti-ET">ኣጥፍእ</lang>
<lang name="tk-TM">Öçürilen</lang>
<lang name="tn-ZA">Timilwe</lang>
<lang name="tr-TR">Kapalı</lang>
<lang name="tt-RU">Сүндерелгән</lang>
<lang name="ug-CN">يېپىق</lang>
<lang name="uk-UA">Вимк.</lang>
<lang name="ur-PK">آف</lang>
<lang name="uz-LATN-UZ">Och</lang>
<lang name="vi-VN">Tắt</lang>
<lang name="wo-SN">Fay</lang>
<lang name="xh-ZA">Cimile</lang>
<lang name="yo-NG">Pa</lang>
<lang name="zh-HK">關閉</lang>
<lang name="zh-TW">關閉</lang>
<lang name="zu-ZA">Cishile</lang>
</resource>
<resource id="ms-resource://Microsoft.WinJS.1.0/ui/on">
<lang name="zh-CN"></lang>
<lang name="en-US">On</lang>
<lang name="af-ZA">Aan</lang>
<lang name="am-ET">አብራ</lang>
<lang name="ar-SA">تشغيل</lang>
<lang name="as-IN">অন</lang>
<lang name="az-LATN-AZ">Aktiv</lang>
<lang name="be-BY">Укл.</lang>
<lang name="bg-BG">Включено</lang>
<lang name="bn-BD">চালু</lang>
<lang name="bn-IN">চালু</lang>
<lang name="bs-LATN-BA">Uključeno</lang>
<lang name="ca-ES">Activa</lang>
<lang name="ca-ES-VALENCIA">Activa</lang>
<lang name="chr-CHER-US">ᎠᏍᏚᎢᏍᏗ</lang>
<lang name="cs-CZ">Zapnuto</lang>
<lang name="cy-GB">Ar waith</lang>
<lang name="da-DK">Til</lang>
<lang name="de-DE">Ein</lang>
<lang name="el-GR">Ενεργό</lang>
<lang name="en-GB">On</lang>
<lang name="es-ES">Activado</lang>
<lang name="et-EE">Sees</lang>
<lang name="eu-ES">Aktibatuta</lang>
<lang name="fa-IR">روشن</lang>
<lang name="fi-FI">Käytössä</lang>
<lang name="fil-PH">Naka-on</lang>
<lang name="fr-FR">Actif</lang>
<lang name="ga-IE">Air</lang>
<lang name="gd-GB">Air</lang>
<lang name="gl-ES">Activado</lang>
<lang name="gu-IN">ચાલુ</lang>
<lang name="ha-LATN-NG">Kunna</lang>
<lang name="he-IL">פעיל</lang>
<lang name="hi-IN">चालू</lang>
<lang name="hr-HR">Uključeno</lang>
<lang name="hu-HU">Bekapcsolva</lang>
<lang name="hy-AM">Միաց</lang>
<lang name="id-ID">Aktif</lang>
<lang name="ig-NG">Gbanye</lang>
<lang name="is-IS">Virkt</lang>
<lang name="it-IT">Attivato</lang>
<lang name="iu-LATN-CA">Ikumajuq</lang>
<lang name="ja-JP">オン</lang>
<lang name="ka-GE">ჩართვა</lang>
<lang name="kk-KZ">Қосылған</lang>
<lang name="km-KH">បើក</lang>
<lang name="kn-IN">ಆನ್</lang>
<lang name="ko-KR">설정</lang>
<lang name="kok-IN">ऑन करचें</lang>
<lang name="ku-ARAB-IQ">هەڵکراو</lang>
<lang name="ky-KG">Күйгүзүлгөн</lang>
<lang name="lb-LU">Un</lang>
<lang name="lt-LT">Įjungta</lang>
<lang name="lv-LV">Ieslēgts</lang>
<lang name="mi-NZ">Kā ana</lang>
<lang name="mk-MK">Вклученo</lang>
<lang name="ml-IN">ഓൺ</lang>
<lang name="mn-MN">Идэвхтэй</lang>
<lang name="mr-IN">चालू</lang>
<lang name="ms-MY">Hidup</lang>
<lang name="mt-MT">Mixgħul</lang>
<lang name="nb-NO"></lang>
<lang name="ne-NP">खोल्नुहोस्</lang>
<lang name="nl-NL">Aan</lang>
<lang name="nn-NO"></lang>
<lang name="nso-ZA">Goteditšwe</lang>
<lang name="or-IN">ଅନ୍</lang>
<lang name="pa-ARAB-PK">چالُو</lang>
<lang name="pa-IN">ਚਾਲੂ ਕਰੋ</lang>
<lang name="pl-PL">Włączone</lang>
<lang name="prs-AF">روشن</lang>
<lang name="pt-BR">Ligado</lang>
<lang name="pt-PT">Ativado</lang>
<lang name="qps-PLOC">[Aj8Pp][Őņ ]</lang>
<lang name="qps-PLOCM">‏أبع[On]לף</lang>
<lang name="qut-GT">Tzijtalik</lang>
<lang name="quz-PE">Kawsarichisqa</lang>
<lang name="ro-RO">Activat</lang>
<lang name="ru-RU">Вкл.</lang>
<lang name="rw-RW">Irafunguye</lang>
<lang name="sd-ARAB-PK">شروع ڪريو</lang>
<lang name="si-LK">සක්‍රීය</lang>
<lang name="sk-SK">Zapnuté</lang>
<lang name="sl-SI">Vklopljeno</lang>
<lang name="sq-AL">Aktiv</lang>
<lang name="sr-CYRL-BA">Укључено</lang>
<lang name="sr-CYRL-CS">Укључено</lang>
<lang name="sr-LATN-CS">Uključeno</lang>
<lang name="sv-SE"></lang>
<lang name="sw-KE">Washa</lang>
<lang name="ta-IN">இயக்கு</lang>
<lang name="te-IN">ఆన్ చేయి</lang>
<lang name="tg-CYRL-TJ">Фаъол</lang>
<lang name="th-TH">เปิด</lang>
<lang name="ti-ET">ወልዕ</lang>
<lang name="tk-TM">Açyk</lang>
<lang name="tn-ZA">Tshubilwe</lang>
<lang name="tr-TR">Açık</lang>
<lang name="tt-RU">Кабызылган</lang>
<lang name="ug-CN">ئوچۇق</lang>
<lang name="uk-UA">Увімк.</lang>
<lang name="ur-PK">آن</lang>
<lang name="uz-LATN-UZ">Yoq</lang>
<lang name="vi-VN">Bật</lang>
<lang name="wo-SN">Taal</lang>
<lang name="xh-ZA">Layitile</lang>
<lang name="yo-NG">Tàn</lang>
<lang name="zh-HK">開啟</lang>
<lang name="zh-TW">開啟</lang>
<lang name="zu-ZA">Vuliwe</lang>
</resource>
<resource id="license">
<lang name="zh-CN">license_cn.html</lang>
<lang name="en-US">license_en.html</lang>
</resource>
<resource id="MANAGER_APPTITLE">
<lang name="zh-CN">Package Manager</lang>
<lang name="en-US">Package Manager</lang>
</resource>
<resource id="MANAGER_MANAGE">
<lang name="zh-CN">管理</lang>
<lang name="en-US">Manage</lang>
</resource>
<resource id="MANAGER_APP_TITLE">
<lang name="zh-CN">应用</lang>
<lang name="en-US">Application</lang>
</resource>
<resource id="MANAGER_APP_DESCRIPTION">
<lang name="zh-CN">在这里,可以对安装的 Windows 商店应用进行管理。</lang>
<lang name="en-US">Here you can manage the installed Windows Store apps.</lang>
</resource>
<resource id="MANAGER_APP_INSTALLEDAPPS">
<lang name="zh-CN">安装的应用</lang>
<lang name="en-US">Installed Apps</lang>
</resource>
<resource id="MANAGER_APP_INSTALLEDAPPS_LOADING">
<lang name="zh-CN">正在加载应用...</lang>
<lang name="en-US">Loading apps...</lang>
</resource>
<resource id="MANAGER_APP_INSTALLEDAPPS_SUCCEED">
<lang name="zh-CN">已经加载了应用。</lang>
<lang name="en-US">Loaded apps.</lang>
</resource>
<resource id="MANAGER_APP_INSTALLEDAPPS_FAILED">
<lang name="zh-CN">加载时发生错误: {0}</lang>
<lang name="en-US">Error loading apps: {0}</lang>
</resource>
<resource id="MANAGER_APP_REFRESH">
<lang name="zh-CN">刷新</lang>
<lang name="en-US">Refresh</lang>
</resource>
<resource id="MANAGER_APP_ADVANCEOPTIONS">
<lang name="zh-CN">高级选项</lang>
<lang name="en-US">Advanced Options</lang>
</resource>
<resource id="MANAGER_APP_UNINSTALL">
<lang name="zh-CN">卸载</lang>
<lang name="en-US">Uninstall</lang>
</resource>
<resource id="MANAGER_APP_LAUNCH">
<lang name="zh-CN">启动</lang>
<lang name="en-US">Launch</lang>
</resource>
<resource id="MANAGER_APP_CREATESHORTCUT">
<lang name="zh-CN">创建桌面快捷方式</lang>
<lang name="en-US">创建桌面快捷方式</lang>
</resource>
<resource id="MANAGER_MANAGE_FINDAPPS">
<lang name="zh-CN">找到 {0} 个应用</lang>
<lang name="en-US">Found {0} apps.</lang>
</resource>
<resource id="MANAGER_MANAGE_LISTEMPTY">
<lang name="zh-CN">还没有内容...</lang>
<lang name="en-US">No content...</lang>
</resource>
<resource id="MANAGER_MANAGE_SEARCHPLACEHOLDER">
<lang name="zh-CN">搜索此列表</lang>
<lang name="en-US">Search this list</lang>
</resource>
<resource id="MANAGER_APP_SHOWSYSTEMAPP">
<lang name="zh-CN">显示系统应用</lang>
<lang name="en-US">Show system apps</lang>
</resource>
<resource id="MANAGER_APP_SHOWFRAMEWORK">
<lang name="zh-CN">显示依赖项</lang>
<lang name="en-US">Show dependencies</lang>
</resource>
<resource id="MANAGER_APP_IDENTITY">
<lang name="zh-CN">标识</lang>
<lang name="en-US">Identity</lang>
</resource>
<resource id="MANAGER_APP_IDENTITY_NAME">
<lang name="zh-CN">名称</lang>
<lang name="en-US">Name</lang>
</resource>
<resource id="MANAGER_APP_IDENTITY_PUBLISHER">
<lang name="zh-CN">发布者</lang>
<lang name="en-US">Publisher</lang>
</resource>
<resource id="MANAGER_APP_IDENTITY_PUBLISHERID">
<lang name="zh-CN">发布者 ID</lang>
<lang name="en-US">Publisher ID</lang>
</resource>
<resource id="MANAGER_APP_IDENTITY_FAMILYNAME">
<lang name="zh-CN">系列名</lang>
<lang name="en-US">Family Name</lang>
</resource>
<resource id="MANAGER_APP_IDENTITY_FULLNAME">
<lang name="zh-CN">全名</lang>
<lang name="en-US">Full Name</lang>
</resource>
<resource id="MANAGER_APP_IDENTITY_ARCHITECTURE">
<lang name="zh-CN">支持的处理器架构</lang>
<lang name="en-US">Supported processor architectures</lang>
</resource>
<resource id="MANAGER_APP_HASAPPS">
<lang name="zh-CN">具有的应用</lang>
<lang name="en-US">Has Apps</lang>
</resource>
<resource id="MANAGER_APP_HASAPPS_DESC">
<lang name="zh-CN">下面是包具有的应用。现在可以直接在这里启动程序,或者创建桌面快捷方式。</lang>
<lang name="en-US">Below are the apps that are included in this package. You can launch the apps directly from here, or create desktop shortcuts.</lang>
</resource>
<resource id="MANAGER_APP_UNINSTALL_DESC">
<lang name="zh-CN">卸载此应用及其设置。</lang>
<lang name="en-US">Uninstall this app and its settings.</lang>
</resource>
<resource id="MANAGER_APP_UNINSTALL_DESC">
<lang name="zh-CN">将从这台电脑中卸载此应用及其相关信息。</lang>
<lang name="en-US">This app and its related information will be uninstalled from this computer.</lang>
</resource>
<resource id="MANAGER_APP_UNINSTALL_ING">
<lang name="zh-CN">正在卸载...</lang>
<lang name="en-US">Uninstalling...</lang>
</resource>
<resource id="MANAGER_APP_UNINSTALL_PROGRESSING">
<lang name="zh-CN">正在卸载... {0}%</lang>
<lang name="en-US">Uninstalling... {0}%</lang>
</resource>
<resource id="MANAGER_APP_UNINSTALL_SUCCEED">
<lang name="zh-CN">已成功卸载。</lang>
<lang name="en-US">Uninstall succeeded.</lang>
</resource>
</resources>