Support hiding some tags in the buddy list, and add an 'Other Contacts' special group for contacts which aren't in any visible group.
This commit is contained in:
Родитель
fc75462d58
Коммит
f94552df58
|
@ -41,6 +41,8 @@ pref("messenger.accounts.promptOnDelete", true);
|
|||
pref("messenger.accounts.reconnectTimer", "1,5,30,60,90,300,600,1200,3600");
|
||||
|
||||
pref("messenger.buddies.showOffline", false);
|
||||
pref("messenger.buddies.hiddenTags", "");
|
||||
pref("messenger.buddies.hideTagPrompt", true);
|
||||
|
||||
pref("messenger.conversations.openInTabs", true);
|
||||
pref("messenger.conversations.useSeparateWindowsForMUCs", false);
|
||||
|
|
|
@ -56,6 +56,7 @@ buddy {
|
|||
|
||||
group {
|
||||
-moz-binding: url("chrome://instantbird/content/group.xml#group");
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
/* The height is required for the animation to work. The skin can
|
||||
|
@ -125,16 +126,20 @@ tooltip[type="buddy"] {
|
|||
-moz-binding: url('chrome://global/content/bindings/textbox.xml#textbox');
|
||||
}
|
||||
|
||||
.hideGroupButton,
|
||||
.startChatBubble,
|
||||
.expander-up,
|
||||
.expander-down {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.startChatBubble {
|
||||
.hideGroupButton,
|
||||
.startChatBubble
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
group:not([id="group-1"]):hover .hideGroupButton,
|
||||
contact[cansend]:hover .startChatBubble,
|
||||
contact[cansend][selected] .startChatBubble {
|
||||
display: -moz-box;
|
||||
|
|
|
@ -41,6 +41,8 @@ const events = ["contact-availability-changed",
|
|||
"contact-added",
|
||||
"contact-moved",
|
||||
"status-changed",
|
||||
"tag-hidden",
|
||||
"tag-shown",
|
||||
"purple-quit"];
|
||||
|
||||
const showOfflineBuddiesPref = "messenger.buddies.showOffline";
|
||||
|
@ -69,8 +71,22 @@ function buddyListContextMenu(aXulMenu) {
|
|||
"context-show-offline-buddies-separator"
|
||||
].forEach(function (aId) {
|
||||
document.getElementById(aId).hidden = hide;
|
||||
});
|
||||
|
||||
[ "context-hide-tag",
|
||||
"context-visible-tags"
|
||||
].forEach(function (aId) {
|
||||
document.getElementById(aId).hidden = !this.onGroup;
|
||||
}, this);
|
||||
|
||||
if (this.onGroup) {
|
||||
document.getElementById("context-hide-tag").disabled =
|
||||
this.target.tag.id == -1;
|
||||
}
|
||||
|
||||
document.getElementById("context-show-offline-buddies-separator").hidden =
|
||||
hide && !this.onGroup;
|
||||
|
||||
let detach = document.getElementById("context-detach");
|
||||
detach.hidden = !this.onBuddy;
|
||||
if (this.onBuddy)
|
||||
|
@ -192,6 +208,62 @@ buddyListContextMenu.prototype = {
|
|||
"Logs", "chrome,resizable", {logs: logs},
|
||||
this.target.displayName);
|
||||
},
|
||||
hideTag: function blcm_hideTag() {
|
||||
if (!this.onGroup || this.target.tag.id == -1)
|
||||
return;
|
||||
|
||||
this.target.hide();
|
||||
},
|
||||
visibleTagsPopupShowing: function blcm_visibleTagsPopupShowing() {
|
||||
if (!this.onGroup)
|
||||
return;
|
||||
|
||||
let popup = document.getElementById("context-visible-tags-popup");
|
||||
let item;
|
||||
while ((item = popup.firstChild) && item.localName != "menuseparator")
|
||||
popup.removeChild(item);
|
||||
|
||||
let sortFunction = function (a, b) {
|
||||
let [a, b] = [a.name.toLowerCase(), b.name.toLowerCase()];
|
||||
return a < b ? 1 : a > b ? -1 : 0;
|
||||
};
|
||||
Services.tags.getTags()
|
||||
.sort(sortFunction)
|
||||
.forEach(function (aTag) {
|
||||
item = document.createElement("menuitem");
|
||||
item.setAttribute("label", aTag.name);
|
||||
item.setAttribute("type", "checkbox");
|
||||
let id = aTag.id;
|
||||
item.groupId = id;
|
||||
if (!Services.tags.isTagHidden(aTag))
|
||||
item.setAttribute("checked", "true");
|
||||
popup.insertBefore(item, popup.firstChild);
|
||||
});
|
||||
|
||||
let otherContactsTag = document.getElementById("group-1");
|
||||
[ "context-other-contacts-tag-separator",
|
||||
"context-other-contacts-tag"
|
||||
].forEach(function (aId) {
|
||||
document.getElementById(aId).hidden = !otherContactsTag;
|
||||
});
|
||||
if (otherContactsTag) {
|
||||
// This avoids having the localizable "Other Contacts" string in
|
||||
// both a .dtd and .properties file.
|
||||
document.getElementById("context-other-contacts-tag").label =
|
||||
otherContactsTag.displayName;
|
||||
}
|
||||
},
|
||||
visibleTags: function blcm_visibleTags(aEvent) {
|
||||
let id = aEvent.originalTarget.groupId;
|
||||
if (!id)
|
||||
return;
|
||||
let tags = Services.tags;
|
||||
let tag = tags.getTagById(id);
|
||||
if (tags.isTagHidden(tag))
|
||||
tags.showTag(tag);
|
||||
else
|
||||
tags.hideTag(tag);
|
||||
},
|
||||
toggleShowOfflineBuddies: function blcm_toggleShowOfflineBuddies() {
|
||||
let newValue =
|
||||
!!document.getElementById("context-show-offline-buddies")
|
||||
|
@ -216,19 +288,20 @@ var buddyList = {
|
|||
else
|
||||
item.removeAttribute("checked");
|
||||
|
||||
let blistBox = document.getElementById("buddylistbox");
|
||||
Services.tags.getTags().forEach(function (aTag) {
|
||||
let elt = document.getElementById("group" + aTag.id);
|
||||
if (elt)
|
||||
elt.showOffline = showOffline;
|
||||
else if (showOffline) {
|
||||
elt = document.createElement("group");
|
||||
blistBox.appendChild(elt);
|
||||
elt._showOffline = true;
|
||||
if (!elt.build(aTag))
|
||||
blistBox.removeChild(elt);
|
||||
if (Services.tags.isTagHidden(aTag))
|
||||
this.showOtherContacts();
|
||||
else
|
||||
this.displayGroup(aTag);
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
let elt = document.getElementById("group-1"); // "Other contacts""
|
||||
if (elt)
|
||||
elt.showOffline = showOffline;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -237,23 +310,24 @@ var buddyList = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (aTopic == "tag-hidden") {
|
||||
this.showOtherContacts();
|
||||
return;
|
||||
}
|
||||
|
||||
if (aTopic == "tag-shown") {
|
||||
if (!document.getElementById("group" + aSubject.id))
|
||||
this.displayGroup(aSubject);
|
||||
return;
|
||||
}
|
||||
|
||||
// aSubject is an imIContact
|
||||
if (aSubject.online || this._showOffline) {
|
||||
aSubject.getTags().forEach(function (aTag) {
|
||||
if (!document.getElementById("group" + aTag.id)) {
|
||||
let groupElt = document.createElement("group");
|
||||
let blistBox = document.getElementById("buddylistbox");
|
||||
blistBox.appendChild(groupElt);
|
||||
if (this._showOffline)
|
||||
groupElt._showOffline = true;
|
||||
if (!groupElt.build(aTag)) {
|
||||
// Broken group or notification?
|
||||
// This should never happen as there will always be at least
|
||||
// one contact shown.
|
||||
// (We test the aSubject.online || this._showOffline to ensure it.)
|
||||
blistBox.removeChild(groupElt);
|
||||
}
|
||||
}
|
||||
if (Services.tags.isTagHidden(aTag))
|
||||
this.showOtherContacts();
|
||||
else if (!document.getElementById("group" + aTag.id))
|
||||
this.displayGroup(aTag);
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
|
@ -420,22 +494,35 @@ var buddyList = {
|
|||
.setAttribute("checked", "true");
|
||||
}
|
||||
|
||||
let blistBox = document.getElementById("buddylistbox");
|
||||
let showOtherContacts = false;
|
||||
Services.tags.getTags().forEach(function (aTag) {
|
||||
let groupElt = document.createElement("group");
|
||||
blistBox.appendChild(groupElt);
|
||||
if (buddyList._showOffline)
|
||||
groupElt._showOffline = true;
|
||||
if (!groupElt.build(aTag))
|
||||
blistBox.removeChild(groupElt);
|
||||
if (Services.tags.isTagHidden(aTag))
|
||||
showOtherContacts = true;
|
||||
else
|
||||
buddyList.displayGroup(aTag);
|
||||
});
|
||||
blistBox.focus();
|
||||
if (showOtherContacts)
|
||||
buddyList.showOtherContacts();
|
||||
document.getElementById("buddylistbox").focus();
|
||||
|
||||
prefBranch.addObserver(showOfflineBuddiesPref, buddyList, false);
|
||||
addObservers(buddyList, events);
|
||||
|
||||
this.addEventListener("unload", buddyList.unload, false);
|
||||
},
|
||||
displayGroup: function(aTag) {
|
||||
let blistBox = document.getElementById("buddylistbox");
|
||||
let groupElt = document.createElement("group");
|
||||
blistBox.insertBefore(groupElt, document.getElementById("group-1"));
|
||||
if (this._showOffline)
|
||||
groupElt._showOffline = true;
|
||||
if (!groupElt.build(aTag))
|
||||
blistBox.removeChild(groupElt);
|
||||
},
|
||||
showOtherContacts: function bl_showOtherContacts() {
|
||||
if (!document.getElementById("group-1"))
|
||||
this.displayGroup(Services.tags.otherContactsTag);
|
||||
},
|
||||
unload: function bl_unload() {
|
||||
removeObservers(buddyList, events);
|
||||
Services.prefs.removeObserver(showOfflineBuddiesPref, buddyList);
|
||||
|
|
|
@ -117,6 +117,21 @@
|
|||
oncommand="gBuddyListContextMenu.moveToNewTag();"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem id="context-hide-tag"
|
||||
label="&hideTagCmd.label;"
|
||||
accesskey="&hideTagCmd.accesskey;"
|
||||
oncommand="gBuddyListContextMenu.hideTag();"/>
|
||||
<menu id="context-visible-tags"
|
||||
label="&visibleTagsCmd.label;"
|
||||
accesskey="&visibleTagsCmd.accesskey;">
|
||||
<menupopup id="context-visible-tags-popup"
|
||||
oncommand="gBuddyListContextMenu.visibleTags(event);"
|
||||
onpopupshowing="gBuddyListContextMenu.visibleTagsPopupShowing();">
|
||||
<menuseparator id="context-other-contacts-tag-separator"/>
|
||||
<menuitem id="context-other-contacts-tag"
|
||||
checked="true" disabled="true"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator id="context-show-offline-buddies-separator"/>
|
||||
<menuitem id="context-show-offline-buddies"
|
||||
label="&showOfflineBuddiesCmd.label;"
|
||||
|
|
|
@ -36,8 +36,10 @@
|
|||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
|
||||
<!DOCTYPE bindings>
|
||||
<!DOCTYPE bindings [
|
||||
<!ENTITY % instantbirdDTD SYSTEM "chrome://instantbird/locale/instantbird.dtd" >
|
||||
%instantbirdDTD;
|
||||
]>
|
||||
|
||||
<bindings id="groupBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
|
@ -48,6 +50,8 @@
|
|||
<content persist="closed">
|
||||
<xul:image class="twisty"/>
|
||||
<xul:label flex="1" crop="end" xbl:inherits="value=name"/>
|
||||
<xul:button anonid="hideGroupButton" class="hideGroupButton"
|
||||
tooltiptext="&hideGroupTooltip;"/>
|
||||
</content>
|
||||
<implementation implements="nsIObserver">
|
||||
|
||||
|
@ -90,6 +94,15 @@
|
|||
this.setAttribute("closed", "true");
|
||||
|
||||
contacts.forEach(this.addContact, this);
|
||||
|
||||
let name;
|
||||
if (this.tag.id != -1)
|
||||
name = this.tag.name;
|
||||
else {
|
||||
name = Services.strings.createBundle("chrome://instantbird/locale/instantbird.properties")
|
||||
.GetStringFromName("group.otherContacts.name");
|
||||
}
|
||||
this.displayName = name;
|
||||
this._updateGroupLabel();
|
||||
this.tag.addObserver(this);
|
||||
return true;
|
||||
|
@ -150,6 +163,16 @@
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aTopic == "tag-hidden") {
|
||||
this.setAttribute("collapsing", "true");
|
||||
this.addEventListener("transitionend", this._transitionEnd, true);
|
||||
for each (let contact in this.contacts) {
|
||||
contact.state = "collapsing";
|
||||
contact.finishRemoveNode();
|
||||
}
|
||||
return;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -214,6 +237,38 @@
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<method name="hide">
|
||||
<body>
|
||||
<![CDATA[
|
||||
const promptPrefName = "messenger.buddies.hideTagPrompt";
|
||||
if (Services.prefs.getBoolPref(promptPrefName)) {
|
||||
let bundle =
|
||||
Services.strings.createBundle("chrome://instantbird/locale/instantbird.properties");
|
||||
let name = this.displayName;
|
||||
let promptTitle =
|
||||
bundle.formatStringFromName("group.hidePrompt.title", [name], 1);
|
||||
let promptMessage =
|
||||
bundle.formatStringFromName("group.hidePrompt.message", [name], 1);
|
||||
let hideButton = bundle.GetStringFromName("group.hidePrompt.button");
|
||||
let promptCheckbox =
|
||||
bundle.GetStringFromName("group.hidePrompt.checkbox");
|
||||
let prompts = Services.prompt;
|
||||
let checkbox = {};
|
||||
let flags = prompts.BUTTON_TITLE_IS_STRING * prompts.BUTTON_POS_0 +
|
||||
prompts.BUTTON_TITLE_CANCEL * prompts.BUTTON_POS_1 +
|
||||
prompts.BUTTON_POS_0_DEFAULT;
|
||||
if (prompts.confirmEx(window, promptTitle, promptMessage, flags,
|
||||
hideButton, null, null, promptCheckbox, checkbox))
|
||||
return;
|
||||
|
||||
if (!checkbox.value)
|
||||
Services.prefs.setBoolPref(promptPrefName, false);
|
||||
}
|
||||
Services.tags.hideTag(this.tag);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_updateClosedState">
|
||||
<parameter name="aClosed"/>
|
||||
<body>
|
||||
|
@ -241,10 +296,11 @@
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<field name="displayName"></field>
|
||||
<method name="_updateGroupLabel">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let name = this.tag.name;
|
||||
let name = this.displayName;
|
||||
if (this.hasAttribute("closed"))
|
||||
name += " (" + this.contacts.length + ")";
|
||||
|
||||
|
@ -284,6 +340,9 @@
|
|||
if ((event.detail == 1 && event.originalTarget.localName == "image") ||
|
||||
(event.detail == 2 && event.originalTarget.localName == "label"))
|
||||
this.close();
|
||||
|
||||
if (event.originalTarget.localName == "button")
|
||||
this.hide();
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
|
|
|
@ -90,12 +90,18 @@
|
|||
<!ENTITY moveNewTagCmd.accesskey "N">
|
||||
<!ENTITY showLogsCmd.label "Show Logs">
|
||||
<!ENTITY showLogsCmd.accesskey "L">
|
||||
<!ENTITY hideTagCmd.label "Hide Tag">
|
||||
<!ENTITY hideTagCmd.accesskey "H">
|
||||
<!ENTITY visibleTagsCmd.label "Visible Tags…">
|
||||
<!ENTITY visibleTagsCmd.accesskey "V">
|
||||
<!ENTITY showOfflineBuddiesCmd.label "Show offline buddies">
|
||||
<!ENTITY showOfflineBuddiesCmd.accesskey "o">
|
||||
|
||||
<!ENTITY expandContactTooltip "Expand">
|
||||
<!ENTITY collapseContactTooltip "Collapse">
|
||||
|
||||
<!ENTITY hideGroupTooltip "Hide">
|
||||
|
||||
<!-- Copied from mozilla/browser/locales/en-US/chrome/browser/baseMenuOverlay.dtd -->
|
||||
<!-- Mac OS X Window Menu -->
|
||||
<!ENTITY windowMenu.label "Window">
|
||||
|
|
|
@ -34,6 +34,24 @@ buddy.deletePrompt.message=%S will be permanently removed from your %S buddy lis
|
|||
# used as the accesskey for this button.
|
||||
buddy.deletePrompt.button=&Delete
|
||||
|
||||
group.otherContacts.name=Other Contacts
|
||||
#LOCALIZATION NOTE
|
||||
# %S here will be replaced by the tag name
|
||||
group.hidePrompt.title=Hide %S?
|
||||
|
||||
#LOCALIZATION NOTE %S here will be replaced by the tag name.
|
||||
# The translation for 'Visible Tags…' here should match the translation of
|
||||
# visibleTagsCmd.label in instantbird.dtd
|
||||
# The translation for 'Other Contacts' should match group.otherContacts.name
|
||||
group.hidePrompt.message=The tag '%S' will no longer be visible. Use the 'Visible Tags…' context menu item to show it again.\n\nContacts that have no visible tag will be displayed in the 'Other Contacts' special group at the bottom of the list.
|
||||
|
||||
#LOCALIZATION NOTE
|
||||
# the & symbol indicates the position of the character that should be
|
||||
# used as the accesskey for this button.
|
||||
group.hidePrompt.button=&Hide
|
||||
|
||||
group.hidePrompt.checkbox=Show next time
|
||||
|
||||
availableStatusType=Available
|
||||
awayStatusType=Away
|
||||
unavailableStatusType=Unavailable
|
||||
|
|
|
@ -99,6 +99,7 @@ buddy[droptarget] {
|
|||
min-height: 40px;
|
||||
}
|
||||
|
||||
.hideGroupButton,
|
||||
.startChatBubble,
|
||||
.expander-up,
|
||||
.expander-down {
|
||||
|
@ -110,6 +111,29 @@ buddy[droptarget] {
|
|||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
%ifdef XP_UNIX
|
||||
%ifndef XP_MACOSX
|
||||
%define UNIX_BUT_NOT_MAC
|
||||
%endif
|
||||
%endif
|
||||
|
||||
.hideGroupButton {
|
||||
-moz-margin-end: 0;
|
||||
-moz-stack-sizing: ignore;
|
||||
%ifdef UNIX_BUT_NOT_MAC
|
||||
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
|
||||
%else
|
||||
list-style-image: url("chrome://global/skin/icons/close.png");
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
.hideGroupButton:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
.hideGroupButton:hover:active {
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
%endif
|
||||
}
|
||||
|
||||
.startChatBubble {
|
||||
list-style-image: url('chrome://instantbird/skin/prpl-generic/icon.png');
|
||||
}
|
||||
|
@ -135,7 +159,9 @@ buddy[droptarget] {
|
|||
max-height: 16px;
|
||||
}
|
||||
|
||||
.protoIcon, .statusIcon, .startChatBubble, .expander-up, .expander-down {
|
||||
.protoIcon, .statusIcon,
|
||||
.hideGroupButton, .startChatBubble,
|
||||
.expander-up, .expander-down {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
min-height: 16px;
|
||||
|
@ -206,6 +232,7 @@ group[closed] .twisty {
|
|||
%ifdef XP_MACOSX
|
||||
group .twisty {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
-moz-margin-end: 3px;
|
||||
-moz-margin-start: 3px;
|
||||
background: url("chrome://global/skin/arrow/arrow-dn-sharp.gif") no-repeat center;
|
||||
|
|
|
@ -77,6 +77,12 @@ interface imITagsService: nsISupports {
|
|||
// Get an array of all existing tags.
|
||||
void getTags([optional] out unsigned long tagCount,
|
||||
[retval, array, size_is(tagCount)] out imITag tags);
|
||||
|
||||
boolean isTagHidden(in imITag aTag);
|
||||
void hideTag(in imITag aTag);
|
||||
void showTag(in imITag aTag);
|
||||
|
||||
readonly attribute imITag otherContactsTag;
|
||||
};
|
||||
|
||||
[scriptable, uuid(c211e5e2-f0a4-4a86-9e4c-3f6b905628a5)]
|
||||
|
|
|
@ -91,6 +91,14 @@ TagsService.prototype = {
|
|||
return Tags;
|
||||
},
|
||||
|
||||
isTagHidden: function(aTag) aTag.id in otherContactsTag._hiddenTags,
|
||||
hideTag: function(aTag) { otherContactsTag.hideTag(aTag); },
|
||||
showTag: function(aTag) { otherContactsTag.showTag(aTag); },
|
||||
get otherContactsTag() {
|
||||
otherContactsTag._initContacts();
|
||||
return otherContactsTag;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.imITagsService]),
|
||||
classDescription: "Tags",
|
||||
classID: Components.ID("{1fa92237-4303-4384-b8ac-4e65b50810a5}"),
|
||||
|
@ -159,6 +167,134 @@ Tag.prototype = {
|
|||
QueryInterface: XPCOMUtils.generateQI([Ci.imITag, Ci.nsIClassInfo])
|
||||
};
|
||||
|
||||
|
||||
var otherContactsTag = {
|
||||
hiddenTagsPref: "messenger.buddies.hiddenTags",
|
||||
_hiddenTags: {},
|
||||
_contactsInitialized: false,
|
||||
_saveHiddenTagsPref: function() {
|
||||
Services.prefs.setCharPref(this.hiddenTagsPref,
|
||||
[id for (id in this._hiddenTags)].join(","));
|
||||
},
|
||||
showTag: function(aTag) {
|
||||
aTag.removeObserver(this);
|
||||
let id = aTag.id;
|
||||
delete this._hiddenTags[id];
|
||||
for each (let contact in this._contacts)
|
||||
if (contact.getTags().some(function(t) t.id == id))
|
||||
this._removeContact(contact);
|
||||
|
||||
aTag.notifyObservers(aTag, "tag-shown", null);
|
||||
Services.obs.notifyObservers(aTag, "tag-shown", null);
|
||||
this._saveHiddenTagsPref();
|
||||
},
|
||||
hideTag: function(aTag) {
|
||||
if (aTag.id < 0 || aTag.id in otherContactsTag._hiddenTags)
|
||||
return;
|
||||
|
||||
this._hiddenTags[aTag.id] = aTag;
|
||||
if (this._contactsInitialized)
|
||||
this._hideTag(aTag);
|
||||
|
||||
aTag.notifyObservers(aTag, "tag-hidden", null);
|
||||
Services.obs.notifyObservers(aTag, "tag-hidden", null);
|
||||
this._saveHiddenTagsPref();
|
||||
},
|
||||
_hideTag: function(aTag) {
|
||||
for each (let contact in aTag.getContacts())
|
||||
if (!(contact.id in this._contacts) &&
|
||||
contact.getTags().every(function(t) t.id in this._hiddenTags, this))
|
||||
this._addContact(contact);
|
||||
aTag.addObserver(this);
|
||||
},
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic != "contact-moved-in" && aTopic != "contact-moved-out")
|
||||
return;
|
||||
|
||||
try {
|
||||
aSubject.QueryInterface(Ci.imIContact);
|
||||
} catch (e) {
|
||||
// TODO Most likely, aSubject is a tag. If a tag was added to a
|
||||
// contact we currently track, we should check that the new tag
|
||||
// is hidden, and if it is not, remove the contact from the
|
||||
// 'other contacts' group.
|
||||
}
|
||||
|
||||
if (aTopic == "contact-moved-in" && !(aSubject.id in this._contacts) &&
|
||||
aSubject.getTags().every(function(t) t.id in this._hiddenTags, this))
|
||||
this._addContact(aSubject);
|
||||
else if (aTopic == "contact-moved-out" && aSubject.id in this._contacts &&
|
||||
aSubject.getTags().some(function(t) !(t.id in this._hiddenTags)))
|
||||
this._removeContact(aSubject);
|
||||
},
|
||||
|
||||
_initHiddenTags: function() {
|
||||
let pref = Services.prefs.getCharPref(this.hiddenTagsPref);
|
||||
if (!pref)
|
||||
return;
|
||||
for each (let tagId in pref.split(","))
|
||||
this._hiddenTags[tagId] = TagsById[tagId];
|
||||
},
|
||||
_initContacts: function() {
|
||||
if (this._contactsInitialized)
|
||||
return;
|
||||
this._observers = [];
|
||||
this._observer = {observe: this.notifyObservers.bind(this)};
|
||||
this._contacts = {};
|
||||
this._contactsInitialized = true;
|
||||
for each (let tag in this._hiddenTags)
|
||||
this._hideTag(tag);
|
||||
},
|
||||
|
||||
// imITag implementation
|
||||
get id() -1,
|
||||
get name() "__others__",
|
||||
set name(aNewName) { throw Cr.NS_ERROR_NOT_AVAILABLE; },
|
||||
getContacts: function(aContactCount) {
|
||||
let contacts = [contact for each (contact in this._contacts)];
|
||||
if (aContactCount)
|
||||
aContactCount.value = contacts.length;
|
||||
return contacts;
|
||||
},
|
||||
_addContact: function (aContact) {
|
||||
this._contacts[aContact.id] = aContact;
|
||||
this.notifyObservers(aContact, "contact-moved-in");
|
||||
for each (let observer in ContactsById[aContact.id]._observers)
|
||||
observer.observe(this, "contact-moved-in", null);
|
||||
aContact.addObserver(this._observer);
|
||||
},
|
||||
_removeContact: function (aContact) {
|
||||
delete this._contacts[aContact.id];
|
||||
aContact.removeObserver(this._observer);
|
||||
this.notifyObservers(aContact, "contact-moved-out");
|
||||
for each (let observer in ContactsById[aContact.id]._observers)
|
||||
observer.observe(this, "contact-moved-out", null);
|
||||
},
|
||||
|
||||
addObserver: function(aObserver) {
|
||||
if (this._observers.indexOf(aObserver) == -1)
|
||||
this._observers.push(aObserver);
|
||||
},
|
||||
removeObserver: function(aObserver) {
|
||||
this._observers = this._observers.filter(function(o) o !== aObserver);
|
||||
},
|
||||
notifyObservers: function(aSubject, aTopic, aData) {
|
||||
for each (let observer in this._observers)
|
||||
observer.observe(aSubject, aTopic, aData);
|
||||
},
|
||||
|
||||
getInterfaces: function(countRef) {
|
||||
var interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.nsIObserver, Ci.imITag];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
getHelperForLanguage: function(language) null,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.imITag, Ci.nsIObserver, Ci.nsIClassInfo])
|
||||
};
|
||||
|
||||
|
||||
var ContactsById = { };
|
||||
var LastDummyContactId = 0;
|
||||
function Contact(aId, aAlias) {
|
||||
|
@ -991,6 +1127,8 @@ ContactsService.prototype = {
|
|||
dump(e + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
otherContactsTag._initHiddenTags();
|
||||
},
|
||||
unInitContacts: function() {
|
||||
AccountsById = { };
|
||||
|
|
Загрузка…
Ссылка в новой задаче