<commit_before><!DOCTYPE html>
<html>
<head>
<!-- Theme specific CSS files are loaded later by the ThemeManager -->
<link id="base_stylesheet" rel="stylesheet" type="text/css" href="css/base.css" />
<link rel="stylesheet" type="text/css" href="css/action_menu.css" />
<link rel="stylesheet" type="text/css" href="css/simple_select.css" />
<link rel="stylesheet" type="text/css" href="css/tipsy.css" />
<link rel="stylesheet" type="text/css" href="css/jquery.contextMenu.css" />
<title>Chromed Bird</title>
<script>
var MAX_TWEET_SIZE = 140;
var Persistence = chrome.extension.getBackgroundPage().Persistence;
var urlExpander = chrome.extension.getBackgroundPage().urlExpander;
var tweetManager = chrome.extension.getBackgroundPage().TweetManager.instance;
var twitterBackend = tweetManager.twitterBackend;
var OptionsBackend = chrome.extension.getBackgroundPage().OptionsBackend;
var TimelineTemplate = chrome.extension.getBackgroundPage().TimelineTemplate;
var ImageService = chrome.extension.getBackgroundPage().ImageService;
var UploadManager = chrome.extension.getBackgroundPage().UploadManager;

chrome.i18n.getMessage = chrome.extension.getBackgroundPage().chrome.i18n.getMessage;

var microbloggingService = OptionsBackend.get('microblogging_service');
var TwitterLib;
if(microbloggingService == 'twitter') {
  TwitterLib = {
    URLS: {
      BASE: 'http://twitter.com/',
      SEARCH: 'http://twitter.com/search?q='
    }
  };
} else if(microbloggingService == 'identica') {
  TwitterLib = {
    URLS: {
      BASE: 'http://identi.ca/',
      SEARCH: 'http://identi.ca/search/notice?q='
    }
  };
}

if(!twitterBackend.authenticated() && !twitterBackend.tokenRequested()) {
  twitterBackend.startAuthentication();
  window.close();
}
</script>

<script type="text/javascript" src="lib/3rdparty/jquery.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery-ui-custom.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery.autocomplete.mod.js"></script>
<script type='text/javascript' src='lib/3rdparty/jquery.tipsy.js'></script>
<script type="text/javascript" src="lib/3rdparty/jquery.contextMenu.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery.insertatcaret.min.js"></script>

<!--script type="text/javascript" src="lib/debug.js"></script-->
<script type="text/javascript" src="lib/any_click.js"></script>
<script type="text/javascript" src="lib/shortener_lib.js"></script>
<script type="text/javascript" src="lib/simple_select.js"></script>
<script type="text/javascript" src="lib/tweet_transforms.js"></script>
<script type="text/javascript" src="lib/action_menu.js"></script>
<script type="text/javascript" src="lib/tweets_assembler.js"></script>
<script>
$.ajaxSetup({
  timeout: OptionsBackend.get('request_timeout')
});

var url_shortener = OptionsBackend.get('url_shortener');
var shortener_acct = OptionsBackend.get('shortener_acct');
var shortener_login = null;
var shortener_key = null;
if(shortener_acct) {
  shortener_login = OptionsBackend.get('shortener_login');
  shortener_key = OptionsBackend.get('shortener_key');
}

if (url_shortener == 'yourls'){
  shortener_key = OptionsBackend.get('yourls_key');
}

var reply_all = OptionsBackend.get('reply_all');
var shortener = new Shortener(url_shortener, shortener_acct, 
			      shortener_login, shortener_key, 
			      OptionsBackend.get('shortener_service_url'));

$.extend($.ui.tabs.prototype, {
  refreshPositions: function() {
    return this._tabify();
  }
});

$.fn.hoverFor = function(time, mainCallback, startingCallback, abortCallback) {
  return this.each(function(){
    var _this = this, timeoutHandle, triggerFired = false;
    $(this).hover(
      function() {
        if(triggerFired)
          return;
        if(startingCallback)
          startingCallback.call(_this);
        timeoutHandle = setTimeout(function() {
          triggerFired = true;
          mainCallback.call(_this);
          timeoutHandle = null;
        }, time);
      },
      function() {
        if(triggerFired)
          return;
        if(timeoutHandle) {
          if(abortCallback)
            abortCallback.call(_this);
          clearTimeout(timeoutHandle);
          timeoutHandle = null;
        }
      }
    );
 });
};

var OAuth = {
  registerPin: function() {
    var pinNumber = $("input[name='pin']").val();
    $("#loading_oauth").show();
    twitterBackend.oauthLib.getAccessToken(pinNumber, function(result) {
      $("#loading_oauth").hide();
      $("#enter_pin").hide();
      if(result) {
        initializeWorkspace();
      } else {
        var errMsg = twitterBackend.oauthLib.error;
        $("#error_pin").show().html(chrome.i18n.getMessage("oAuthError", errMsg));
      }
    });
  },
  requestNewToken: function() {
    twitterBackend.startAuthentication();
    window.close();
  }
};

var Paginator = {
  needsMore: false,
  firstPage: function(shouldScrollTop) {
    this.needsMore = false;
    if(shouldScrollTop) {
      $("#timeline-" + tweetManager.currentTimelineId + ' .inner_timeline').scrollTop(0);
      tweetManager.getCurrentTimeline().currentScroll = 0;
    }
  },
  nextPage: function() {
    this.needsMore = true;
    loadTimeline();
  }
};

