// there's relay now
  private void attachToBufferOrClose() {
    if (DEBUG_LIFECYCLE) logger.warn("{} attachToBufferOrClose()", fullName);
    relay.addRelayConnectionHandler(this); // connect/disconnect watcher

    buffer = relay.getBufferByFullName(fullName);
    if (buffer == null) {
      // no buffer? it might happen if:
      //  * the buffer was closed in weechat. if so, close here as well
      //    (post so that closing doesn't get executed on current loop to avoid issues)
      //  * we are not yet connected, e.g., after service shutdown. if so,
      //    wait for onBuffersListed event
      if (relay.isConnection(RelayService.BUFFERS_LISTED)) onBufferClosed();
      return;
    }
    shortName = buffer.shortName;
    buffer.setBufferEye(
        this); // buffer watcher TODO: java.lang.NullPointerException if run in thread ?!?!

    linesAdapter = new ChatLinesAdapter(activity, buffer, uiLines);
    linesAdapter.setFont(prefs.getString(PREF_BUFFER_FONT, PREF_BUFFER_FONT_D));
    linesAdapter.readLinesFromBuffer();

    activity.runOnUiThread(
        new Runnable() {
          @Override
          public void run() {
            activity.updateCutePagerTitleStrip();
            uiLines.setAdapter(linesAdapter);
          }
        });
    maybeChangeVisibilityState();
  }
 // this method is using the following:
 // lastVisibleLine      last line that exists in the buffer. NOTE: "visible" here means line is
 // not filtered in weechat
 // readMarkerLine       used for display. it is:
 //     * saved on app shutdown and restored on start
 //     * altered if a buffer has been read in weechat (see BufferList.saveLastReadLine)
 //     * set to the last displayed line when user navigates away from a buffer
 //     * shifted from invisible line to last visible line if buffer is filtered
 private void maybeMoveReadMarker() {
   if (DEBUG_VISIBILITY) logger.debug("maybeMoveReadMarker()");
   if (buffer != null && buffer.readMarkerLine != buffer.lastVisibleLine) {
     buffer.readMarkerLine = buffer.lastVisibleLine;
     linesAdapter.needMoveLastReadMarker = true;
     onLinesChanged();
   }
 }
 // this method is using the following:
 // lastVisibleLine      last line that exists in the buffer. NOTE: "visible" here means line is
 // not filtered in weechat
 // readMarkerLine       used for display. it is:
 //     * saved on app shutdown and restored on start
 //     * altered if a buffer has been read in weechat (see BufferList.saveLastReadLine)
 //     * set to the last displayed line when user navigates away from a buffer
 //     * shifted from invisible line to last visible line if buffer is filtered
 private void maybeMoveReadMarker() {
   if (DEBUG_VISIBILITY) logger.warn("{} maybeMoveReadMarker({})", shortName);
   if (buffer != null && buffer.readMarkerLine != buffer.lastVisibleLine) {
     buffer.readMarkerLine = buffer.lastVisibleLine;
     linesAdapter.needMoveLastReadMarker = true;
     onLinesChanged();
   }
 }
  private void attachToBuffer() {
    logger.debug("attachToBuffer()");

    buffer.setBufferEye(this);

    linesAdapter = new ChatLinesAdapter(activity, buffer, uiLines);
    linesAdapter.setFont(P.bufferFont);
    linesAdapter.readLinesFromBuffer();

    activity.runOnUiThread(
        new Runnable() {
          @Override
          public void run() {
            activity.updateCutePagerTitleStrip();
            uiLines.setAdapter(linesAdapter);
            maybeChangeHeader();
          }
        });
    maybeChangeVisibilityState();
  }
 @Override
 public void onPropertiesChanged() {
   linesAdapter.onPropertiesChanged();
 }
 @Override
 public void onLinesListed() {
   linesAdapter.onLinesChanged();
   maybeChangeHeader();
   scrollToHotLineIfNeeded();
 }
 @Override
 public void onLinesChanged() {
   linesAdapter.onLinesChanged();
   maybeChangeHeader();
 }
 @Override
 public void onLinesChanged() {
   linesAdapter.onLinesChanged();
 }