mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-06-19 05:40:12 +10:00
Updated manager and added appx manifest reader.
This commit is contained in:
@@ -0,0 +1,479 @@
|
||||
(function(global) {
|
||||
"use strict";
|
||||
global.DataView = {
|
||||
ChangeType: {
|
||||
add: "add",
|
||||
remove: "remove",
|
||||
change: "change",
|
||||
clear: "clear",
|
||||
move: "move",
|
||||
sort: "sort",
|
||||
},
|
||||
};
|
||||
var childAnimeDuration = 120;
|
||||
var parentAnimeDuration = 400;
|
||||
|
||||
function showItemAmine(node) {
|
||||
return Windows.UI.Animation.runAsync(node, [
|
||||
Windows.UI.Animation.Keyframes.Scale.up,
|
||||
Windows.UI.Animation.Keyframes.Opacity.visible,
|
||||
], childAnimeDuration);
|
||||
}
|
||||
|
||||
function hideItemAmine(node) {
|
||||
return Windows.UI.Animation.runAsync(node, [
|
||||
Windows.UI.Animation.Keyframes.Scale.down,
|
||||
Windows.UI.Animation.Keyframes.Opacity.hidden,
|
||||
], childAnimeDuration);
|
||||
}
|
||||
|
||||
function updateItemAmine(node, updateCallback) {
|
||||
return Windows.UI.Animation.runAsync(node, [
|
||||
Windows.UI.Animation.Keyframes.Opacity.hidden,
|
||||
Windows.UI.Animation.Keyframes.Scale.down
|
||||
], 120).then(function() {
|
||||
if (updateCallback && typeof updateCallback === 'function') {
|
||||
updateCallback(node);
|
||||
}
|
||||
return Windows.UI.Animation.runAsync(node, [
|
||||
Windows.UI.Animation.Keyframes.Opacity.visible,
|
||||
Windows.UI.Animation.Keyframes.Scale.up
|
||||
], 120);
|
||||
}).then(function() {
|
||||
return node;
|
||||
});
|
||||
}
|
||||
|
||||
function PMChangeEvent(type, datas, detailOperation) {
|
||||
this.type = type; // ChangeType
|
||||
this.datas = datas || []; // 受影响的数据
|
||||
this.detail = detailOperation || null;
|
||||
}
|
||||
|
||||
function PMDataSource() {
|
||||
var _list = [];
|
||||
var _listeners = [];
|
||||
this.subscribe = function(fn) {
|
||||
if (typeof fn === "function") {
|
||||
_listeners.push(fn);
|
||||
}
|
||||
};
|
||||
|
||||
function emit(evt) {
|
||||
for (var i = 0; i < _listeners.length; i++) {
|
||||
_listeners[i](evt);
|
||||
}
|
||||
}
|
||||
this.add = function(item) {
|
||||
_list.push(item);
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.add, [item], { index: _list.length - 1 }
|
||||
));
|
||||
};
|
||||
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 }
|
||||
));
|
||||
};
|
||||
this.changeAt = function(index, newItem) {
|
||||
if (index < 0 || index >= _list.length) return;
|
||||
_list[index] = newItem;
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.change, [newItem], { index: index }
|
||||
));
|
||||
};
|
||||
this.clear = function() {
|
||||
_list.length = 0;
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.clear
|
||||
));
|
||||
};
|
||||
this.move = function(from, to) {
|
||||
if (from === to ||
|
||||
from < 0 || to < 0 ||
|
||||
from >= _list.length || to >= _list.length) {
|
||||
return;
|
||||
}
|
||||
var item = _list.splice(from, 1)[0];
|
||||
_list.splice(to, 0, item);
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.move, [item], { from: from, to: to }
|
||||
));
|
||||
};
|
||||
this.sort = function(compareFn) {
|
||||
_list.sort(compareFn);
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.sort,
|
||||
_list.slice(0), { compare: compareFn }
|
||||
));
|
||||
};
|
||||
this.get = function() {
|
||||
return _list.slice(0);
|
||||
};
|
||||
this.addList = function(list, keySelector) {
|
||||
if (!list || !list.length) return;
|
||||
|
||||
var added = [];
|
||||
var changed = [];
|
||||
|
||||
var useKey = keySelector !== void 0;
|
||||
var getKey;
|
||||
|
||||
if (keySelector === null) {
|
||||
getKey = function(item) {
|
||||
return item && item.id;
|
||||
};
|
||||
} else if (typeof keySelector === "function") {
|
||||
getKey = keySelector;
|
||||
}
|
||||
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var item = list[i];
|
||||
|
||||
if (!useKey) {
|
||||
_list.push(item);
|
||||
added.push({ item: item, index: _list.length - 1 });
|
||||
continue;
|
||||
}
|
||||
|
||||
var key = getKey(item);
|
||||
if (key === void 0) {
|
||||
_list.push(item);
|
||||
added.push({ item: item, index: _list.length - 1, key: key });
|
||||
continue;
|
||||
}
|
||||
|
||||
var found = -1;
|
||||
for (var j = 0; j < _list.length; j++) {
|
||||
if (getKey(_list[j]) === key) {
|
||||
found = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found >= 0) {
|
||||
_list[found] = item;
|
||||
changed.push({ item: item, index: found, key: key });
|
||||
} else {
|
||||
_list.push(item);
|
||||
added.push({ item: item, index: _list.length - 1, key: key });
|
||||
}
|
||||
}
|
||||
|
||||
// 统一发出一个事件
|
||||
if (added.length > 0) {
|
||||
emit(new PMChangeEvent(DataView.ChangeType.add, added));
|
||||
}
|
||||
if (changed.length > 0) {
|
||||
emit(new PMChangeEvent(DataView.ChangeType.change, changed));
|
||||
}
|
||||
};
|
||||
this.updateList = function(list, fnGetKey) {
|
||||
if (!list) list = [];
|
||||
|
||||
var getKey;
|
||||
|
||||
if (fnGetKey === null) {
|
||||
getKey = function(item) {
|
||||
return item && item.id;
|
||||
};
|
||||
} else if (typeof fnGetKey === "function") {
|
||||
getKey = fnGetKey;
|
||||
} else {
|
||||
// 不提供 key:直接整体替换
|
||||
_list = list.slice(0);
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.clear
|
||||
));
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.add,
|
||||
list.map(function(item, index) {
|
||||
return { item: item, index: index };
|
||||
})
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
var oldList = _list;
|
||||
var newList = list;
|
||||
|
||||
var oldKeyIndex = {};
|
||||
var newKeyIndex = {};
|
||||
|
||||
var i;
|
||||
|
||||
// 建立旧列表 key → index
|
||||
for (i = 0; i < oldList.length; i++) {
|
||||
var ok = getKey(oldList[i]);
|
||||
if (ok !== void 0) {
|
||||
oldKeyIndex[ok] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// 建立新列表 key → index
|
||||
for (i = 0; i < newList.length; i++) {
|
||||
var nk = getKey(newList[i]);
|
||||
if (nk !== void 0) {
|
||||
newKeyIndex[nk] = i;
|
||||
}
|
||||
}
|
||||
|
||||
var added = [];
|
||||
var changed = [];
|
||||
var removed = [];
|
||||
|
||||
// 1️⃣ 找 remove
|
||||
for (i = oldList.length - 1; i >= 0; i--) {
|
||||
var oldItem = oldList[i];
|
||||
var oldKey = getKey(oldItem);
|
||||
|
||||
if (oldKey === void 0 || newKeyIndex[oldKey] === void 0) {
|
||||
removed.push({
|
||||
item: oldItem,
|
||||
index: i,
|
||||
key: oldKey
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 2️⃣ 找 add / change
|
||||
for (i = 0; i < newList.length; i++) {
|
||||
var newItem = newList[i];
|
||||
var newKey = getKey(newItem);
|
||||
|
||||
if (newKey === void 0 || oldKeyIndex[newKey] === void 0) {
|
||||
added.push({
|
||||
item: newItem,
|
||||
index: i,
|
||||
key: newKey
|
||||
});
|
||||
} else {
|
||||
var oldIndex = oldKeyIndex[newKey];
|
||||
var oldItem2 = oldList[oldIndex];
|
||||
|
||||
if (oldItem2 !== newItem) {
|
||||
changed.push({
|
||||
item: newItem,
|
||||
index: oldIndex,
|
||||
key: newKey
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ 执行 remove(从后往前)
|
||||
if (removed.length > 0) {
|
||||
for (i = 0; i < removed.length; i++) {
|
||||
_list.splice(removed[i].index, 1);
|
||||
}
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.remove,
|
||||
removed
|
||||
));
|
||||
}
|
||||
|
||||
// 4️⃣ 执行 add / change(重建顺序)
|
||||
_list = newList.slice(0);
|
||||
|
||||
if (added.length > 0) {
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.add,
|
||||
added
|
||||
));
|
||||
}
|
||||
|
||||
if (changed.length > 0) {
|
||||
emit(new PMChangeEvent(
|
||||
DataView.ChangeType.change,
|
||||
changed
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function PMDataListView(container, templateFn) {
|
||||
this.container = container;
|
||||
this.templateFn = templateFn;
|
||||
this.listViewControl = this;
|
||||
}
|
||||
PMDataListView.prototype.bind = function(ds) {
|
||||
var self = this;
|
||||
var items = ds.get();
|
||||
self.container.innerHTML = "";
|
||||
|
||||
// 动画队列,保证异步操作不会乱序
|
||||
var queue = Promise.resolve();
|
||||
|
||||
function renderItem(data, index) {
|
||||
var el = self.templateFn(data, index);
|
||||
|
||||
el.addEventListener("click", function() {
|
||||
self._toggleSelect(el);
|
||||
});
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
// 初始化渲染
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
self.container.appendChild(renderItem(items[i], i));
|
||||
}
|
||||
|
||||
ds.subscribe(function(evt) {
|
||||
|
||||
// 把每次事件放进队列,保证顺序执行
|
||||
queue = queue.then(function() {
|
||||
switch (evt.type) {
|
||||
|
||||
case DataView.ChangeType.add:
|
||||
{
|
||||
// evt.datas = [{item, index}, ...]
|
||||
var datas = evt.datas;
|
||||
|
||||
// 先批量 append 到 DOM(顺序必须保持)
|
||||
var nodes = [];
|
||||
for (var i = 0; i < datas.length; i++) {
|
||||
var n = renderItem(datas[i].item, datas[i].index);
|
||||
nodes.push(n);
|
||||
self.container.appendChild(n);
|
||||
}
|
||||
|
||||
// 如果数量>=20,动画并行,否则串行
|
||||
if (datas.length >= 20) {
|
||||
var promises = [];
|
||||
for (var j = 0; j < nodes.length; j++) {
|
||||
promises.push(showItemAmine(nodes[j]));
|
||||
}
|
||||
return Promise.all(promises);
|
||||
} else {
|
||||
// 串行
|
||||
var p = Promise.resolve();
|
||||
for (var k = 0; k < nodes.length; k++) {
|
||||
(function(node) {
|
||||
p = p.then(function() {
|
||||
return showItemAmine(node);
|
||||
});
|
||||
})(nodes[k]);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
case DataView.ChangeType.remove:
|
||||
{
|
||||
var node = self.container.children[evt.detail.index];
|
||||
if (!node) return;
|
||||
|
||||
// 隐藏动画完成后再移除
|
||||
return hideItemAmine(node).then(function() {
|
||||
self.container.removeChild(node);
|
||||
});
|
||||
}
|
||||
|
||||
case DataView.ChangeType.change:
|
||||
{
|
||||
var oldNode = self.container.children[evt.detail.index];
|
||||
if (!oldNode) return;
|
||||
|
||||
// 先淡出旧节点
|
||||
return hideItemAmine(oldNode).then(function() {
|
||||
// 替换节点
|
||||
var newNode = renderItem(evt.datas[0], evt.detail.index);
|
||||
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 ref = self.container.children[evt.detail.to] || null;
|
||||
if (node) self.container.insertBefore(node, ref);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
case DataView.ChangeType.sort:
|
||||
{
|
||||
self.container.innerHTML = "";
|
||||
for (var i = 0; i < evt.datas.length; i++) {
|
||||
self.container.appendChild(renderItem(evt.datas[i], i));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
PMDataListView.prototype._toggleSelect = function(ele) {
|
||||
// 如果选择模式为 none,则不处理
|
||||
if (this.selectionMode === "none") return;
|
||||
|
||||
var isSelected = ele.classList.contains("selected");
|
||||
|
||||
if (this.selectionMode === "single") {
|
||||
// 单选:先取消所有选中
|
||||
this._clearSelected();
|
||||
if (!isSelected) {
|
||||
ele.classList.add("selected");
|
||||
}
|
||||
} else if (this.selectionMode === "multiple") {
|
||||
// 多选:点一次切换状态
|
||||
if (isSelected) {
|
||||
ele.classList.remove("selected");
|
||||
} else {
|
||||
ele.classList.add("selected");
|
||||
}
|
||||
}
|
||||
};
|
||||
PMDataListView.prototype._clearSelected = function() {
|
||||
var selected = this.container.querySelectorAll(".selected");
|
||||
for (var i = 0; i < selected.length; i++) {
|
||||
selected[i].classList.remove("selected");
|
||||
}
|
||||
};
|
||||
Object.defineProperty(PMDataListView.prototype, "selectionMode", {
|
||||
get: function() {
|
||||
return this._selectionMode || "none";
|
||||
},
|
||||
set: function(value) {
|
||||
var mode = String(value).toLowerCase();
|
||||
if (mode !== "none" && mode !== "single" && mode !== "multiple") {
|
||||
mode = "none";
|
||||
}
|
||||
this._selectionMode = mode;
|
||||
|
||||
// 切换模式时,清空选中状态(可选)
|
||||
if (mode === "none") {
|
||||
this._clearSelected();
|
||||
}
|
||||
if (mode === "single") {
|
||||
// 单选模式:如果多选了多个,保留第一个
|
||||
var selected = this.container.querySelectorAll(".selected");
|
||||
if (selected.length > 1) {
|
||||
for (var i = 1; i < selected.length; i++) {
|
||||
selected[i].classList.remove("selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.defineProperty(PMDataListView.prototype, "selectedItems", {
|
||||
get: function() {
|
||||
return Array.prototype.slice.call(this.container.querySelectorAll(".selected"));
|
||||
}
|
||||
});
|
||||
|
||||
global.DataView.ChangeEvent = PMChangeEvent;
|
||||
global.DataView.DataSource = PMDataSource;
|
||||
global.DataView.ListView = PMDataListView;
|
||||
})(this);
|
||||
Reference in New Issue
Block a user