var ThemeManager = {
  init: function () {
    $("link.theme").remove();
    var theme = OptionsBackend.get('theme');
    $(theme.split(",")).each(function(i, p) {
      $("<link rel='stylesheet' type='text/css' class='theme' href='" + p + "'>").appendTo(document.head);
    });
    var baseStyle = $("#base_stylesheet")[0];
    if(baseStyle.sheet && baseStyle.sheet.cssRules) {
      var baseRules = baseStyle.sheet.cssRules;
      var fontFamily = OptionsBackend.get('font_family');
      var fontSize = OptionsBackend.get('font_size');
      for(var i = 0, len = baseRules.length; i < len; ++i) {
        var rule = baseRules[i];
        if(rule.selectorText == ".tweet") {
          rule.style.fontFamily = fontFamily;
          rule.style.fontSize = fontSize;
          break;
        }
      }
    }

    ThemeManager.isPopup = location.search == '?popup';
    ThemeManager.isDetached = location.search == '?detached';

    if(!ThemeManager.isPopup) {
      $('<base target="_blank">').appendTo(document.head);
    }

    var persistedPosition = Persistence.windowPosition();
    ThemeManager.detachedPos = persistedPosition.val();
    if(!ThemeManager.detachedPos) {
      // Setting default values
      ThemeManager.detachedPos = {
        left: 100,
        top: 100,
        height: null,
        width: null
      };
      persistedPosition.save(ThemeManager.detachedPos);
    }
    if(ThemeManager.isDetached) {
      $("#detach_img").hide();
      // Listening to resize and move events
      $(window).resize(function() {
        ThemeManager.detachedPos.height = window.innerHeight;
        ThemeManager.detachedPos.width = window.innerWidth;
        persistedPosition.save(ThemeManager.detachedPos);
      });
      setInterval(function() {
        if(ThemeManager.detachedPos.left != window.screenLeft || ThemeManager.detachedPos.top != window.screenTop) {
          ThemeManager.detachedPos.left = window.screenLeft;
          ThemeManager.detachedPos.top = window.screenTop;
          persistedPosition.save(ThemeManager.detachedPos);
        }
      }, 1000);
    }
  },

  setPopupSize: function(width, height, autoFitWidth) {
    if(!ThemeManager.isPopup) {
      return;
    }

    /* HACK: Magic numbers */
    var hackBordersWidth = 14;
    var hackTabsAdditionalWidth = 40;
    var hackHeaderHeight = 75;
    var hackMinValidHeight = 400;

    width = width || 490;
    height = height || 400;
    var minWidth = 450;
    var maxWidth = 800 - hackBordersWidth;
    if(width > maxWidth) {
      width = maxWidth;
    }
    if(width < minWidth) {
      width = minWidth;
    }
    if(autoFitWidth) {
      setTimeout(function() {
        var tabsBarWidth = 0;
        $("li.timeline_tab").each(function() {
          tabsBarWidth += $(this).width();
        });
        tabsBarWidth += hackTabsAdditionalWidth;
        if(tabsBarWidth > width) {
          ThemeManager.setPopupSize(tabsBarWidth, height);
        }
      }, 300);
    }

    $(".timeline").width(width + 'px');
    $(".inner_timeline,.timeline").height(height + 'px');

    setTimeout(function() {
      if(window.innerHeight < hackMinValidHeight) { return; }
      if(window.innerHeight < ($(".timeline").height() + hackHeaderHeight)) {
        var height = window.innerHeight - hackHeaderHeight;
        ThemeManager.setPopupSize(width, height, autoFitWidth);
      }
    }, 100);
  },

  popupSizeData: Persistence.popupSize(),

  initWindowResizing: function() {
    ThemeManager.handleWindowResizing();
    if(!ThemeManager.isPopup) {
      var resizeFunc = function() {
        var timelineHeight = window.innerHeight - 79;
        $('.inner_timeline,.timeline').css('maxHeight', timelineHeight + 'px');
      };
      $(window).resize(resizeFunc);
      resizeFunc();
      return;
    }
    $(".timeline").resizable({
      handles: 'e, s, se',
      minWidth: 450,
      resize: function(e, ui) {
        var $this = $(this);
        ThemeManager.setPopupSize($this.width(), $this.height());
      },
      stop: function(e, ui) {
        var $this = $(this);
        ThemeManager.popupSizeData.save($this.width() + 'x' + $this.height());
      }
    });
    $(".ui-resizable-handle").attr('title', chrome.i18n.getMessage("resetSize"));
    $(".ui-resizable-handle").dblclick(function(e) {
      ThemeManager.popupSizeData.remove();
      ThemeManager.setPopupSize(null, null, true);
    });
  },

  handleWindowResizing: function() {
    var sizeArray = ThemeManager.popupSizeData.val();
    if(sizeArray) {
      sizeArray = sizeArray.split('x');
      ThemeManager.setPopupSize(sizeArray[0], sizeArray[1], true);
    } else {
      ThemeManager.setPopupSize(null, null, true);
    }
  },

  sortableEl: null,
  uiTabs: null,
  handleSortableTabs: function() {
    this.uiTabs = $("#tabs");
    this.sortableEl = this.uiTabs.find(".ui-tabs-nav");
    this.sortableEl.sortable({
      stop: function(event, ui) {
        ThemeManager.updateTabsOrder();
      }
    });
  },

  reOrderPanels: function(sortedTimelines) {
    var panels = $("#tabs .ui-tabs-panel");
    for(var i = 0, len = sortedTimelines.length; i < len; ++i) {
      var correctTimeline = sortedTimelines[i];
      var correctPanel = $("#timeline-" + correctTimeline);
      var positionPanel = panels.eq(i);
      if(correctPanel[0].id != positionPanel[0].id) {
        var currentScroll = $('.inner_timeline', correctPanel).scrollTop();
        correctPanel.detach();
        positionPanel.before(correctPanel);
        $('.inner_timeline', correctPanel).scrollTop(currentScroll);
        panels = $("#tabs .ui-tabs-panel");
      }
    }
  },

  updateTabsOrder: function() {
    var sortedTabs = this.sortableEl.sortable('toArray');
    var sortedTimelines = [];
    for(var i = 0; i < sortedTabs.length; ++i) {
      sortedTimelines[i] = sortedTabs[i].split('-')[1];
    }
    tweetManager.setTimelineOrder(sortedTimelines);
    this.reOrderPanels(sortedTimelines);
    this.uiTabs.tabs('refreshPositions');
  }
};

