Skip to content

Commit

Permalink
Merge pull request #66 from alan16742/master
Browse files Browse the repository at this point in the history
fix: numeric sort
  • Loading branch information
vcheckzen authored Nov 1, 2024
2 parents a37987d + 72c3cd5 commit eea217e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 66 deletions.
7 changes: 1 addition & 6 deletions back-end-cf/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/**
* IS_CN: 如果为世纪互联版本,请将 0 改为 1
* EXPOSE_PATH:暴露路径,如全盘展示请留空,否则按 '/媒体/音乐' 的格式填写
* ONEDRIVE_REFRESHTOKEN: refresh_token
* PASSWD_FILENAME: 密码文件名
* PROTECTED_LAYERS: EXPOSE_PATH 目录密码防护层数,防止猜测目录,默认 -1 为关闭,类似 '/Applications' 需要保护填写为 2(保护 EXPOSE_PATH 及其一级子目录),开启需在 EXPORSE_PATH 目录的 PASSWORD_FILENAME 文件中填写密码
*/
const IS_CN = 0;
const EXPOSE_PATH = '';
const ONEDRIVE_REFRESHTOKEN = '';
const PASSWD_FILENAME = '.password';
Expand Down Expand Up @@ -230,9 +228,6 @@ async function fetchFiles(path, passwd, skipToken, orderby) {
: undefined;
const children = pageRes.value;

if (orderby) {
orderby = orderby.replace('lastModifiedDateTime', 'time');
}
return JSON.stringify({
parent,
skipToken,
Expand All @@ -241,7 +236,7 @@ async function fetchFiles(path, passwd, skipToken, orderby) {
.map((file) => ({
name: file.name,
size: file.size,
time: file.lastModifiedDateTime,
lastModifiedDateTime: file.lastModifiedDateTime,
url: file['@microsoft.graph.downloadUrl'],
}))
.filter((file) => file.name !== PASSWD_FILENAME),
Expand Down
142 changes: 82 additions & 60 deletions front-end/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"
name="viewport"
/>
<link rel="icon" href="data:;base64,=" type="image/x-icon" />
<link
href="//lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/material-design-iconic-font/2.2.0/css/material-design-iconic-font.min.css"
type="text/css"
Expand Down Expand Up @@ -530,7 +531,7 @@
padding-left: 0;
}

.time {
.lastModifiedDateTime {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
Expand All @@ -545,7 +546,7 @@
margin-left: auto;
display: grid;
grid-template-columns: 1fr 1em;
column-gap: 0.5em;
column-gap: 0.6em;
justify-items: right;
}

Expand Down Expand Up @@ -599,7 +600,7 @@
width: 75%;
}

.time {
.lastModifiedDateTime {
display: none !important;
}

Expand Down Expand Up @@ -646,15 +647,10 @@
let xhr = new XMLHttpRequest();
if ('withCredentials' in xhr) {
xhr.open(method, url, true);
} else if (typeof XDomainRequest !== 'undefined') {
xhr = new XDomainRequest();
xhr.open(method, url);
xhr.timeout = timeout;
} else {
xhr = null;
}
if (xhr) {
xhr.timeout = timeout;
}
return xhr;
}

Expand Down Expand Up @@ -846,19 +842,6 @@
function renderFileList(page, fromLoadNextPage) {
switchRightDisplay('list');

const pageRef = page;
if (page.orderby) {
// Not changing file cache, so file tree order is untouched.
const sortField = page.orderby.split(' ').shift();
const files = page.files.toSorted((a, b) =>
a[sortField] < b[sortField] ? -1 : 1
);
if (page.orderby.includes('desc')) {
files.reverse();
}
page = { ...page, files };
}

const formatDate = (date) => {
date = new Date(date);
const addZero = (num) => `${num}`.padStart(2, '0');
Expand Down Expand Up @@ -886,7 +869,8 @@
.content.cloneNode(true);
fileWrapper.querySelector('i').className = `zmdi zmdi-${type}`;
fileWrapper.querySelector('.name').innerText = name;
fileWrapper.querySelector('.time').innerText = formatDate(time);
fileWrapper.querySelector('.lastModifiedDateTime').innerText =
formatDate(time);
[
fileWrapper.querySelector('.size .value').innerText,
fileWrapper.querySelector('.size .unit').innerText,
Expand All @@ -901,6 +885,7 @@
};

const children = [];
const parent = page.parent === window.api.root ? '' : page.parent;
page.files.forEach((file) => {
// Only load readme not all .md files for performance reason.
if (file.name.toLowerCase() === 'readme.md') {
Expand All @@ -918,25 +903,24 @@
switchRightDisplay('upload');
};
} else {
const parent = page.parent === window.api.root ? '' : page.parent;
children.push(
createFileWrapper.bind(
if (!file.toFragment) {
file.toFragment = createFileWrapper.bind(
null,
file.url ? 'file' : 'folder',
file.name,
file.time,
file.lastModifiedDateTime,
file.size,
parent + '/' + file.name,
file.url
)
);
);
}
children.push(file);
}
});

const listContainer = document.getElementById('file-list');
if (!pageRef.lazyRenderStat) {
pageRef.lazyRenderStat = { pageSize: 200 };
const stat = pageRef.lazyRenderStat;
if (!page.lazyRenderStat) {
page.lazyRenderStat = { pageSize: 200 };
const stat = page.lazyRenderStat;
stat.observer = new IntersectionObserver((entries) => {
if (Date.now() - stat.lastRenderedTs <= 500 /* 0.5s */) {
return;
Expand All @@ -945,8 +929,12 @@
entries.forEach((entry) => {
if (entry.isIntersecting) {
stat.lastRenderedTs = Date.now();
if (pageRef.skipToken) {
loadNextPage(pageRef);
// Do not load next page before all the data loaded being rendered.
if (
stat.renderedItems >= stat.children.length &&
page.skipToken
) {
loadNextPage(page);
} else {
renderItems();
}
Expand All @@ -955,34 +943,59 @@
});
});
}
const stat = pageRef.lazyRenderStat;
const stat = page.lazyRenderStat;
stat.children = children;
if (page.compare && !page.skipToken && !fromLoadNextPage) {
// All data loaded before this call, sort them all.
stat.children.sort(page.compare);
}
if (!fromLoadNextPage) {
// Rendering from start, sort all loaded data for business version even if there is data unloaded.
stat.renderedItems = 0;
if (
page.compare &&
page.skipToken &&
window.GLOBAL_CONFIG.IS_BUSINESS
) {
stat.children.sort(page.compare);
}
}
stat.children = children;
renderItems();
renderItems(fromLoadNextPage);

function renderItems() {
// The arg is necessary, or it will always be the value captured at the first time.
function renderItems(fromLoadNextPage) {
const startIndex = stat.renderedItems;
stat.renderedItems += stat.pageSize;
stat.renderedItems = Math.min(
stat.renderedItems,
stat.children.length
);
const toBeRendered = stat.children.slice(
startIndex,
stat.renderedItems
);
if (
page.compare &&
window.GLOBAL_CONFIG.IS_BUSINESS &&
fromLoadNextPage
) {
// Sort the new loaded slice for business version.
toBeRendered.sort(page.compare);
}

const fragment = document.createDocumentFragment();
fragment.append(
...stat.children
.slice(startIndex, stat.renderedItems)
.map((create) => create())
...toBeRendered.map(({ toFragment }) => toFragment())
);
const listContainer = document.getElementById('file-list');
if (startIndex === 0) {
listContainer.replaceChildren(fragment);
} else {
stat.observer.disconnect();
listContainer.lastElementChild.style.backgroundColor = '#f1f1f1';
listContainer.appendChild(fragment);
}
if (pageRef.skipToken || stat.renderedItems < stat.children.length) {
stat.observer?.disconnect();
if (page.skipToken || stat.renderedItems < stat.children.length) {
stat.observer.observe(listContainer.lastElementChild);
}
}
Expand Down Expand Up @@ -1670,9 +1683,9 @@
document.querySelector('.file-upload-progress').dataset.hidden = '1';
document.querySelector('.file-upload-wrapper').dataset.hidden = '0';
} else if (display === 'list') {
const sortOrder =
window.fileCache.get(window.backForwardCache.current)?.orderby ||
'name asc';
const sortOrder = window.fileCache.get(
window.backForwardCache.current
)?.orderby;
document
.querySelectorAll('.list-header .row .file > div')
.forEach((field) => {
Expand Down Expand Up @@ -1839,6 +1852,15 @@
});
}

/**
* 1. 不对左侧目录树排序,仅对右侧文件列表排序。
* 2. 若页面已加载完毕,前端对缓存拷贝整体排序。
* 3. 若页面未加载完毕:
* A. 个人版完全依赖 API 序,前端不排序。
* B. 商业版完全抛弃 API 序:
* a. 从头渲染列表时(打开新文件夹或点击排序按钮),前端对已加载数据的拷贝整体排序,向下滑动时,保证已加载数据显示完再加载新页,确保新页数据渲染到已加载数据后面。
* b. 加载出新页时,前端对新页拷贝单独排序,保证新页数据渲染到已加载数据之后。
*/
function sortList(clickedElem) {
const loadedPages = window.fileCache.get(
window.backForwardCache.current
Expand All @@ -1849,11 +1871,17 @@
.className.includes('up')
? 'desc'
: 'asc';
const reverseFactor = sortOrder === 'asc' ? 1 : -1;
loadedPages.orderby = `${sortField} ${sortOrder}`;
const noSortRequest =
(window.GLOBAL_CONFIG.IS_BUSINESS && sortField !== 'name') ||
!loadedPages.skipToken;
if (noSortRequest) {
loadedPages.compare = (a, b) =>
reverseFactor *
a[sortField]
.toString()
.localeCompare(b[sortField].toString(), undefined, {
numeric: true,
sensitivity: 'base',
});
if (!loadedPages.skipToken || window.GLOBAL_CONFIG.IS_BUSINESS) {
renderFileList(loadedPages);
return;
}
Expand Down Expand Up @@ -2137,14 +2165,8 @@
method: 'POST',
formatPayload: (path, passwd, kvs) => {
const payload = { path, passwd, ...kvs };
const orderby = payload.orderby;
if (
window.GLOBAL_CONFIG.IS_BUSINESS &&
!orderby?.startsWith('name')
) {
if (window.GLOBAL_CONFIG.IS_BUSINESS) {
delete payload['orderby'];
} else if (orderby) {
payload.orderby = orderby.replace('time', 'lastModifiedDateTime');
}
return JSON.stringify(payload);
},
Expand Down Expand Up @@ -2188,7 +2210,7 @@
<div class="file">
<i></i>
<span class="name"></span>
<span class="time"></span>
<span class="lastModifiedDateTime"></span>
<div class="size">
<span class="value"></span>
<span class="unit"></span>
Expand Down Expand Up @@ -2234,7 +2256,7 @@
<span>ITEMS</span>
<i class="zmdi zmdi-chevron-up"></i>
</div>
<div class="time" onclick="sortList(this)">
<div class="lastModifiedDateTime" onclick="sortList(this)">
<span>TIME</span>
<i class="zmdi zmdi-chevron-up"></i>
</div>
Expand Down

0 comments on commit eea217e

Please sign in to comment.