import React from 'react'; import Term_ from './term'; import Component from '../component'; import { last } from '../utils/array'; import { decorate, getTermProps } from '../utils/plugins'; 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)) { 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 ('write' === i) continue; if (this.props[i] !== nextProps[i]) { return true; } } for (const i in this.props) { if ('write' === i) 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