var Composer = {
  replyId: null,
  replyUser: null,
  rtId: null,
  destroyId: null,
  favoriteId: null,
  destroyTimelineId: null,

  init: function() {
    if(tweetManager.composerData.isComposing) {
      Composer.initMessage(tweetManager.composerData.saveMessage, tweetManager.composerData.replyId,
          tweetManager.composerData.replyUser, false);
    }
    Composer.textareaChanged();
  },

  initMessage: function(message, replyId, replyUser, shouldAnimate) {
    Composer.replyId = replyId;
    Composer.replyUser = replyUser;
    $("#compose_tweet_area textarea").val(message || '');
    Composer.showComposeArea(true, !shouldAnimate);
    Composer.textareaChanged();
  },

  share: function (node) {
    Composer.showComposeArea(true);
    var el = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var msg = $(".text", node).text();
    el.val("RT @" + user + ": " + msg);
    Composer.textareaChanged();
  },

  confirmDestroy: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;

    tweetManager.destroy(function(success, data, status) {
      $("#loading").hide();
      var notFound = status && status.match(/Not Found/);
      if(success || notFound) {
        $(".tweet[tweetid='" + _this.destroyId + "']").parents('.tweet_space').first().hide('blind', { direction: "vertical" });
        var currentCount = tweetManager.getCurrentTimeline().getTweetsCache().length;
        if(currentCount < OptionsBackend.get('tweets_per_page')) {
          Paginator.nextPage();
        }
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_deletingTweet", status), 'Composer.confirmDestroy');
      }
    }, this.destroyTimelineId, this.destroyId);
  },

  denyDestroy: function() {
    $(".rt_confirm").hide();
  },

  destroy: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm.destroy", node).show();
    this.destroyId = $(node).attr('tweetid');
    this.destroyTimelineId = $(node).attr('timelineid');
  },

  confirmRT: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;
    tweetManager.postRetweet(function(success, data, status) {
      $("#loading").hide();
      if(success) {
        loadTimeline(true, "home");
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_retweeting", status), 'Composer.confirmRT');
      }
    }, _this.rtId);
  },

  denyRT: function() {
    $(".rt_confirm").hide();
  },

  retweet: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm", node).show();
    this.rtId = $(node).attr('tweetid');
  },

  favorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.favorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_markFavorite", status), 'Composer.favorite');
      }
    }, this.favoriteId);
  },

  unFavorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.unFavorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_unmarkFavorite", status), 'Composer.unFavorite');
      }
    }, this.favoriteId);
  },

  addUser: function (user, replies) {
    var textArea = $("#compose_tweet_area textarea");
    var currentVal = textArea.val();
    replies =  replies || [];
    if(currentVal.length > 0 && currentVal[currentVal.length - 1] != ' ') {
      currentVal += ' ';
    }
    currentVal += '@' + user + ' ' + replies.join('');
    textArea.val(currentVal);
  },

  reply: function (node) {
    Composer.showComposeArea(true);

    var textArea = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var timelineId = $(node).attr('timelineid');

    if(timelineId == TimelineTemplate.RECEIVED_DMS || timelineId == TimelineTemplate.SENT_DMS) {
      textArea.val("d " + user + " ");
      Composer.textareaChanged();
      return;
    }

    var currentVal = textArea.val();
    var replies = [];
    var ownName = tweetManager.twitterBackend.username();
    if (reply_all) {
      $(".text a", node).each(function(){
        var t = $(this).text();
        if (t !== ownName && (/^[A-Z0-9_-]{1,15}$/i).test(t)) {
          replies.push('@'+t+' ');
        }
      });
    }

    if(Composer.replyId && currentVal.indexOf(Composer.replyUser) != -1) {
      this.addUser(user, replies);
      Composer.textareaChanged();
      return;
    }

    this.addUser(user, replies);
    tweetManager.composerData.replyId = Composer.replyId = $(node).attr('tweetid');
    tweetManager.composerData.replyUser = Composer.replyUser = user;

    Composer.textareaChanged();
  },

  showComposeArea: function (showOnly, noAnimation) {
    var composeArea = $("#compose_tweet_area");
    var textarea = $("textarea", composeArea);
    var visible = composeArea.is(':visible');

    if(!visible) {
      if(noAnimation) {
        composeArea.show();
      } else {
        composeArea.show('blind', { direction: "vertical" }, 'normal', function() {
          textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
          textarea.focus();
        });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_up.gif');
      tweetManager.composerData.isComposing = true;
      tweetManager.composerData.replyId = Composer.replyId;
      tweetManager.composerData.replyUser = Composer.replyUser;
    } else if(!showOnly) {
      if(noAnimation) {
        composeArea.hide();
      } else {
        composeArea.hide('blind', { direction: "vertical" });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_down.gif');
      tweetManager.composerData.saveMessage = '';
      tweetManager.composerData.isComposing = false;
      tweetManager.composerData.replyId = null;
      tweetManager.composerData.replyUser = null;
      Shortener.closeArea();
    }

    if((visible && showOnly) || (!visible && noAnimation)) {
      textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
      textarea.focus();
    }
  },

  textareaChanged: function (e) {
    var el = $("#compose_tweet_area textarea");
    tweetManager.composerData.saveMessage = el.val();
    var availableChars = MAX_TWEET_SIZE - el.val().length;
    var charsLeftEl = $("#compose_tweet_area .chars_left");
    charsLeftEl.text(availableChars);
    if(availableChars < 0 || availableChars == MAX_TWEET_SIZE) {
      if(availableChars < 0) {
        charsLeftEl.css('color', 'red');
      }
      $("#compose_tweet_area input[type='button']").attr("disabled", "disabled");
    } else {
      charsLeftEl.css('color', 'black');
      $("#compose_tweet_area input[type='button']").removeAttr("disabled");
      if(e && e.ctrlKey && e.which == 13) { // Ctrl + Enter
        this.sendTweet();
      }
    }
  },

  sendTweet: function () {
    var textarea = $("#compose_tweet_area textarea");
    tweetManager.enqueueTweet(textarea.val(), Composer.replyId, Composer.replyUser);

    textarea.val("");
    Composer.replyId = null;
    Composer.textareaChanged();
    Composer.showComposeArea();
    Shortener.clear();
  },

  refreshNew: function() {
    // FIXME: #loading shouldn't be used for that.
    if($("#loading").is(":visible")) {
      return;
    }
    loadTimeline(true);
  },

  isVisible: function() {
    var composeArea = $("#compose_tweet_area");
    var textarea = $("textarea", composeArea);
    var visible = composeArea.is(':visible');
    return visible && textarea.val().length > 0;
  },

  addText: function(value) {
    var textarea = $("#compose_tweet_area textarea");
    var tmpText = textarea.val();
    if(tmpText.length > 0) {
      if((textarea[0].selectionStart > 0) &&
        (tmpText[textarea[0].selectionStart-1] != ' ')) {
        value = ' ' + value;
      }
      if((textarea[0].selectionEnd < tmpText.length) &&
         (tmpText[textarea[0].selectionEnd+1] != ' ')) {
         value += ' ';
      }
    }
    textarea.insertAtCaret(value);
    Composer.textareaChanged();
  }
};

var WorkList = {
  /* Not really a work list yet, but I intend in making it into one
     and hopefully stop this #loading madness.
   */
  init: function() {
    if(tweetManager.sendQueue.queueSize() !== 0) {
      $("#queue_loading").show();
    }
    tweetManager.sendQueue.onQueueEmpty(function(lastSent) {
      if(!window) {
        return;
      }
      WorkList.sendQueueEmpty(lastSent);
    });
    tweetManager.sendQueue.onTweetEnqueued(function() {
      if(!window) {
        return;
      }
      WorkList.tweetEnqueued();
    });
    tweetManager.sendQueue.onSendFailed(function() {
      if(!window) {
        return;
      }
      WorkList.sendFailed();
    });
    // Just checking
    WorkList.sendFailed();

    $("#queue_loading").tipsy({
      title: function() {
        var html = '<div class="worklist_container"><span class="title">' +
                   chrome.i18n.getMessage("queued_messages") +
                   '</span>';
        html += '<ul class="worklist">';
        var queueItems = tweetManager.sendQueue.queue;
        for(var i = 0, len = queueItems.length; i < len; ++i) {
          var queueItem = queueItems[i];
          var message = queueItem.message;
          if(i === 0 && message.length > 15) {
            message = message.substring(0, 13) + '...';
          } else if(message.length > 50) {
            message = message.substring(0, 48) + '...';
          }
          html += '<li>';
          html += message;
          if(i === 0) {
            var timeDiff = ((new Date()).getTime() - queueItem.createdAt.getTime()) / 1000;
            var timeDiffDesc;
            if(timeDiff < 60) {
              timeDiffDesc = parseInt(timeDiff, 10) + 's';
            } else {
              timeDiffDesc = parseInt(timeDiff / 60, 10) + 'm';
            }
            if(queueItem.retryCount == 1) {
              html += '<span class="title"> ' +
                      chrome.i18n.getMessage("queue_trying", timeDiffDesc) +
                      '</span>';
            } else {
              html += '<span class="title"> ' +
                      chrome.i18n.getMessage("queue_retried", [queueItem.retryCount, timeDiffDesc, queueItem.lastStatus]) +
                      '</span>';
            }
            if(queueItem.shouldCancel) {
              html += ' <span class="title" style="color: #d00;">' +
                      chrome.i18n.getMessage("canceling") +
                      '</span>';
            } else {
              html += '<img src="img/cancel.png" onclick="WorkList.cancelMessage();" title="' +
                      chrome.i18n.getMessage("cancelTweet") + '">';
            }
          }
          html += '</li>';
        }
        html += '</ul></div>';
        return html;
      },
      html: true,
      opacity: 0.9,
      delayOut: 500,
      persistOnHover: true,
      maxWidth: 400,
      gravity: 'tasks'
    });
  },

  cancelMessage: function() {
    var queueItems = tweetManager.sendQueue.queue;
    if(queueItems.length > 0) {
      queueItems[0].cancel();
    }
    $("#queue_loading").tipsy({refresh: true});
  },

  sendQueueEmpty: function(lastSent) {
    $("#queue_loading").hide();
    var updateTimelineId = TimelineTemplate.HOME;
    if(lastSent && lastSent.message.indexOf('d ') === 0) {
      updateTimelineId = TimelineTemplate.SENT_DMS;
    }
    loadTimeline(true, updateTimelineId);
  },

  tweetEnqueued: function() {
    $("#queue_loading").show();
  },

  sendFailed: function() {
    var abortedQueue = tweetManager.sendQueue.abortedStatus();
    if(!abortedQueue || abortedQueue.length === 0) {
      return;
    }
    // If we're here that's because something went wrong
    if(!Composer.isVisible()) {
      // For now let's just show the first enqueued message
      var topMessage = abortedQueue[0];
      Composer.initMessage(topMessage.message, topMessage.replyId, topMessage.replyUser, true);
    }
    Renderer.showError(chrome.i18n.getMessage("tweet_send_error"));
  }
};

var Shortener = {
  SHORTENER_IDLE_STR: chrome.i18n.getMessage("shortenerIdleString"),

  init: function() {
    var savedUrl = tweetManager.composerData.urlShortener;
    if(savedUrl !== '') {
      $("#shortener_area input").val(savedUrl);
    }
    this.blur();
  },

  clear: function() {
    $("#shortener_area input").val('');
    this.blur();
  },

  closeArea: function() {
    tweetManager.composerData.urlShortener = '';
  },

  focus: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if(val == this.SHORTENER_IDLE_STR) {
      shortener.val('');
      shortener.removeAttr('style');
    }
  },

  showButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(!shortenerButton.is(":visible"))
      shortenerButton.show('blind', { direction: "vertical" }, 'fast');
  },

  hideButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(shortenerButton.is(":visible"))
      shortenerButton.hide('blind', { direction: "vertical" }, 'fast');
  },

  blur: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if($.trim(val) === '' || val == this.SHORTENER_IDLE_STR) {
      shortener.val(this.SHORTENER_IDLE_STR);
      shortener.attr('style', 'color: #aaa;');
      this.hideButton();
    } else {
      this.showButton();
    }
  },

  changed: function(e) {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    tweetManager.composerData.urlShortener = val;
    if($.trim(val) !== '') {
      if(e.which == 13) { //Enter key
        this.shortenIt();
      } else {
        this.showButton();
      }
    } else {
      this.hideButton();
    }
  },

  shortenCurrentPage: function() {
    var _this = this;
    chrome.tabs.getSelected(null, function(tab) {
      var shortenerInput = $("#shortener_area input");
      shortenerInput.val(tab.url);
      _this.shortenIt({title: tab.title});
    });
  },

  shortenIt: function(context) {
    var shortenerInput = $("#shortener_area input");
    var longUrl = shortenerInput.val();
    this.shortenPage(longUrl, context);
  },

  shortenPage: function(longUrl, context) {
    $("#loading").show();
    var shortenerInput = $("#shortener_area input");
    shortenerInput.attr('disabled', 'disabled');
    this.hideButton();
    var _this = this;
    shortener.shorten(longUrl, function(success, shortUrl) {
      $("#loading").hide();
      shortenerInput.removeAttr('disabled');
      _this.closeArea();
      _this.clear();
      var textarea = $("#compose_tweet_area textarea");
      if(success && shortUrl) {
        if(context && context.title && OptionsBackend.get('share_include_title')) {
          shortUrl = context.title + ' - ' + shortUrl;
        }
        Composer.addText(shortUrl);
      } else if(!success) {
        Renderer.showError(shortUrl);
      }
      Composer.showComposeArea(true);
    });
  }
};

