import React from 'react'; import Component from '../component'; import {last} from '../utils/array'; import {decorate, getTermProps} from '../utils/plugins'; import Term_ from './term'; const Term = decorate(Term_, 'Term'); export default class Terms extends Component { constructor(props, context) { super(props, context); this.terms = {}; this.bound = new WeakMap(); this.onRef = this.onRef.bind(this); props.ref_(this); } componentWillReceiveProps(next) { const {write} = next; if (write && this.props.write !== write) { this.getTermByUid(write.uid).write(write.data); } // if we just rendered, we consider the first tab active // why is this decided here? because what session becomes // active is a *view* and *layout* concern. for example, // if a split is closed (and we had split), the next active // session after the close would be the one next to it // *in the view*, not necessarily the model datastructure if (next.sessions && next.sessions.length) { if (!this.props.activeSession && next.sessions.length) { this.props.onActive(next.sessions[0].uid); } else if (this.props.sessions.length !== next.sessions.length) { if (next.sessions.length > this.props.sessions.length) { // if we are adding, we focused on the new one this.props.onActive(last(next.sessions).uid); return; } const newUids = uids(next.sessions); const curActive = this.props.activeSession; // if we closed an item that wasn't focused, nothing changes if (newUids.indexOf(curActive) !== -1) { return; } const oldIndex = uids(this.props.sessions).indexOf(curActive); if (newUids[oldIndex]) { this.props.onActive(newUids[oldIndex]); } else { this.props.onActive(last(next.sessions).uid); } } } else { this.props.onActive(null); } } shouldComponentUpdate(nextProps) { for (const i in nextProps) { if (i === 'write') { continue; } if (this.props[i] !== nextProps[i]) { return true; } } for (const i in this.props) { if (i === 'write') { continue; } if (this.props[i] !== nextProps[i]) { return true; } } return false; } onRef(uid, term) { if (term) { this.terms[uid] = term; } else { delete this.terms[uid]; } } getTermByUid(uid) { return this.terms[uid]; } getActiveTerm() { return this.getTermByUid(this.props.activeSession); } getLastTermIndex() { return this.props.sessions.length - 1; } bind(fn, thisObj, uid) { if (!this.bound.has(fn)) { this.bound.set(fn, {}); } const map = this.bound.get(fn); if (!map[uid]) { map[uid] = fn.bind(thisObj, uid); } return map[uid]; } getTermProps(uid) { return getTermProps(uid, this.props); } onTerminal(uid, term) { this.terms[uid] = term; } componentWillUnmount() { this.props.ref_(null); } template(css) { return (