Improve and cleanup Selector even more

This commit is contained in:
the-djmaze 2022-09-09 12:07:05 +02:00
parent 47a861a243
commit 44ac2626ec
3 changed files with 87 additions and 119 deletions

View file

@ -31,17 +31,18 @@ export class Selector {
sItemCheckedSelector,
sItemFocusedSelector
) {
koFocusedItem = (koFocusedItem || ko.observable(null)).extend({ toggleSubscribeProperty: [this, 'focused'] });
koSelectedItem = (koSelectedItem || ko.observable(null)).extend({ toggleSubscribeProperty: [null, 'selected'] });
this.list = koList;
this.listChecked = koComputable(() => this.list.filter(item => item.checked())).extend({ rateLimit: 0 });
this.listChecked = koComputable(() => koList.filter(item => item.checked())).extend({ rateLimit: 0 });
this.focusedItem = koFocusedItem || ko.observable(null);
this.selectedItem = koSelectedItem || ko.observable(null);
this.selectedItemUseCallback = true;
this.focusedItem = koFocusedItem;
this.selectedItem = koSelectedItem;
this.iSelectNextHelper = 0;
this.iFocusedNextHelper = 0;
this.oContentScrollable;
// this.oContentScrollable = null;
this.sItemSelector = sItemSelector;
this.sItemCheckedSelector = sItemCheckedSelector;
@ -52,54 +53,57 @@ export class Selector {
const itemSelectedThrottle = (item => this.itemSelected(item)).debounce(300);
this.listChecked.subscribe((items) => {
this.listChecked.subscribe(items => {
if (items.length) {
if (null === this.selectedItem()) {
if (this.selectedItem.valueHasMutated) {
this.selectedItem.valueHasMutated();
if (null === koSelectedItem()) {
if (koSelectedItem.valueHasMutated) {
koSelectedItem.valueHasMutated();
}
} else {
this.selectedItem(null);
koSelectedItem(null);
}
} else if (this.autoSelect() && this.focusedItem()) {
this.selectedItem(this.focusedItem());
} else if (this.autoSelect() && koFocusedItem()) {
koSelectedItem(koFocusedItem());
}
}, this);
this.selectedItem.subscribe((item) => {
let selectedItemUseCallback = true;
koSelectedItem.subscribe(item => {
if (item) {
this.list.forEach(subItem => subItem.checked(false));
if (this.selectedItemUseCallback) {
koList.forEach(subItem => subItem.checked(false));
if (selectedItemUseCallback) {
itemSelectedThrottle(item);
}
} else if (this.selectedItemUseCallback) {
this.itemSelected(null);
} else if (selectedItemUseCallback) {
this.itemSelected();
}
}, this);
this.selectedItem = this.selectedItem.extend({ toggleSubscribeProperty: [this, 'selected'] });
this.focusedItem = this.focusedItem.extend({ toggleSubscribeProperty: [null, 'focused'] });
koFocusedItem.subscribe(item => item && (this.sLastUid = this.getItemUid(item)), this);
this.focusedItem.subscribe(item => item && (this.sLastUid = this.getItemUid(item)), this);
/**
* Below code is used to keep checked/focused/selected states when array is refreshed.
*/
let aCache = [],
aCheckedCache = [],
mFocused = null,
mSelected = null;
this.list.subscribe(
// Before removing old list
koList.subscribe(
items => {
if (isArray(items)) {
items.forEach(item => {
if (item) {
const uid = this.getItemUid(item);
const uid = this.getItemUid(item);
if (uid) {
aCache.push(uid);
item.checked() && aCheckedCache.push(uid);
if (null === mFocused && item.focused()) {
if (!mFocused && item.focused()) {
mFocused = uid;
}
if (null === mSelected && item.selected()) {
if (!mSelected && item.selected()) {
mSelected = uid;
}
}
@ -110,109 +114,78 @@ export class Selector {
'beforeChange'
);
this.list.subscribe((aItems) => {
let temp = null,
getNext = false,
isNextFocused = mFocused,
isChecked = false,
isSelected = false,
len = 0;
koList.subscribe(aItems => {
selectedItemUseCallback = false;
const uids = [];
this.selectedItemUseCallback = false;
this.focusedItem(null);
this.selectedItem(null);
koFocusedItem(null);
koSelectedItem(null);
if (isArray(aItems)) {
len = aCheckedCache.length;
let temp,
isChecked;
aItems.forEach(item => {
const uid = this.getItemUid(item);
uids.push(uid);
if (uid) {
if (null !== mFocused && mFocused === uid) {
this.focusedItem(item);
mFocused = null;
}
if (mFocused === uid) {
koFocusedItem(item);
mFocused = null;
}
if (0 < len && aCheckedCache.includes(uid)) {
isChecked = true;
item.checked(true);
--len;
}
if (aCheckedCache.includes(uid)) {
item.checked(true);
isChecked = true;
}
if (!isChecked && null !== mSelected && mSelected === uid) {
isSelected = true;
this.selectedItem(item);
mSelected = null;
if (!isChecked && mSelected === uid) {
koSelectedItem(item);
mSelected = null;
}
}
});
this.selectedItemUseCallback = true;
if (!isChecked && !isSelected && this.autoSelect()) {
if (this.focusedItem()) {
this.selectedItem(this.focusedItem());
} else if (aItems.length) {
if (null !== isNextFocused) {
getNext = false;
isNextFocused = aCache.find(sUid => {
if (getNext && uids.includes(sUid)) {
return sUid;
}
if (isNextFocused === sUid) {
getNext = true;
}
return false;
});
if (isNextFocused) {
temp = aItems.find(oItem => isNextFocused === this.getItemUid(oItem));
}
}
this.selectedItem(temp || null);
this.focusedItem(this.selectedItem());
}
}
selectedItemUseCallback = true;
if (
(0 !== this.iSelectNextHelper || 0 !== this.iFocusedNextHelper) &&
(this.iSelectNextHelper || this.iFocusedNextHelper) &&
aItems.length &&
!this.focusedItem()
!koFocusedItem()
) {
temp = null;
if (0 !== this.iFocusedNextHelper) {
temp = aItems[-1 === this.iFocusedNextHelper ? aItems.length - 1 : 0] || null;
if (this.iFocusedNextHelper) {
temp = aItems[-1 === this.iFocusedNextHelper ? aItems.length - 1 : 0];
}
if (!temp && 0 !== this.iSelectNextHelper) {
temp = aItems[-1 === this.iSelectNextHelper ? aItems.length - 1 : 0] || null;
if (!temp && this.iSelectNextHelper) {
temp = aItems[-1 === this.iSelectNextHelper ? aItems.length - 1 : 0];
}
if (temp) {
if (0 !== this.iSelectNextHelper) {
this.selectedItem(temp || null);
if (this.iSelectNextHelper) {
koSelectedItem(temp);
}
this.focusedItem(temp || null);
koFocusedItem(temp);
this.scrollToFocused();
setTimeout(this.scrollToFocused, 100);
}
this.iSelectNextHelper = 0;
this.iFocusedNextHelper = 0;
}
if (!isChecked && !koSelectedItem() && koFocusedItem() && this.autoSelect()) {
koSelectedItem(koFocusedItem());
}
}
aCache = [];
aCheckedCache = [];
mFocused = null;
mSelected = null;
selectedItemUseCallback = true;
});
}
@ -297,14 +270,7 @@ export class Selector {
* @returns {string}
*/
getItemUid(item) {
let uid = '';
const getItemUidCallback = this.oCallbacks.ItemGetUid || null;
if (getItemUidCallback && item) {
uid = getItemUidCallback(item);
}
return uid.toString();
return ((item && this.oCallbacks.ItemGetUid?.(item)) || '').toString();
}
/**
@ -321,25 +287,28 @@ export class Selector {
listLen = list.length,
focused = this.focusedItem();
bShiftKey || (shiftStart = -1);
if (' ' === sEventKey) {
focused?.checked(!focused.checked());
} else if (listLen) {
if (focused) {
if (isArrow) {
let i = list.indexOf(focused);
shiftStart = bShiftKey ? (-1 < shiftStart ? shiftStart : i) : -1;
shiftStart == i && focused.checked(true);
if ('ArrowUp' == sEventKey) {
bShiftKey && shiftStart < i && focused.checked(false);
let i = list.indexOf(focused),
up = 'ArrowUp' == sEventKey;
if (bShiftKey) {
shiftStart = -1 < shiftStart ? shiftStart : i;
shiftStart == i
? focused.checked(true)
: ((up ? shiftStart < i : shiftStart > i) && focused.checked(false));
}
if (up) {
i > 0 && (result = list[--i]);
} else {
bShiftKey && shiftStart > i && focused.checked(false);
if (++i < listLen) {
result = list[i];
}
} else if (++i < listLen) {
result = list[i];
}
bShiftKey && result?.checked(true);
result || this.oCallbacks.UpOrDown?.('ArrowUp' === sEventKey);
result || this.oCallbacks.UpOrDown?.(up);
} else if ('Home' === sEventKey) {
result = list[0];
} else if ('End' === sEventKey) {
@ -442,7 +411,7 @@ export class Selector {
}
}
this.sLastUid = uid || '';
this.sLastUid = uid;
}
/**

View file

@ -28,7 +28,7 @@ export class MailFolderList extends AbstractViewLeft {
constructor() {
super();
this.oContentScrollable = null;
// this.oContentScrollable = null;
this.composeInEdit = ComposePopupView.inEdit;

View file

@ -352,13 +352,12 @@ export class MailMessageList extends AbstractViewRight {
return false;
});
if (!SettingsUserStore.usePreviewPane() && !MessageUserStore.message()) {
this.selector.iFocusedNextHelper = up ? -1 : 1;
} else {
this.selector.iSelectNextHelper = up ? -1 : 1;
}
if (up ? prev : next) {
if (SettingsUserStore.usePreviewPane() || MessageUserStore.message()) {
this.selector.iSelectNextHelper = up ? -1 : 1;
} else {
this.selector.iFocusedNextHelper = up ? -1 : 1;
}
this.selector.unselect();
this.gotoPage(up ? prev : next);
}