$.extend(Renderer, {
  assemblyTweets: function (tweets, timelineId) {
    var destination = $("#timeline-" + timelineId + " .inner_timeline");
    if(destination.length === 0)
      return;

    var useColors = true;
    if(OptionsBackend.get('tweets_color_only_unified')) {
      if(timelineId != TimelineTemplate.UNIFIED) {
        useColors = false;
      }
    }

    var nameAttribute = OptionsBackend.get('name_attribute');
    var destinationDom = destination[0];
    destinationDom.innerHTML = "";
    for(var i = 0; i < tweets.length; ++i) {
      destinationDom.appendChild(Renderer.renderTweet(tweets[i], useColors, nameAttribute));
    }

    $(".tweet").live('mouseover mouseout', function(event) {
      if(event.type == 'mouseover') {
        $(".new_actions img:not(.starred)", this).show();
      } else {
        $(".new_actions img:not(.starred)", this).hide();
      }
    });

    var hoverFunc = function(event) {
      var $this = $(this);
      var old_src = $this.attr('src');
      var new_src = old_src;<commit_msg>Fixing weird flickering when hovering tweets.<commit_after><!DOCTYPE html>
<html>
<head>
<!-- Theme specific CSS files are loaded later by the ThemeManager -->
<link id="base_stylesheet" rel="stylesheet" type="text/css" href="css/base.css" />
<link rel="stylesheet" type="text/css" href="css/action_menu.css" />
<link rel="stylesheet" type="text/css" href="css/simple_select.css" />
<link rel="stylesheet" type="text/css" href="css/tipsy.css" />
<link rel="stylesheet" type="text/css" href="css/jquery.contextMenu.css" />
<title>Chromed Bird</title>
<script>
var MAX_TWEET_SIZE = 140;
var Persistence = chrome.extension.getBackgroundPage().Persistence;
var urlExpander = chrome.extension.getBackgroundPage().urlExpander;
var tweetManager = chrome.extension.getBackgroundPage().TweetManager.instance;
var twitterBackend = tweetManager.twitterBackend;
var OptionsBackend = chrome.extension.getBackgroundPage().OptionsBackend;
var TimelineTemplate = chrome.extension.getBackgroundPage().TimelineTemplate;
var ImageService = chrome.extension.getBackgroundPage().ImageService;
var UploadManager = chrome.extension.getBackgroundPage().UploadManager;

chrome.i18n.getMessage = chrome.extension.getBackgroundPage().chrome.i18n.getMessage;

var microbloggingService = OptionsBackend.get('microblogging_service');
var TwitterLib;
if(microbloggingService == 'twitter') {
  TwitterLib = {
    URLS: {
      BASE: 'http://twitter.com/',
      SEARCH: 'http://twitter.com/search?q='
    }
  };
} else if(microbloggingService == 'identica') {
  TwitterLib = {
    URLS: {
      BASE: 'http://identi.ca/',
      SEARCH: 'http://identi.ca/search/notice?q='
    }
  };
}

if(!twitterBackend.authenticated() && !twitterBackend.tokenRequested()) {
  twitterBackend.startAuthentication();
  window.close();
}
</script>

<script type="text/javascript" src="lib/3rdparty/jquery.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery-ui-custom.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery.autocomplete.mod.js"></script>
<script type='text/javascript' src='lib/3rdparty/jquery.tipsy.js'></script>
<script type="text/javascript" src="lib/3rdparty/jquery.contextMenu.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery.insertatcaret.min.js"></script>

<!--script type="text/javascript" src="lib/debug.js"></script-->
<script type="text/javascript" src="lib/any_click.js"></script>
<script type="text/javascript" src="lib/shortener_lib.js"></script>
<script type="text/javascript" src="lib/simple_select.js"></script>
<script type="text/javascript" src="lib/tweet_transforms.js"></script>
<script type="text/javascript" src="lib/action_menu.js"></script>
<script type="text/javascript" src="lib/tweets_assembler.js"></script>
<script>
$.ajaxSetup({
  timeout: OptionsBackend.get('request_timeout')
});

var url_shortener = OptionsBackend.get('url_shortener');
var shortener_acct = OptionsBackend.get('shortener_acct');
var shortener_login = null;
var shortener_key = null;
if(shortener_acct) {
  shortener_login = OptionsBackend.get('shortener_login');
  shortener_key = OptionsBackend.get('shortener_key');
}

if (url_shortener == 'yourls'){
  shortener_key = OptionsBackend.get('yourls_key');
}

var reply_all = OptionsBackend.get('reply_all');
var shortener = new Shortener(url_shortener, shortener_acct, 
			      shortener_login, shortener_key, 
			      OptionsBackend.get('shortener_service_url'));

$.extend($.ui.tabs.prototype, {
  refreshPositions: function() {
    return this._tabify();
  }
});

$.fn.hoverFor = function(time, mainCallback, startingCallback, abortCallback) {
  return this.each(function(){
    var _this = this, timeoutHandle, triggerFired = false;
    $(this).hover(
      function() {
        if(triggerFired)
          return;
        if(startingCallback)
          startingCallback.call(_this);
        timeoutHandle = setTimeout(function() {
          triggerFired = true;
          mainCallback.call(_this);
          timeoutHandle = null;
        }, time);
      },
      function() {
        if(triggerFired)
          return;
        if(timeoutHandle) {
          if(abortCallback)
            abortCallback.call(_this);
          clearTimeout(timeoutHandle);
          timeoutHandle = null;
        }
      }
    );
 });
};

var OAuth = {
  registerPin: function() {
    var pinNumber = $("input[name='pin']").val();
    $("#loading_oauth").show();
    twitterBackend.oauthLib.getAccessToken(pinNumber, function(result) {
      $("#loading_oauth").hide();
      $("#enter_pin").hide();
      if(result) {
        initializeWorkspace();
      } else {
        var errMsg = twitterBackend.oauthLib.error;
        $("#error_pin").show().html(chrome.i18n.getMessage("oAuthError", errMsg));
      }
    });
  },
  requestNewToken: function() {
    twitterBackend.startAuthentication();
    window.close();
  }
};

var Paginator = {
  needsMore: false,
  firstPage: function(shouldScrollTop) {
    this.needsMore = false;
    if(shouldScrollTop) {
      $("#timeline-" + tweetManager.currentTimelineId + ' .inner_timeline').scrollTop(0);
      tweetManager.getCurrentTimeline().currentScroll = 0;
    }
  },
  nextPage: function() {
    this.needsMore = true;
    loadTimeline();
  }
};

var ThemeManager = {
  init: function () {
    $("link.theme").remove();
    var theme = OptionsBackend.get('theme');
    $(theme.split(",")).each(function(i, p) {
      $("<link rel='stylesheet' type='text/css' class='theme' href='" + p + "'>").appendTo(document.head);
    });
    var baseStyle = $("#base_stylesheet")[0];
    if(baseStyle.sheet && baseStyle.sheet.cssRules) {
      var baseRules = baseStyle.sheet.cssRules;
      var fontFamily = OptionsBackend.get('font_family');
      var fontSize = OptionsBackend.get('font_size');
      for(var i = 0, len = baseRules.length; i < len; ++i) {
        var rule = baseRules[i];
        if(rule.selectorText == ".tweet") {
          rule.style.fontFamily = fontFamily;
          rule.style.fontSize = fontSize;
          break;
        }
      }
    }

    ThemeManager.isPopup = location.search == '?popup';
    ThemeManager.isDetached = location.search == '?detached';

    if(!ThemeManager.isPopup) {
      $('<base target="_blank">').appendTo(document.head);
    }

    var persistedPosition = Persistence.windowPosition();
    ThemeManager.detachedPos = persistedPosition.val();
    if(!ThemeManager.detachedPos) {
      // Setting default values
      ThemeManager.detachedPos = {
        left: 100,
        top: 100,
        height: null,
        width: null
      };
      persistedPosition.save(ThemeManager.detachedPos);
    }
    if(ThemeManager.isDetached) {
      $("#detach_img").hide();
      // Listening to resize and move events
      $(window).resize(function() {
        ThemeManager.detachedPos.height = window.innerHeight;
        ThemeManager.detachedPos.width = window.innerWidth;
        persistedPosition.save(ThemeManager.detachedPos);
      });
      setInterval(function() {
        if(ThemeManager.detachedPos.left != window.screenLeft || ThemeManager.detachedPos.top != window.screenTop) {
          ThemeManager.detachedPos.left = window.screenLeft;
          ThemeManager.detachedPos.top = window.screenTop;
          persistedPosition.save(ThemeManager.detachedPos);
        }
      }, 1000);
    }
  },

  setPopupSize: function(width, height, autoFitWidth) {
    if(!ThemeManager.isPopup) {
      return;
    }

    /* HACK: Magic numbers */
    var hackBordersWidth = 14;
    var hackTabsAdditionalWidth = 40;
    var hackHeaderHeight = 75;
    var hackMinValidHeight = 400;

    width = width || 490;
    height = height || 400;
    var minWidth = 450;
    var maxWidth = 800 - hackBordersWidth;
    if(width > maxWidth) {
      width = maxWidth;
    }
    if(width < minWidth) {
      width = minWidth;
    }
    if(autoFitWidth) {
      setTimeout(function() {
        var tabsBarWidth = 0;
        $("li.timeline_tab").each(function() {
          tabsBarWidth += $(this).width();
        });
        tabsBarWidth += hackTabsAdditionalWidth;
        if(tabsBarWidth > width) {
          ThemeManager.setPopupSize(tabsBarWidth, height);
        }
      }, 300);
    }

    $(".timeline").width(width + 'px');
    $(".inner_timeline,.timeline").height(height + 'px');

    setTimeout(function() {
      if(window.innerHeight < hackMinValidHeight) { return; }
      if(window.innerHeight < ($(".timeline").height() + hackHeaderHeight)) {
        var height = window.innerHeight - hackHeaderHeight;
        ThemeManager.setPopupSize(width, height, autoFitWidth);
      }
    }, 100);
  },

  popupSizeData: Persistence.popupSize(),

  initWindowResizing: function() {
    ThemeManager.handleWindowResizing();
    if(!ThemeManager.isPopup) {
      var resizeFunc = function() {
        var timelineHeight = window.innerHeight - 79;
        $('.inner_timeline,.timeline').css('maxHeight', timelineHeight + 'px');
      };
      $(window).resize(resizeFunc);
      resizeFunc();
      return;
    }
    $(".timeline").resizable({
      handles: 'e, s, se',
      minWidth: 450,
      resize: function(e, ui) {
        var $this = $(this);
        ThemeManager.setPopupSize($this.width(), $this.height());
      },
      stop: function(e, ui) {
        var $this = $(this);
        ThemeManager.popupSizeData.save($this.width() + 'x' + $this.height());
      }
    });
    $(".ui-resizable-handle").attr('title', chrome.i18n.getMessage("resetSize"));
    $(".ui-resizable-handle").dblclick(function(e) {
      ThemeManager.popupSizeData.remove();
      ThemeManager.setPopupSize(null, null, true);
    });
  },

  handleWindowResizing: function() {
    var sizeArray = ThemeManager.popupSizeData.val();
    if(sizeArray) {
      sizeArray = sizeArray.split('x');
      ThemeManager.setPopupSize(sizeArray[0], sizeArray[1], true);
    } else {
      ThemeManager.setPopupSize(null, null, true);
    }
  },

  sortableEl: null,
  uiTabs: null,
  handleSortableTabs: function() {
    this.uiTabs = $("#tabs");
    this.sortableEl = this.uiTabs.find(".ui-tabs-nav");
    this.sortableEl.sortable({
      stop: function(event, ui) {
        ThemeManager.updateTabsOrder();
      }
    });
  },

  reOrderPanels: function(sortedTimelines) {
    var panels = $("#tabs .ui-tabs-panel");
    for(var i = 0, len = sortedTimelines.length; i < len; ++i) {
      var correctTimeline = sortedTimelines[i];
      var correctPanel = $("#timeline-" + correctTimeline);
      var positionPanel = panels.eq(i);
      if(correctPanel[0].id != positionPanel[0].id) {
        var currentScroll = $('.inner_timeline', correctPanel).scrollTop();
        correctPanel.detach();
        positionPanel.before(correctPanel);
        $('.inner_timeline', correctPanel).scrollTop(currentScroll);
        panels = $("#tabs .ui-tabs-panel");
      }
    }
  },

  updateTabsOrder: function() {
    var sortedTabs = this.sortableEl.sortable('toArray');
    var sortedTimelines = [];
    for(var i = 0; i < sortedTabs.length; ++i) {
      sortedTimelines[i] = sortedTabs[i].split('-')[1];
    }
    tweetManager.setTimelineOrder(sortedTimelines);
    this.reOrderPanels(sortedTimelines);
    this.uiTabs.tabs('refreshPositions');
  }
};

var Composer = {
  replyId: null,
  replyUser: null,
  rtId: null,
  destroyId: null,
  favoriteId: null,
  destroyTimelineId: null,

  init: function() {
    if(tweetManager.composerData.isComposing) {
      Composer.initMessage(tweetManager.composerData.saveMessage, tweetManager.composerData.replyId,
          tweetManager.composerData.replyUser, false);
    }
    Composer.textareaChanged();
  },

  initMessage: function(message, replyId, replyUser, shouldAnimate) {
    Composer.replyId = replyId;
    Composer.replyUser = replyUser;
    $("#compose_tweet_area textarea").val(message || '');
    Composer.showComposeArea(true, !shouldAnimate);
    Composer.textareaChanged();
  },

  share: function (node) {
    Composer.showComposeArea(true);
    var el = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var msg = $(".text", node).text();
    el.val("RT @" + user + ": " + msg);
    Composer.textareaChanged();
  },

  confirmDestroy: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;

    tweetManager.destroy(function(success, data, status) {
      $("#loading").hide();
      var notFound = status && status.match(/Not Found/);
      if(success || notFound) {
        $(".tweet[tweetid='" + _this.destroyId + "']").parents('.tweet_space').first().hide('blind', { direction: "vertical" });
        var currentCount = tweetManager.getCurrentTimeline().getTweetsCache().length;
        if(currentCount < OptionsBackend.get('tweets_per_page')) {
          Paginator.nextPage();
        }
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_deletingTweet", status), 'Composer.confirmDestroy');
      }
    }, this.destroyTimelineId, this.destroyId);
  },

  denyDestroy: function() {
    $(".rt_confirm").hide();
  },

  destroy: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm.destroy", node).show();
    this.destroyId = $(node).attr('tweetid');
    this.destroyTimelineId = $(node).attr('timelineid');
  },

  confirmRT: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;
    tweetManager.postRetweet(function(success, data, status) {
      $("#loading").hide();
      if(success) {
        loadTimeline(true, "home");
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_retweeting", status), 'Composer.confirmRT');
      }
    }, _this.rtId);
  },

  denyRT: function() {
    $(".rt_confirm").hide();
  },

  retweet: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm", node).show();
    this.rtId = $(node).attr('tweetid');
  },

  favorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.favorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_markFavorite", status), 'Composer.favorite');
      }
    }, this.favoriteId);
  },

  unFavorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.unFavorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError(chrome.i18n.getMessage("ue_unmarkFavorite", status), 'Composer.unFavorite');
      }
    }, this.favoriteId);
  },

  addUser: function (user, replies) {
    var textArea = $("#compose_tweet_area textarea");
    var currentVal = textArea.val();
    replies =  replies || [];
    if(currentVal.length > 0 && currentVal[currentVal.length - 1] != ' ') {
      currentVal += ' ';
    }
    currentVal += '@' + user + ' ' + replies.join('');
    textArea.val(currentVal);
  },

  reply: function (node) {
    Composer.showComposeArea(true);

    var textArea = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var timelineId = $(node).attr('timelineid');

    if(timelineId == TimelineTemplate.RECEIVED_DMS || timelineId == TimelineTemplate.SENT_DMS) {
      textArea.val("d " + user + " ");
      Composer.textareaChanged();
      return;
    }

    var currentVal = textArea.val();
    var replies = [];
    var ownName = tweetManager.twitterBackend.username();
    if (reply_all) {
      $(".text a", node).each(function(){
        var t = $(this).text();
        if (t !== ownName && (/^[A-Z0-9_-]{1,15}$/i).test(t)) {
          replies.push('@'+t+' ');
        }
      });
    }

    if(Composer.replyId && currentVal.indexOf(Composer.replyUser) != -1) {
      this.addUser(user, replies);
      Composer.textareaChanged();
      return;
    }

    this.addUser(user, replies);
    tweetManager.composerData.replyId = Composer.replyId = $(node).attr('tweetid');
    tweetManager.composerData.replyUser = Composer.replyUser = user;

    Composer.textareaChanged();
  },

  showComposeArea: function (showOnly, noAnimation) {
    var composeArea = $("#compose_tweet_area");
    var textarea = $("textarea", composeArea);
    var visible = composeArea.is(':visible');

    if(!visible) {
      if(noAnimation) {
        composeArea.show();
      } else {
        composeArea.show('blind', { direction: "vertical" }, 'normal', function() {
          textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
          textarea.focus();
        });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_up.gif');
      tweetManager.composerData.isComposing = true;
      tweetManager.composerData.replyId = Composer.replyId;
      tweetManager.composerData.replyUser = Composer.replyUser;
    } else if(!showOnly) {
      if(noAnimation) {
        composeArea.hide();
      } else {
        composeArea.hide('blind', { direction: "vertical" });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_down.gif');
      tweetManager.composerData.saveMessage = '';
      tweetManager.composerData.isComposing = false;
      tweetManager.composerData.replyId = null;
      tweetManager.composerData.replyUser = null;
      Shortener.closeArea();
    }

    if((visible && showOnly) || (!visible && noAnimation)) {
      textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
      textarea.focus();
    }
  },

  textareaChanged: function (e) {
    var el = $("#compose_tweet_area textarea");
    tweetManager.composerData.saveMessage = el.val();
    var availableChars = MAX_TWEET_SIZE - el.val().length;
    var charsLeftEl = $("#compose_tweet_area .chars_left");
    charsLeftEl.text(availableChars);
    if(availableChars < 0 || availableChars == MAX_TWEET_SIZE) {
      if(availableChars < 0) {
        charsLeftEl.css('color', 'red');
      }
      $("#compose_tweet_area input[type='button']").attr("disabled", "disabled");
    } else {
      charsLeftEl.css('color', 'black');
      $("#compose_tweet_area input[type='button']").removeAttr("disabled");
      if(e && e.ctrlKey && e.which == 13) { // Ctrl + Enter
        this.sendTweet();
      }
    }
  },

  sendTweet: function () {
    var textarea = $("#compose_tweet_area textarea");
    tweetManager.enqueueTweet(textarea.val(), Composer.replyId, Composer.replyUser);

    textarea.val("");
    Composer.replyId = null;
    Composer.textareaChanged();
    Composer.showComposeArea();
    Shortener.clear();
  },

  refreshNew: function() {
    // FIXME: #loading shouldn't be used for that.
    if($("#loading").is(":visible")) {
      return;
    }
    loadTimeline(true);
  },

  isVisible: function() {
    var composeArea = $("#compose_tweet_area");
    var textarea = $("textarea", composeArea);
    var visible = composeArea.is(':visible');
    return visible && textarea.val().length > 0;
  },

  addText: function(value) {
    var textarea = $("#compose_tweet_area textarea");
    var tmpText = textarea.val();
    if(tmpText.length > 0) {
      if((textarea[0].selectionStart > 0) &&
        (tmpText[textarea[0].selectionStart-1] != ' ')) {
        value = ' ' + value;
      }
      if((textarea[0].selectionEnd < tmpText.length) &&
         (tmpText[textarea[0].selectionEnd+1] != ' ')) {
         value += ' ';
      }
    }
    textarea.insertAtCaret(value);
    Composer.textareaChanged();
  }
};

var WorkList = {
  /* Not really a work list yet, but I intend in making it into one
     and hopefully stop this #loading madness.
   */
  init: function() {
    if(tweetManager.sendQueue.queueSize() !== 0) {
      $("#queue_loading").show();
    }
    tweetManager.sendQueue.onQueueEmpty(function(lastSent) {
      if(!window) {
        return;
      }
      WorkList.sendQueueEmpty(lastSent);
    });
    tweetManager.sendQueue.onTweetEnqueued(function() {
      if(!window) {
        return;
      }
      WorkList.tweetEnqueued();
    });
    tweetManager.sendQueue.onSendFailed(function() {
      if(!window) {
        return;
      }
      WorkList.sendFailed();
    });
    // Just checking
    WorkList.sendFailed();

    $("#queue_loading").tipsy({
      title: function() {
        var html = '<div class="worklist_container"><span class="title">' +
                   chrome.i18n.getMessage("queued_messages") +
                   '</span>';
        html += '<ul class="worklist">';
        var queueItems = tweetManager.sendQueue.queue;
        for(var i = 0, len = queueItems.length; i < len; ++i) {
          var queueItem = queueItems[i];
          var message = queueItem.message;
          if(i === 0 && message.length > 15) {
            message = message.substring(0, 13) + '...';
          } else if(message.length > 50) {
            message = message.substring(0, 48) + '...';
          }
          html += '<li>';
          html += message;
          if(i === 0) {
            var timeDiff = ((new Date()).getTime() - queueItem.createdAt.getTime()) / 1000;
            var timeDiffDesc;
            if(timeDiff < 60) {
              timeDiffDesc = parseInt(timeDiff, 10) + 's';
            } else {
              timeDiffDesc = parseInt(timeDiff / 60, 10) + 'm';
            }
            if(queueItem.retryCount == 1) {
              html += '<span class="title"> ' +
                      chrome.i18n.getMessage("queue_trying", timeDiffDesc) +
                      '</span>';
            } else {
              html += '<span class="title"> ' +
                      chrome.i18n.getMessage("queue_retried", [queueItem.retryCount, timeDiffDesc, queueItem.lastStatus]) +
                      '</span>';
            }
            if(queueItem.shouldCancel) {
              html += ' <span class="title" style="color: #d00;">' +
                      chrome.i18n.getMessage("canceling") +
                      '</span>';
            } else {
              html += '<img src="img/cancel.png" onclick="WorkList.cancelMessage();" title="' +
                      chrome.i18n.getMessage("cancelTweet") + '">';
            }
          }
          html += '</li>';
        }
        html += '</ul></div>';
        return html;
      },
      html: true,
      opacity: 0.9,
      delayOut: 500,
      persistOnHover: true,
      maxWidth: 400,
      gravity: 'tasks'
    });
  },

  cancelMessage: function() {
    var queueItems = tweetManager.sendQueue.queue;
    if(queueItems.length > 0) {
      queueItems[0].cancel();
    }
    $("#queue_loading").tipsy({refresh: true});
  },

  sendQueueEmpty: function(lastSent) {
    $("#queue_loading").hide();
    var updateTimelineId = TimelineTemplate.HOME;
    if(lastSent && lastSent.message.indexOf('d ') === 0) {
      updateTimelineId = TimelineTemplate.SENT_DMS;
    }
    loadTimeline(true, updateTimelineId);
  },

  tweetEnqueued: function() {
    $("#queue_loading").show();
  },

  sendFailed: function() {
    var abortedQueue = tweetManager.sendQueue.abortedStatus();
    if(!abortedQueue || abortedQueue.length === 0) {
      return;
    }
    // If we're here that's because something went wrong
    if(!Composer.isVisible()) {
      // For now let's just show the first enqueued message
      var topMessage = abortedQueue[0];
      Composer.initMessage(topMessage.message, topMessage.replyId, topMessage.replyUser, true);
    }
    Renderer.showError(chrome.i18n.getMessage("tweet_send_error"));
  }
};

var Shortener = {
  SHORTENER_IDLE_STR: chrome.i18n.getMessage("shortenerIdleString"),

  init: function() {
    var savedUrl = tweetManager.composerData.urlShortener;
    if(savedUrl !== '') {
      $("#shortener_area input").val(savedUrl);
    }
    this.blur();
  },

  clear: function() {
    $("#shortener_area input").val('');
    this.blur();
  },

  closeArea: function() {
    tweetManager.composerData.urlShortener = '';
  },

  focus: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if(val == this.SHORTENER_IDLE_STR) {
      shortener.val('');
      shortener.removeAttr('style');
    }
  },

  showButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(!shortenerButton.is(":visible"))
      shortenerButton.show('blind', { direction: "vertical" }, 'fast');
  },

  hideButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(shortenerButton.is(":visible"))
      shortenerButton.hide('blind', { direction: "vertical" }, 'fast');
  },

  blur: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if($.trim(val) === '' || val == this.SHORTENER_IDLE_STR) {
      shortener.val(this.SHORTENER_IDLE_STR);
      shortener.attr('style', 'color: #aaa;');
      this.hideButton();
    } else {
      this.showButton();
    }
  },

  changed: function(e) {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    tweetManager.composerData.urlShortener = val;
    if($.trim(val) !== '') {
      if(e.which == 13) { //Enter key
        this.shortenIt();
      } else {
        this.showButton();
      }
    } else {
      this.hideButton();
    }
  },

  shortenCurrentPage: function() {
    var _this = this;
    chrome.tabs.getSelected(null, function(tab) {
      var shortenerInput = $("#shortener_area input");
      shortenerInput.val(tab.url);
      _this.shortenIt({title: tab.title});
    });
  },

  shortenIt: function(context) {
    var shortenerInput = $("#shortener_area input");
    var longUrl = shortenerInput.val();
    this.shortenPage(longUrl, context);
  },

  shortenPage: function(longUrl, context) {
    $("#loading").show();
    var shortenerInput = $("#shortener_area input");
    shortenerInput.attr('disabled', 'disabled');
    this.hideButton();
    var _this = this;
    shortener.shorten(longUrl, function(success, shortUrl) {
      $("#loading").hide();
      shortenerInput.removeAttr('disabled');
      _this.closeArea();
      _this.clear();
      var textarea = $("#compose_tweet_area textarea");
      if(success && shortUrl) {
        if(context && context.title && OptionsBackend.get('share_include_title')) {
          shortUrl = context.title + ' - ' + shortUrl;
        }
        Composer.addText(shortUrl);
      } else if(!success) {
        Renderer.showError(shortUrl);
      }
      Composer.showComposeArea(true);
    });
  }
};

