From 03d97f1aa1648bde10613083e50d65090c0476aa Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 9 Apr 2018 17:22:17 +0900 Subject: [PATCH 1/4] virtualize beatmap listing --- package.json | 1 + .../assets/coffee/react/beatmaps/main.coffee | 30 ++++++++++++++----- resources/assets/lib/import-shims.coffee | 2 ++ yarn.lock | 14 +++++++++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 318292b7b63..4543165e92b 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "react-autosize-textarea": "*", "react-dom": "^16.2.0", "react-dom-factories": "^1.0.0", + "react-virtual-list": "^2.2.4", "require-dir": "^0.3.2", "retina.js": "^1.1.0", "timeago": "^1.5.0", diff --git a/resources/assets/coffee/react/beatmaps/main.coffee b/resources/assets/coffee/react/beatmaps/main.coffee index d0d6964c5d5..5babb119f8f 100644 --- a/resources/assets/coffee/react/beatmaps/main.coffee +++ b/resources/assets/coffee/react/beatmaps/main.coffee @@ -18,6 +18,25 @@ {div} = ReactDOMFactories el = React.createElement +VirtualList = window.VirtualList + +ListRender = ({ virtual, itemHeight }) -> + console.log virtual.style + style = _.extend {}, virtual.style + div + style: style + div + className: 'beatmapsets__items' + virtual.items.map (item) -> + div + className: 'beatmapsets__item' + style: + height: 205 + key: item.id + el BeatmapsetPanel, beatmap: item + +BeatmapList = VirtualList()(ListRender) + class Beatmaps.Main extends React.PureComponent constructor: (props) -> @@ -77,13 +96,10 @@ class Beatmaps.Main extends React.PureComponent div className: 'beatmapsets__content' if @state.beatmaps.length > 0 - div - className: 'beatmapsets__items' - for beatmap in @state.beatmaps - div - className: 'beatmapsets__item' - key: beatmap.id - el BeatmapsetPanel, beatmap: beatmap + el BeatmapList, + items: @state.beatmaps + itemBuffer: 0 + itemHeight: 205 else div className: 'beatmapsets__empty', diff --git a/resources/assets/lib/import-shims.coffee b/resources/assets/lib/import-shims.coffee index 527d4c7abe9..b6925740953 100644 --- a/resources/assets/lib/import-shims.coffee +++ b/resources/assets/lib/import-shims.coffee @@ -21,9 +21,11 @@ import { StoreCheckout } from 'store-checkout' import Promise from 'promise-polyfill' import TextareaAutosize from 'react-autosize-textarea' +import VirtualList from 'react-virtual-list' # polyfill non-Edge IE window.Promise ?= Promise window.StoreCheckout = StoreCheckout window.TextareaAutosize = TextareaAutosize +window.VirtualList = VirtualList diff --git a/yarn.lock b/yarn.lock index da31b78f71c..e3ee50c2f83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5079,6 +5079,14 @@ promise@^7.1.1: dependencies: asap "~2.0.3" +prop-types@^15.5.10: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + prop-types@^15.5.6, prop-types@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" @@ -5216,6 +5224,12 @@ react-dom@^16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" +react-virtual-list@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/react-virtual-list/-/react-virtual-list-2.2.4.tgz#bbeb4938436f80ddbff4f8724f43de2117085691" + dependencies: + prop-types "^15.5.10" + react@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" From 6664fc36197db2beb748d1e478243e59150a69f3 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 9 Apr 2018 19:37:51 +0900 Subject: [PATCH 2/4] change number of columns to render when window size changes. proper resizing with un-forked version --- .../assets/coffee/react/beatmaps/main.coffee | 39 ++++++++++++++----- resources/assets/less/bem/beatmapsets.less | 5 +++ .../assets/less/bootstrap-variables.less | 2 +- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/resources/assets/coffee/react/beatmaps/main.coffee b/resources/assets/coffee/react/beatmaps/main.coffee index 5babb119f8f..9d94b2c3670 100644 --- a/resources/assets/coffee/react/beatmaps/main.coffee +++ b/resources/assets/coffee/react/beatmaps/main.coffee @@ -20,20 +20,23 @@ el = React.createElement VirtualList = window.VirtualList +ITEM_HEIGHT = 205 # needs to be known in advance to calculate size of virtual scrolling area. + ListRender = ({ virtual, itemHeight }) -> - console.log virtual.style style = _.extend {}, virtual.style div style: style div className: 'beatmapsets__items' - virtual.items.map (item) -> + virtual.items.map (row) -> div - className: 'beatmapsets__item' - style: - height: 205 - key: item.id - el BeatmapsetPanel, beatmap: item + className: 'beatmapsets__items-row' + key: (beatmap.id for beatmap in row).join('-') + for beatmap in row + div + className: 'beatmapsets__item' + key: beatmap.id + el BeatmapsetPanel, beatmap: beatmap BeatmapList = VirtualList()(ListRender) @@ -50,6 +53,7 @@ class Beatmaps.Main extends React.PureComponent @state = prevState.state if prevState.url == location.href @state ?= _.extend beatmaps: @props.beatmaps + columnCount: @columnCount() paging: page: 1 url: laroute.route('beatmapsets.search') @@ -61,6 +65,20 @@ class Beatmaps.Main extends React.PureComponent @stateFromUrl() + columnCount: () -> + # see @screen-sm-min + if window.innerWidth < 900 then 1 else 2 + + + updateColumnCount: () => + @setState (prevState) => + count = @columnCount() + # The list component has to be recreated for correct sizing. + BeatmapList = VirtualList()(ListRender) if prevState.columnCount != count + + columnCount: count + + componentDidMount: => $(document).on 'beatmap:load_more.beatmaps', @loadMore $(document).on 'beatmap:search:start.beatmaps', @search @@ -68,6 +86,7 @@ class Beatmaps.Main extends React.PureComponent $(document).on 'beatmap:search:filtered.beatmaps', @updateFilters $(document).on 'turbolinks:before-visit.beatmaps', @recordUrl $(document).on 'turbolinks:before-cache.beatmaps', @saveState + $(window).on 'resize.beatmaps', @updateColumnCount componentWillUnmount: => @@ -97,9 +116,9 @@ class Beatmaps.Main extends React.PureComponent className: 'beatmapsets__content' if @state.beatmaps.length > 0 el BeatmapList, - items: @state.beatmaps - itemBuffer: 0 - itemHeight: 205 + items: _.chunk(@state.beatmaps, @state.columnCount) + itemBuffer: 5 + itemHeight: ITEM_HEIGHT else div className: 'beatmapsets__empty', diff --git a/resources/assets/less/bem/beatmapsets.less b/resources/assets/less/bem/beatmapsets.less index 0ee5d927af9..2f2523480ac 100644 --- a/resources/assets/less/bem/beatmapsets.less +++ b/resources/assets/less/bem/beatmapsets.less @@ -52,4 +52,9 @@ display: flex; flex-wrap: wrap; } + + &__items-row { + display: flex; + width: 100%; + } } diff --git a/resources/assets/less/bootstrap-variables.less b/resources/assets/less/bootstrap-variables.less index df5dd76b9d2..d6cce59806c 100644 --- a/resources/assets/less/bootstrap-variables.less +++ b/resources/assets/less/bootstrap-variables.less @@ -53,7 +53,7 @@ @input-color: @gray-dark; @input-border-focus: @pink; -@screen-sm-min: 900px; // sync with osu.isDesktop +@screen-sm-min: 900px; // sync with osu.isDesktop, react/beatmaps/main.coffee @screen-lg-min: 1300px; @screen-md-min: @screen-sm-min; From 2a182319aecc7dfe7383c0dc831dcb3252b90808 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 16 Apr 2018 18:49:29 +0900 Subject: [PATCH 3/4] columnCount should be overriden even if reloading state --- resources/assets/coffee/react/beatmaps/main.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/assets/coffee/react/beatmaps/main.coffee b/resources/assets/coffee/react/beatmaps/main.coffee index 9d94b2c3670..a9e8cc3f7a5 100644 --- a/resources/assets/coffee/react/beatmaps/main.coffee +++ b/resources/assets/coffee/react/beatmaps/main.coffee @@ -53,7 +53,6 @@ class Beatmaps.Main extends React.PureComponent @state = prevState.state if prevState.url == location.href @state ?= _.extend beatmaps: @props.beatmaps - columnCount: @columnCount() paging: page: 1 url: laroute.route('beatmapsets.search') @@ -64,6 +63,8 @@ class Beatmaps.Main extends React.PureComponent isExpanded: null @stateFromUrl() + @state.columnCount = @columnCount() + columnCount: () -> # see @screen-sm-min From 5f7b1a6aea658e665a196b69d93e45ac575b55a8 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Tue, 17 Apr 2018 14:07:44 +0900 Subject: [PATCH 4/4] osu.isDesktop() is a thing --- resources/assets/coffee/react/beatmaps/main.coffee | 3 +-- resources/assets/less/bootstrap-variables.less | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/assets/coffee/react/beatmaps/main.coffee b/resources/assets/coffee/react/beatmaps/main.coffee index a9e8cc3f7a5..0de3e4b2a93 100644 --- a/resources/assets/coffee/react/beatmaps/main.coffee +++ b/resources/assets/coffee/react/beatmaps/main.coffee @@ -67,8 +67,7 @@ class Beatmaps.Main extends React.PureComponent columnCount: () -> - # see @screen-sm-min - if window.innerWidth < 900 then 1 else 2 + if osu.isDesktop() then 2 else 1 updateColumnCount: () => diff --git a/resources/assets/less/bootstrap-variables.less b/resources/assets/less/bootstrap-variables.less index d6cce59806c..df5dd76b9d2 100644 --- a/resources/assets/less/bootstrap-variables.less +++ b/resources/assets/less/bootstrap-variables.less @@ -53,7 +53,7 @@ @input-color: @gray-dark; @input-border-focus: @pink; -@screen-sm-min: 900px; // sync with osu.isDesktop, react/beatmaps/main.coffee +@screen-sm-min: 900px; // sync with osu.isDesktop @screen-lg-min: 1300px; @screen-md-min: @screen-sm-min;