mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Created list that renders only currently visible items
This commit is contained in:
parent
18bb02244f
commit
ec259f866f
@ -24,6 +24,20 @@ class ElectronAppWrapper {
|
||||
return this.logger_;
|
||||
}
|
||||
|
||||
store() {
|
||||
return this.store_;
|
||||
}
|
||||
|
||||
dispatch(action) {
|
||||
return this.store().dispatch(action);
|
||||
}
|
||||
|
||||
windowContentSize() {
|
||||
if (!this.win_) return { width: 0, height: 0 };
|
||||
const s = this.win_.getContentSize();
|
||||
return { width: s[0], height: s[1] };
|
||||
}
|
||||
|
||||
createWindow() {
|
||||
// Create the browser window.
|
||||
this.win_ = new BrowserWindow({width: 800, height: 600})
|
||||
@ -45,6 +59,18 @@ class ElectronAppWrapper {
|
||||
// when you should delete the corresponding element.
|
||||
this.win_ = null
|
||||
})
|
||||
|
||||
this.win_.on('resize', () => {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_CONTENT_SIZE_SET',
|
||||
size: this.windowContentSize(),
|
||||
});
|
||||
});
|
||||
|
||||
this.dispatch({
|
||||
type: 'WINDOW_CONTENT_SIZE_SET',
|
||||
size: this.windowContentSize(),
|
||||
});
|
||||
}
|
||||
|
||||
async waitForElectronAppReady() {
|
||||
|
@ -1,16 +1,66 @@
|
||||
class ItemList extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.scrollTop_ = 0;
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.setState({
|
||||
topItemIndex: this.topItemIndex(),
|
||||
bottomItemIndex: this.bottomItemIndex(),
|
||||
});
|
||||
}
|
||||
|
||||
onScroll(scrollTop) {
|
||||
this.scrollTop_ = scrollTop;
|
||||
|
||||
this.setState({
|
||||
topItemIndex: this.topItemIndex(),
|
||||
bottomItemIndex: this.bottomItemIndex(),
|
||||
});
|
||||
}
|
||||
|
||||
topItemIndex() {
|
||||
return Math.floor(this.scrollTop_ / this.props.itemHeight);
|
||||
}
|
||||
|
||||
visibleItemCount() {
|
||||
return Math.ceil(this.props.style.height / this.props.itemHeight);
|
||||
}
|
||||
|
||||
bottomItemIndex() {
|
||||
let r = this.topItemIndex() + this.visibleItemCount();
|
||||
if (r >= this.props.items.length) r = this.props.items.length - 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
render() {
|
||||
const items = this.props.items;
|
||||
|
||||
let itemComps = [];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (!this.props.itemHeight) throw new Error('itemHeight is required');
|
||||
|
||||
const blankItem = function(key, height) {
|
||||
return <div key={key} style={{height:height}}></div>
|
||||
}
|
||||
|
||||
let itemComps = [blankItem('top', this.state.topItemIndex * this.props.itemHeight)];
|
||||
|
||||
for (let i = this.state.topItemIndex; i <= this.state.bottomItemIndex; i++) {
|
||||
const itemComp = this.props.itemRenderer(i, items[i]);
|
||||
itemComps.push(itemComp);
|
||||
}
|
||||
|
||||
itemComps.push(blankItem('bottom', (items.length - this.state.bottomItemIndex - 1) * this.props.itemHeight));
|
||||
|
||||
let classes = ['item-list'];
|
||||
if (this.props.className) classes.push(this.props.className);
|
||||
|
||||
const that = this;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.join(' ')} style={this.props.style} onScroll={ (event) => { this.onScroll(event.target.scrollTop) }}>
|
||||
{ itemComps }
|
||||
</div>
|
||||
);
|
||||
|
@ -10,21 +10,25 @@ class NoteListComponent extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={"note-list"}>
|
||||
<h1>Notes</h1>
|
||||
<ItemList
|
||||
items={this.props.notes}
|
||||
itemRenderer={ (index, item) => { return this.itemRenderer(index, item) } }
|
||||
/>
|
||||
</div>
|
||||
<ItemList
|
||||
itemHeight={this.props.itemHeight}
|
||||
style={this.props.style}
|
||||
className={"note-list"}
|
||||
items={this.props.notes}
|
||||
itemRenderer={ (index, item) => { return this.itemRenderer(index, item) } }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
let notes = [];
|
||||
for (let i = 0; i < 100; i++) notes.push({ title: "Note " + i });
|
||||
|
||||
return {
|
||||
notes: state.notes,
|
||||
//notes: state.notes,
|
||||
notes: notes,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -10,17 +10,29 @@ const { app } = require('electron').remote.require('./app');
|
||||
class ReactRootComponent extends React.Component {
|
||||
|
||||
render() {
|
||||
const style = {
|
||||
width: this.props.size.width,
|
||||
height: this.props.size.height,
|
||||
};
|
||||
|
||||
const noteListStyle = {
|
||||
width: this.props.size.width,
|
||||
height: this.props.size.height,
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{height: "1000px"}}>
|
||||
<NoteList></NoteList>
|
||||
<div style={style}>
|
||||
<NoteList itemHeight={40} style={noteListStyle}></NoteList>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {};
|
||||
return {
|
||||
size: state.windowContentSize,
|
||||
};
|
||||
};
|
||||
|
||||
const ReactRoot = connect(mapStateToProps)(ReactRootComponent);
|
||||
|
@ -6,7 +6,7 @@
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div style="height: '1000px';" id="react-root"></div>
|
||||
<div id="react-root"></div>
|
||||
<script src="gui/Root.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,5 +1,19 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#react-root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.item-list {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.note-list .item {
|
||||
height: 40px;
|
||||
height: 40px; /* This must match NoteList.itemHeight */
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ const defaultState = {
|
||||
routeName: 'Welcome',
|
||||
params: {},
|
||||
},
|
||||
windowContentSize: { width: 0, height: 0 },
|
||||
};
|
||||
|
||||
let navHistory = [];
|
||||
@ -410,6 +411,12 @@ const reducer = (state = defaultState, action) => {
|
||||
newState.appState = action.state;
|
||||
break;
|
||||
|
||||
case 'WINDOW_CONTENT_SIZE_SET':
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
newState.windowContentSize = action.size;
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
error.message = 'In reducer: ' + error.message + ' Action: ' + JSON.stringify(action);
|
||||
|
Loading…
Reference in New Issue
Block a user