$.extend(Renderer, {
  assemblyTweets: function (tweets, timelineId) {
    var destination = $("#timeline-" + timelineId + " .inner_timeline");
    if(destination.length === 0)
      return;

    var useColors = true;
    if(OptionsBackend.get('tweets_color_only_unified')) {
      if(timelineId != TimelineTemplate.UNIFIED) {
        useColors = false;
      }
    }

    var nameAttribute = OptionsBackend.get('name_attribute');
    var destinationDom = destination[0];
    destinationDom.innerHTML = "";
    for(var i = 0; i < tweets.length; ++i) {
      destinationDom.appendChild(Renderer.renderTweet(tweets[i], useColors, nameAttribute));
    }

    $(".tweet").live('mouseover mouseout', function(event) {
      if(event.type == 'mouseover') {
        $(".new_actions img:not(.starred)", this).css('display', 'inline');
      } else {
        $(".new_actions img:not(.starred)", this).css('display', 'none');
      }
    });

    var hoverFunc = function(event) {
      var $this = $(this);
      var old_src = $this.attr('src');
      var new_src = old_src;
{'fraction_non_alphanumeric': 0.16232025788692092, 'fraction_numerical': 0.005976312072150386, 'mean_word_length': 2.967737299705396, 'pattern_counts': {'":': 8, '<': 143, '<?xml version=': 0, '>': 135, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4753641', 'n_tokens_mistral': 17698, 'n_tokens_neox': 17240, 'n_words': 2874}