From 705b0e19152c467f045c2a9327ac22d652fbe373 Mon Sep 17 00:00:00 2001 From: redhoodsu Date: Sun, 11 Dec 2022 18:55:22 +0800 Subject: [PATCH] feat(network): use luna data grid --- src/Info/Info.scss | 2 +- src/Network/Network.js | 191 ++++++++++++++++++++++--------------- src/Network/Network.scss | 62 ++---------- src/Snippets/Snippets.scss | 3 +- src/lib/util.js | 2 - src/style/luna.scss | 8 ++ src/style/style.scss | 1 + test/network.js | 2 +- 8 files changed, 136 insertions(+), 135 deletions(-) diff --git a/src/Info/Info.scss b/src/Info/Info.scss index 09eb5c4..57df21b 100644 --- a/src/Info/Info.scss +++ b/src/Info/Info.scss @@ -13,7 +13,6 @@ .title { position: relative; padding-bottom: 0; - font-size: $font-size-l; color: var(--accent); .icon-copy { position: absolute; @@ -31,6 +30,7 @@ margin: 0; user-select: text; color: var(--foreground); + font-size: $font-size-s; word-break: break-all; table { width: 100%; diff --git a/src/Network/Network.js b/src/Network/Network.js index 7d29f7c..ff3cea1 100644 --- a/src/Network/Network.js +++ b/src/Network/Network.js @@ -1,15 +1,15 @@ import Tool from '../DevTools/Tool' -import isEmpty from 'licia/isEmpty' import $ from 'licia/$' import ms from 'licia/ms' import each from 'licia/each' import last from 'licia/last' import Detail from './Detail' -import map from 'licia/map' -import escape from 'licia/escape' +import throttle from 'licia/throttle' import { getFileName, classPrefix as c } from '../lib/util' import evalCss from '../lib/evalCss' import chobitsu from '../lib/chobitsu' +import LunaDataGrid from 'luna-data-grid' +import ResizeSensor from 'licia/ResizeSensor' export default class Network extends Tool { constructor() { @@ -26,16 +26,53 @@ export default class Network extends Tool { this._container = container this._initTpl() this._detail = new Detail(this._$detail) + this._requestDataGrid = new LunaDataGrid(this._$requests.get(0), { + columns: [ + { + id: 'name', + title: 'Name', + sortable: true, + weight: 30, + }, + { + id: 'method', + title: 'Method', + sortable: true, + weight: 14, + }, + { + id: 'status', + title: 'Status', + sortable: true, + weight: 14, + }, + { + id: 'type', + title: 'Type', + sortable: true, + weight: 14, + }, + { + id: 'size', + title: 'Size', + sortable: true, + weight: 14, + }, + { + id: 'time', + title: 'Time', + sortable: true, + weight: 14, + }, + ], + }) + this._updateDataGridHeight() + this._resizeSensor = new ResizeSensor($el.get(0)) this._bindEvent() } - show() { - super.show() - - this._render() - } clear() { this._requests = {} - this._render() + this._requestDataGrid.clear() } requests() { const ret = [] @@ -44,8 +81,13 @@ export default class Network extends Tool { }) return ret } + _updateDataGridHeight() { + const height = this._$el.offset().height - 41 + this._requestDataGrid.setOption('minHeight', height) + this._requestDataGrid.setOption('maxHeight', height) + } _reqWillBeSent = (params) => { - this._requests[params.requestId] = { + const request = { name: getFileName(params.request.url), url: params.request.url, status: 'pending', @@ -61,60 +103,83 @@ export default class Network extends Tool { reqHeaders: params.request.headers || {}, resHeaders: {}, } + let node + request.render = () => { + const data = { + name: request.name, + method: request.method, + status: request.status, + type: request.subType, + size: request.size, + time: request.displayTime, + } + if (node) { + node.data = data + node.render() + } else { + node = this._requestDataGrid.append(data, { selectable: true }) + $(node.container).data('id', params.requestId) + } + if (request.hasErr) { + $(node.container).addClass(c('request-error')) + } + } + request.render() + this._requests[params.requestId] = request } _resReceivedExtraInfo = (params) => { - const target = this._requests[params.requestId] - if (!target) { + const request = this._requests[params.requestId] + if (!request) { return } - target.resHeaders = params.headers + request.resHeaders = params.headers - this._updateType(target) - this._render() + this._updateType(request) + request.render() } - _updateType(target) { - const contentType = target.resHeaders['content-type'] || '' + _updateType(request) { + const contentType = request.resHeaders['content-type'] || '' const { type, subType } = getType(contentType) - target.type = type - target.subType = subType + request.type = type + request.subType = subType } _resReceived = (params) => { - const target = this._requests[params.requestId] - if (!target) { + const request = this._requests[params.requestId] + if (!request) { return } const { response } = params const { status, headers } = response - target.status = status + request.status = status if (status < 200 || status >= 300) { - target.hasErr = true + request.hasErr = true } if (headers) { - target.resHeaders = headers - this._updateType(target) + request.resHeaders = headers + this._updateType(request) } - this._render() + request.render() } _loadingFinished = (params) => { - const target = this._requests[params.requestId] - if (!target) { + const request = this._requests[params.requestId] + if (!request) { return } const time = params.timestamp * 1000 - target.time = time - target.startTime - target.displayTime = ms(target.time) + request.time = time - request.startTime + request.displayTime = ms(request.time) - target.size = params.encodedDataLength - target.done = true - target.resTxt = chobitsu.domain('Network').getResponseBody({ + request.size = params.encodedDataLength + request.done = true + request.resTxt = chobitsu.domain('Network').getResponseBody({ requestId: params.requestId, }).body - this._render() + request.render() } _bindEvent() { const $el = this._$el @@ -122,16 +187,16 @@ export default class Network extends Tool { const self = this - $el - .on('click', c('.request'), function () { - const id = $(this).data('id') - const data = self._requests[id] + $el.on('click', c('.clear-request'), () => this.clear()) - if (!data.done) return - - self._detail.show(data) - }) - .on('click', c('.clear-request'), () => this.clear()) + this._requestDataGrid.on('select', (node) => { + const id = $(node.container).data('id') + const request = self._requests[id] + if (!request.done) { + return + } + self._detail.show(request) + }) this._detail.on('showSources', function (type, data) { const sources = container.get('sources') @@ -142,6 +207,10 @@ export default class Network extends Tool { container.showTool('sources') }) + this._resizeSensor.addListener( + throttle(() => this._updateDataGridHeight(), 15) + ) + chobitsu.domain('Network').enable() const network = chobitsu.domain('Network') @@ -153,6 +222,7 @@ export default class Network extends Tool { destroy() { super.destroy() + this._resizeSensor.destroy() evalCss.remove(this._style) const network = chobitsu.domain('Network') @@ -170,45 +240,12 @@ export default class Network extends Tool { - +
`) ) this._$detail = $el.find(c('.detail')) this._$requests = $el.find(c('.requests')) } - _render() { - if (!this.active) return - - const renderData = {} - - if (!isEmpty(this._requests)) renderData.requests = this._requests - - let html = `
  • Empty
  • ` - if (renderData.requests) { - html = map( - renderData.requests, - ({ hasErr, name, status, method, subType, size, displayTime }, idx) => { - return `
  • - ${escape(name)} - ${status} - ${method} - ${subType} - ${size} - ${displayTime} -
  • ` - } - ).join('') - } - - this._renderHtml(html) - } - _renderHtml(html) { - if (html === this._lastHtml) return - this._lastHtml = html - this._$requests.html(html) - } } function getType(contentType) { diff --git a/src/Network/Network.scss b/src/Network/Network.scss index fcb4444..02d9452 100644 --- a/src/Network/Network.scss +++ b/src/Network/Network.scss @@ -2,65 +2,21 @@ @import '../style/mixin'; #network { - padding-top: 36px; + padding-top: 40px; .title { - @include absolute(100%, 36px); + @include absolute(100%, 40px); @include right-btn(); background: var(--darker-background); padding: $padding; color: var(--primary); - height: 36px; - border-bottom: 1px solid var(--border); + height: 40px; } - .requests { - @include overflow-auto(y); - height: 100%; - border-bottom: 1px solid var(--border); - margin-bottom: 10px; - li { - display: flex; - width: 100%; - cursor: pointer; - border-bottom: 1px solid var(--border); - height: 41px; - color: var(--foreground); - white-space: nowrap; - &.error { - span { - color: var(--console-error-foreground); - } - } - span { - display: block; - line-height: 40px; - height: 40px; - padding: 0 5px; - font-size: $font-size-s; - vertical-align: top; - text-overflow: ellipsis; - overflow: hidden; - } - .name { - flex: 1; - padding-left: $padding; - } - .status { - width: 40px; - } - .method, - .type { - width: 50px; - } - .size { - width: 70px; - } - .time { - width: 60px; - padding-right: $padding; - } - &:nth-child(even) { - background: var(--contrast); - } + .request-error { + color: var(--console-error-foreground); + } + .luna-data-grid-data-container:focus { + .request-error.luna-data-grid-selected { + background: var(--console-error-background); } } .detail { diff --git a/src/Snippets/Snippets.scss b/src/Snippets/Snippets.scss index ba62627..fc6d3a8 100644 --- a/src/Snippets/Snippets.scss +++ b/src/Snippets/Snippets.scss @@ -19,7 +19,7 @@ padding: $padding; color: var(--primary); background: var(--darker-background); - transition: background $anim-duration; + transition: background-color $anim-duration; .btn { margin-left: 10px; float: right; @@ -31,6 +31,7 @@ } } .description { + font-size: $font-size-s; color: var(--foreground); padding: $padding; transition: background $anim-duration; diff --git a/src/lib/util.js b/src/lib/util.js index a28de8a..cdaded2 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -190,8 +190,6 @@ export function safeStorage(type, memReplacement) { export function getFileName(url) { let ret = last(url.split('/')) - if (ret.indexOf('?') > -1) ret = trim(ret.split('?')[0]) - if (ret === '') { url = new Url(url) ret = url.hostname diff --git a/src/style/luna.scss b/src/style/luna.scss index a99ea0d..6141eec 100644 --- a/src/style/luna.scss +++ b/src/style/luna.scss @@ -181,6 +181,14 @@ } } .luna-data-grid-data-container { + &:focus { + .luna-data-grid-node.luna-data-grid-selected { + background: var(--accent); + } + } + .luna-data-grid-node.luna-data-grid-selected { + background: var(--highlight); + } tr:nth-child(even) { background: var(--contrast); } diff --git a/src/style/style.scss b/src/style/style.scss index cc6838f..ff34d74 100644 --- a/src/style/style.scss +++ b/src/style/style.scss @@ -71,6 +71,7 @@ } h2 { + font-size: $font-size; [class^='icon-'], [class*=' icon-'] { font-weight: normal; diff --git a/test/network.js b/test/network.js index af97e23..75b9ee7 100644 --- a/test/network.js +++ b/test/network.js @@ -7,7 +7,7 @@ describe('network', function () { it('xhr', function (done) { $('.eruda-clear-xhr').click() util.ajax.get(window.location.toString(), function () { - expect($('.eruda-requests li')).toHaveLength(1) + expect($('.eruda-requests .luna-data-grid-node')).toHaveLength(1) done() }) })