Add support for pinning/unpinning groups in people panel and contacts floater
Signed-off-by: PanteraPolnocy <panterapolnocy@gmail.com>master
parent
a1ba797c46
commit
77023234d3
|
|
@ -114,6 +114,7 @@ set(viewer_SOURCE_FILES
|
||||||
fsdroptarget.cpp
|
fsdroptarget.cpp
|
||||||
fsexportperms.cpp
|
fsexportperms.cpp
|
||||||
fsfloateraddtocontactset.cpp
|
fsfloateraddtocontactset.cpp
|
||||||
|
fsfavoritegroups.cpp
|
||||||
fsfloaterassetblacklist.cpp
|
fsfloaterassetblacklist.cpp
|
||||||
fsfloateravatarrendersettings.cpp
|
fsfloateravatarrendersettings.cpp
|
||||||
fsfloaterblocklist.cpp
|
fsfloaterblocklist.cpp
|
||||||
|
|
@ -956,6 +957,7 @@ set(viewer_HEADER_FILES
|
||||||
fsdroptarget.h
|
fsdroptarget.h
|
||||||
fsexportperms.h
|
fsexportperms.h
|
||||||
fsfloateraddtocontactset.h
|
fsfloateraddtocontactset.h
|
||||||
|
fsfavoritegroups.h
|
||||||
fsfloaterassetblacklist.h
|
fsfloaterassetblacklist.h
|
||||||
fsfloateravatarrendersettings.h
|
fsfloateravatarrendersettings.h
|
||||||
fsfloaterblocklist.h
|
fsfloaterblocklist.h
|
||||||
|
|
|
||||||
|
|
@ -1374,6 +1374,17 @@
|
||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</map>
|
</map>
|
||||||
|
<key>FSFavoriteGroups</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>List of favorite/pinned group UUIDs</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>LLSD</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<array></array>
|
||||||
|
</map>
|
||||||
<key>FSMaxSharedMaturity</key>
|
<key>FSMaxSharedMaturity</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
/**
|
||||||
|
* @file fsfavoritegroups.cpp
|
||||||
|
* @brief Favorite groups storage management
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||||
|
* Phoenix Firestorm Viewer Source Code
|
||||||
|
* Copyright (C) 2025, The Phoenix Firestorm Project, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||||
|
* http://www.firestormviewer.org
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "llviewerprecompiledheaders.h"
|
||||||
|
|
||||||
|
#include "fsfavoritegroups.h"
|
||||||
|
|
||||||
|
#include "llagent.h"
|
||||||
|
#include "llviewercontrol.h"
|
||||||
|
|
||||||
|
FSFavoriteGroups::FSFavoriteGroups()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FSFavoriteGroups::~FSFavoriteGroups()
|
||||||
|
{
|
||||||
|
saveFavorites();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FSFavoriteGroups::isFavorite(const LLUUID& group_id) const
|
||||||
|
{
|
||||||
|
return mFavoriteGroups.find(group_id) != mFavoriteGroups.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSFavoriteGroups::addFavorite(const LLUUID& group_id)
|
||||||
|
{
|
||||||
|
if (group_id.isNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFavoriteGroups.insert(group_id).second)
|
||||||
|
{
|
||||||
|
saveFavorites();
|
||||||
|
mFavoritesChangedSignal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSFavoriteGroups::removeFavorite(const LLUUID& group_id)
|
||||||
|
{
|
||||||
|
if (mFavoriteGroups.erase(group_id) > 0)
|
||||||
|
{
|
||||||
|
saveFavorites();
|
||||||
|
mFavoritesChangedSignal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSFavoriteGroups::toggleFavorite(const LLUUID& group_id)
|
||||||
|
{
|
||||||
|
if (isFavorite(group_id))
|
||||||
|
{
|
||||||
|
removeFavorite(group_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addFavorite(group_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSFavoriteGroups::loadFavorites()
|
||||||
|
{
|
||||||
|
mFavoriteGroups.clear();
|
||||||
|
|
||||||
|
LLSD favorites = gSavedPerAccountSettings.getLLSD("FSFavoriteGroups");
|
||||||
|
|
||||||
|
if (favorites.isArray())
|
||||||
|
{
|
||||||
|
for (LLSD::array_const_iterator it = favorites.beginArray(); it != favorites.endArray(); ++it)
|
||||||
|
{
|
||||||
|
if (it->isUUID())
|
||||||
|
{
|
||||||
|
mFavoriteGroups.insert(it->asUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LL_INFOS("FavoriteGroups") << "Loaded " << mFavoriteGroups.size() << " favorite groups from per-account settings" << LL_ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSFavoriteGroups::saveFavorites()
|
||||||
|
{
|
||||||
|
|
||||||
|
std::set<LLUUID> stale_groups;
|
||||||
|
for (const auto& group_id : mFavoriteGroups)
|
||||||
|
{
|
||||||
|
if (!gAgent.isInGroup(group_id))
|
||||||
|
{
|
||||||
|
stale_groups.insert(group_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stale_groups.empty())
|
||||||
|
{
|
||||||
|
for (const auto& group_id : stale_groups)
|
||||||
|
{
|
||||||
|
mFavoriteGroups.erase(group_id);
|
||||||
|
}
|
||||||
|
LL_INFOS("FavoriteGroups") << "Removed " << stale_groups.size() << " stale group(s) from favorites (no longer a member)" << LL_ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLSD favorites_array = LLSD::emptyArray();
|
||||||
|
|
||||||
|
for (const auto& group_id : mFavoriteGroups)
|
||||||
|
{
|
||||||
|
favorites_array.append(group_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
gSavedPerAccountSettings.setLLSD("FSFavoriteGroups", favorites_array);
|
||||||
|
|
||||||
|
LL_DEBUGS("FavoriteGroups") << "Saved " << mFavoriteGroups.size() << " favorite groups to per-account settings" << LL_ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* @file fsfavoritegroups.h
|
||||||
|
* @brief Favorite groups storage management
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||||
|
* Phoenix Firestorm Viewer Source Code
|
||||||
|
* Copyright (C) 2025, The Phoenix Firestorm Project, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||||
|
* http://www.firestormviewer.org
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FS_FAVORITEGROUPS_H
|
||||||
|
#define FS_FAVORITEGROUPS_H
|
||||||
|
|
||||||
|
#include "llsingleton.h"
|
||||||
|
#include "lluuid.h"
|
||||||
|
#include <boost/signals2.hpp>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
class FSFavoriteGroups : public LLSingleton<FSFavoriteGroups>
|
||||||
|
{
|
||||||
|
LLSINGLETON(FSFavoriteGroups);
|
||||||
|
~FSFavoriteGroups();
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool isFavorite(const LLUUID& group_id) const;
|
||||||
|
void addFavorite(const LLUUID& group_id);
|
||||||
|
void removeFavorite(const LLUUID& group_id);
|
||||||
|
void toggleFavorite(const LLUUID& group_id);
|
||||||
|
const std::set<LLUUID>& getFavorites() const { return mFavoriteGroups; }
|
||||||
|
bool hasFavorites() const { return !mFavoriteGroups.empty(); }
|
||||||
|
void loadFavorites();
|
||||||
|
void saveFavorites();
|
||||||
|
|
||||||
|
typedef boost::signals2::signal<void()> favorites_changed_signal_t;
|
||||||
|
boost::signals2::connection setFavoritesChangedCallback(const favorites_changed_signal_t::slot_type& cb)
|
||||||
|
{
|
||||||
|
return mFavoritesChangedSignal.connect(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<LLUUID> mFavoriteGroups;
|
||||||
|
favorites_changed_signal_t mFavoritesChangedSignal;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FS_FAVORITEGROUPS_H
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include "fscommon.h"
|
#include "fscommon.h"
|
||||||
#include "fscontactsfriendsmenu.h"
|
#include "fscontactsfriendsmenu.h"
|
||||||
|
#include "fsfavoritegroups.h"
|
||||||
#include "fsfloaterimcontainer.h"
|
#include "fsfloaterimcontainer.h"
|
||||||
#include "fsscrolllistctrl.h"
|
#include "fsscrolllistctrl.h"
|
||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
|
|
@ -147,6 +148,7 @@ bool FSFloaterContacts::postBuild()
|
||||||
mGroupsChatBtn = mGroupsTab->getChild<LLButton>("chat_btn");
|
mGroupsChatBtn = mGroupsTab->getChild<LLButton>("chat_btn");
|
||||||
mGroupsInfoBtn = mGroupsTab->getChild<LLButton>("info_btn");
|
mGroupsInfoBtn = mGroupsTab->getChild<LLButton>("info_btn");
|
||||||
mGroupsActivateBtn = mGroupsTab->getChild<LLButton>("activate_btn");
|
mGroupsActivateBtn = mGroupsTab->getChild<LLButton>("activate_btn");
|
||||||
|
mGroupsFavoriteBtn = mGroupsTab->getChild<LLButton>("favorite_btn");
|
||||||
mGroupsLeaveBtn = mGroupsTab->getChild<LLButton>("leave_btn");
|
mGroupsLeaveBtn = mGroupsTab->getChild<LLButton>("leave_btn");
|
||||||
mGroupsCreateBtn = mGroupsTab->getChild<LLButton>("create_btn");
|
mGroupsCreateBtn = mGroupsTab->getChild<LLButton>("create_btn");
|
||||||
mGroupsSearchBtn = mGroupsTab->getChild<LLButton>("search_btn");
|
mGroupsSearchBtn = mGroupsTab->getChild<LLButton>("search_btn");
|
||||||
|
|
@ -156,6 +158,7 @@ bool FSFloaterContacts::postBuild()
|
||||||
mGroupsChatBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this));
|
mGroupsChatBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this));
|
||||||
mGroupsInfoBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupInfoButtonClicked, this));
|
mGroupsInfoBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupInfoButtonClicked, this));
|
||||||
mGroupsActivateBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupActivateButtonClicked, this));
|
mGroupsActivateBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupActivateButtonClicked, this));
|
||||||
|
mGroupsFavoriteBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupFavoriteButtonClicked, this));
|
||||||
mGroupsLeaveBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupLeaveButtonClicked, this));
|
mGroupsLeaveBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupLeaveButtonClicked, this));
|
||||||
mGroupsCreateBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupCreateButtonClicked, this));
|
mGroupsCreateBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupCreateButtonClicked, this));
|
||||||
mGroupsSearchBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupSearchButtonClicked, this));
|
mGroupsSearchBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupSearchButtonClicked, this));
|
||||||
|
|
@ -247,6 +250,12 @@ void FSFloaterContacts::updateGroupButtons()
|
||||||
mGroupsLeaveBtn->setEnabled(isGroup);
|
mGroupsLeaveBtn->setEnabled(isGroup);
|
||||||
mGroupsCreateBtn->setEnabled((!gMaxAgentGroups) || (gAgent.mGroups.size() < gMaxAgentGroups));
|
mGroupsCreateBtn->setEnabled((!gMaxAgentGroups) || (gAgent.mGroups.size() < gMaxAgentGroups));
|
||||||
mGroupsInviteBtn->setEnabled(isGroup && gAgent.hasPowerInGroup(groupId, GP_MEMBER_INVITE));
|
mGroupsInviteBtn->setEnabled(isGroup && gAgent.hasPowerInGroup(groupId, GP_MEMBER_INVITE));
|
||||||
|
mGroupsFavoriteBtn->setEnabled(isGroup);
|
||||||
|
if (isGroup)
|
||||||
|
{
|
||||||
|
bool is_favorite = FSFavoriteGroups::getInstance()->isFavorite(groupId);
|
||||||
|
mGroupsFavoriteBtn->setLabel(is_favorite ? getString("unfavorite_label") : getString("favorite_label"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSFloaterContacts::onOpen(const LLSD& key)
|
void FSFloaterContacts::onOpen(const LLSD& key)
|
||||||
|
|
@ -432,6 +441,15 @@ void FSFloaterContacts::onGroupActivateButtonClicked()
|
||||||
LLGroupActions::activate(mGroupList->getSelectedUUID());
|
LLGroupActions::activate(mGroupList->getSelectedUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FSFloaterContacts::onGroupFavoriteButtonClicked()
|
||||||
|
{
|
||||||
|
if (LLUUID group_id = getCurrentItemID(); group_id.notNull())
|
||||||
|
{
|
||||||
|
FSFavoriteGroups::getInstance()->toggleFavorite(group_id);
|
||||||
|
updateGroupButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FSFloaterContacts::onGroupLeaveButtonClicked()
|
void FSFloaterContacts::onGroupLeaveButtonClicked()
|
||||||
{
|
{
|
||||||
if (LLUUID group_id = getCurrentItemID(); group_id.notNull())
|
if (LLUUID group_id = getCurrentItemID(); group_id.notNull())
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ private:
|
||||||
void onGroupChatButtonClicked();
|
void onGroupChatButtonClicked();
|
||||||
void onGroupInfoButtonClicked();
|
void onGroupInfoButtonClicked();
|
||||||
void onGroupActivateButtonClicked();
|
void onGroupActivateButtonClicked();
|
||||||
|
void onGroupFavoriteButtonClicked();
|
||||||
void onGroupLeaveButtonClicked();
|
void onGroupLeaveButtonClicked();
|
||||||
void onGroupCreateButtonClicked();
|
void onGroupCreateButtonClicked();
|
||||||
void onGroupSearchButtonClicked();
|
void onGroupSearchButtonClicked();
|
||||||
|
|
@ -167,6 +168,7 @@ private:
|
||||||
LLButton* mGroupsChatBtn{ nullptr };
|
LLButton* mGroupsChatBtn{ nullptr };
|
||||||
LLButton* mGroupsInfoBtn{ nullptr };
|
LLButton* mGroupsInfoBtn{ nullptr };
|
||||||
LLButton* mGroupsActivateBtn{ nullptr };
|
LLButton* mGroupsActivateBtn{ nullptr };
|
||||||
|
LLButton* mGroupsFavoriteBtn{ nullptr };
|
||||||
LLButton* mGroupsLeaveBtn{ nullptr };
|
LLButton* mGroupsLeaveBtn{ nullptr };
|
||||||
LLButton* mGroupsCreateBtn{ nullptr };
|
LLButton* mGroupsCreateBtn{ nullptr };
|
||||||
LLButton* mGroupsSearchBtn{ nullptr };
|
LLButton* mGroupsSearchBtn{ nullptr };
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
// [RLVa:KB] - Checked: RLVa-2.0.3
|
// [RLVa:KB] - Checked: RLVa-2.0.3
|
||||||
#include "rlvactions.h"
|
#include "rlvactions.h"
|
||||||
// [/RLVa:KB]
|
// [/RLVa:KB]
|
||||||
|
#include "fsfavoritegroups.h" // <FS:PP> Group favorites / pinning
|
||||||
#include "llslurl.h"
|
#include "llslurl.h"
|
||||||
#include "llurlaction.h"
|
#include "llurlaction.h"
|
||||||
|
|
||||||
|
|
@ -59,8 +60,37 @@ public:
|
||||||
/** Returns true if item1 < item2, false otherwise */
|
/** Returns true if item1 < item2, false otherwise */
|
||||||
/*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
|
/*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
|
||||||
{
|
{
|
||||||
std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
|
// <FS:PP> Group favorites / pinning
|
||||||
std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
|
// std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
|
||||||
|
// std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
|
||||||
|
|
||||||
|
const LLGroupListItem* group_item1 = dynamic_cast<const LLGroupListItem*>(item1);
|
||||||
|
const LLGroupListItem* group_item2 = dynamic_cast<const LLGroupListItem*>(item2);
|
||||||
|
|
||||||
|
if (!group_item1 || !group_item2)
|
||||||
|
{
|
||||||
|
if (!group_item1 && group_item2)
|
||||||
|
{
|
||||||
|
return group_item2->isFavorite() ? false : true;
|
||||||
|
}
|
||||||
|
if (group_item1 && !group_item2)
|
||||||
|
{
|
||||||
|
return group_item1->isFavorite() ? true : false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fav1 = group_item1->isFavorite();
|
||||||
|
bool fav2 = group_item2->isFavorite();
|
||||||
|
|
||||||
|
if (fav1 != fav2)
|
||||||
|
{
|
||||||
|
return fav1 > fav2;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name1 = group_item1->getGroupName();
|
||||||
|
std::string name2 = group_item2->getGroupName();
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
LLStringUtil::toUpper(name1);
|
LLStringUtil::toUpper(name1);
|
||||||
LLStringUtil::toUpper(name2);
|
LLStringUtil::toUpper(name2);
|
||||||
|
|
@ -76,11 +106,22 @@ public:
|
||||||
|
|
||||||
/*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
|
/*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
|
||||||
{
|
{
|
||||||
const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1);
|
// <FS:PP> Group favorites / pinning
|
||||||
|
const LLGroupListItem* group_item1 = dynamic_cast<const LLGroupListItem*>(item1);
|
||||||
|
const LLGroupListItem* group_item2 = dynamic_cast<const LLGroupListItem*>(item2);
|
||||||
|
if (!group_item1 || !group_item2)
|
||||||
|
{
|
||||||
|
// Sorting doesn't matter, as we hit a separator that shouldn't be visible in this view
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1);
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
std::string name1 = group_item1->getGroupName();
|
std::string name1 = group_item1->getGroupName();
|
||||||
bool item1_shared = gAgent.isInGroup(group_item1->getGroupID(), true);
|
bool item1_shared = gAgent.isInGroup(group_item1->getGroupID(), true);
|
||||||
|
|
||||||
const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2);
|
// const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2); - <FS:PP> Group favorites / pinning
|
||||||
std::string name2 = group_item2->getGroupName();
|
std::string name2 = group_item2->getGroupName();
|
||||||
bool item2_shared = gAgent.isInGroup(group_item2->getGroupID(), true);
|
bool item2_shared = gAgent.isInGroup(group_item2->getGroupID(), true);
|
||||||
|
|
||||||
|
|
@ -134,6 +175,12 @@ LLGroupList::~LLGroupList()
|
||||||
{
|
{
|
||||||
if (mForAgent) gAgent.removeListener(this);
|
if (mForAgent) gAgent.removeListener(this);
|
||||||
if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
|
if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
if (mFavoritesChangedConnection.connected())
|
||||||
|
{
|
||||||
|
mFavoritesChangedConnection.disconnect();
|
||||||
|
}
|
||||||
|
// </FS:PP>
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLGroupList::enableForAgent(bool show_icons)
|
void LLGroupList::enableForAgent(bool show_icons)
|
||||||
|
|
@ -152,6 +199,11 @@ void LLGroupList::enableForAgent(bool show_icons)
|
||||||
registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2));
|
registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2));
|
||||||
enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2));
|
enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2));
|
||||||
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
mFavoritesChangedConnection = FSFavoriteGroups::getInstance()->setFavoritesChangedCallback(boost::bind(&LLGroupList::onFavoritesChanged, this));
|
||||||
|
enable_registrar.add("People.Groups.Visible", boost::bind(&LLGroupList::onContextMenuItemVisible, this, _2));
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml",
|
LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml",
|
||||||
gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
|
gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
|
||||||
if(context_menu)
|
if(context_menu)
|
||||||
|
|
@ -174,6 +226,13 @@ bool LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
||||||
|
|
||||||
if (mForAgent)
|
if (mForAgent)
|
||||||
{
|
{
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
LLPanel* selected_item = getSelectedItem();
|
||||||
|
if (dynamic_cast<LLGroupListSeparator*>(selected_item))
|
||||||
|
{
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
// </FS:PP>
|
||||||
LLToggleableMenu* context_menu = mContextMenuHandle.get();
|
LLToggleableMenu* context_menu = mContextMenuHandle.get();
|
||||||
if (context_menu && size() > 0)
|
if (context_menu && size() > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -234,24 +293,53 @@ void LLGroupList::refresh()
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
bool has_favorites = false;
|
||||||
|
bool has_non_favorites = false;
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
for(S32 i = 0; i < count; ++i)
|
for(S32 i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
id = gAgent.mGroups.at(i).mID;
|
id = gAgent.mGroups.at(i).mID;
|
||||||
const LLGroupData& group_data = gAgent.mGroups.at(i);
|
const LLGroupData& group_data = gAgent.mGroups.at(i);
|
||||||
if (have_filter && !findInsensitive(group_data.mName, mNameFilter))
|
if (have_filter && !findInsensitive(group_data.mName, mNameFilter))
|
||||||
continue;
|
continue;
|
||||||
addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile);
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
// addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile);
|
||||||
|
bool is_favorite = FSFavoriteGroups::getInstance()->isFavorite(id);
|
||||||
|
if (is_favorite)
|
||||||
|
{
|
||||||
|
has_favorites = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
has_non_favorites = true;
|
||||||
|
}
|
||||||
|
addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile, is_favorite);
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the list.
|
// Sort the list.
|
||||||
sort();
|
sort();
|
||||||
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
if (has_favorites && has_non_favorites && !have_filter)
|
||||||
|
{
|
||||||
|
addFavoritesSeparator();
|
||||||
|
}
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
// Add "none" to list at top if filter not set (what's the point of filtering "none"?).
|
// Add "none" to list at top if filter not set (what's the point of filtering "none"?).
|
||||||
// but only if some real groups exists. EXT-4838
|
// but only if some real groups exists. EXT-4838
|
||||||
if (!have_filter && count > 0 && mShowNone)
|
if (!have_filter && count > 0 && mShowNone)
|
||||||
{
|
{
|
||||||
std::string loc_none = LLTrans::getString("GroupsNone");
|
std::string loc_none = LLTrans::getString("GroupsNone");
|
||||||
addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
|
// <FS:PP> Group favorites / pinning
|
||||||
|
// addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
|
||||||
|
addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP, true, false);
|
||||||
|
// </FS:PP>
|
||||||
}
|
}
|
||||||
|
|
||||||
selectItemByUUID(highlight_id);
|
selectItemByUUID(highlight_id);
|
||||||
|
|
@ -298,13 +386,17 @@ void LLGroupList::setGroups(const std::map< std::string,LLUUID> group_list)
|
||||||
// PRIVATE Section
|
// PRIVATE Section
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile)
|
// <FS:PP> Group favorites / pinning
|
||||||
|
// void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile)
|
||||||
|
void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile, bool is_favorite)
|
||||||
|
// </FS:PP>
|
||||||
{
|
{
|
||||||
LLGroupListItem* item = new LLGroupListItem(mForAgent, mShowIcons);
|
LLGroupListItem* item = new LLGroupListItem(mForAgent, mShowIcons);
|
||||||
|
|
||||||
item->setGroupID(id);
|
item->setGroupID(id);
|
||||||
item->setName(name, mNameFilter);
|
item->setName(name, mNameFilter);
|
||||||
item->setGroupIconID(icon_id);
|
item->setGroupIconID(icon_id);
|
||||||
|
item->setFavorite(is_favorite); // <FS:PP> Group favorites / pinning
|
||||||
|
|
||||||
item->getChildView("info_btn")->setVisible( false);
|
item->getChildView("info_btn")->setVisible( false);
|
||||||
item->getChildView("profile_btn")->setVisible( false);
|
item->getChildView("profile_btn")->setVisible( false);
|
||||||
|
|
@ -390,6 +482,16 @@ bool LLGroupList::onContextMenuItemClick(const LLSD& userdata)
|
||||||
LLUrlAction::copyURLToClipboard(LLSLURL("group", selected_group, "about").getSLURLString());
|
LLUrlAction::copyURLToClipboard(LLSLURL("group", selected_group, "about").getSLURLString());
|
||||||
}
|
}
|
||||||
// </FS:Ansariel>
|
// </FS:Ansariel>
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
else if (action == "favorite")
|
||||||
|
{
|
||||||
|
FSFavoriteGroups::getInstance()->addFavorite(selected_group);
|
||||||
|
}
|
||||||
|
else if (action == "unfavorite")
|
||||||
|
{
|
||||||
|
FSFavoriteGroups::getInstance()->removeFavorite(selected_group);
|
||||||
|
}
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -412,9 +514,84 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
|
||||||
if (userdata.asString() == "call")
|
if (userdata.asString() == "call")
|
||||||
return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
|
return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
|
||||||
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
if (userdata.asString() == "favorite" || userdata.asString() == "unfavorite")
|
||||||
|
return real_group_selected; // Just in case
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
return real_group_selected;
|
return real_group_selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
bool LLGroupList::onContextMenuItemVisible(const LLSD& userdata)
|
||||||
|
{
|
||||||
|
std::string action = userdata.asString();
|
||||||
|
LLUUID selected_group_id = getSelectedUUID();
|
||||||
|
|
||||||
|
if (action == "favorite")
|
||||||
|
{
|
||||||
|
return selected_group_id.notNull() && !FSFavoriteGroups::getInstance()->isFavorite(selected_group_id);
|
||||||
|
}
|
||||||
|
else if (action == "unfavorite")
|
||||||
|
{
|
||||||
|
return selected_group_id.notNull() && FSFavoriteGroups::getInstance()->isFavorite(selected_group_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLGroupList::onFavoritesChanged()
|
||||||
|
{
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLGroupList::refreshFavorites()
|
||||||
|
{
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLGroupList::addFavoritesSeparator()
|
||||||
|
{
|
||||||
|
// Find the position to insert the separator (after the last favorite)
|
||||||
|
std::vector<LLPanel*> items;
|
||||||
|
getItems(items);
|
||||||
|
|
||||||
|
// Count favorite items to find where separator should go
|
||||||
|
S32 favorite_count = 0;
|
||||||
|
for (auto* panel : items)
|
||||||
|
{
|
||||||
|
LLGroupListItem* item = dynamic_cast<LLGroupListItem*>(panel);
|
||||||
|
if (item && item->isFavorite())
|
||||||
|
{
|
||||||
|
++favorite_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (favorite_count > 0)
|
||||||
|
{
|
||||||
|
LLGroupListSeparator* separator = new LLGroupListSeparator();
|
||||||
|
static const LLUUID SEPARATOR_UUID("00000000-0000-0000-0000-000000000001");
|
||||||
|
addItem(separator, SEPARATOR_UUID, ADD_BOTTOM, false);
|
||||||
|
sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* LLGroupListSeparator implementation */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
LLGroupListSeparator::LLGroupListSeparator()
|
||||||
|
: LLPanel()
|
||||||
|
{
|
||||||
|
buildFromFile("panel_group_list_separator.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLGroupListSeparator::postBuild()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* LLGroupListItem implementation */
|
/* LLGroupListItem implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@
|
||||||
|
|
||||||
#include "llgroupmgr.h"
|
#include "llgroupmgr.h"
|
||||||
|
|
||||||
|
#include <boost/signals2.hpp> // <FS:PP> Group favorites / pinning
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-updating list of agent groups.
|
* Auto-updating list of agent groups.
|
||||||
*
|
*
|
||||||
|
|
@ -72,14 +74,22 @@ public:
|
||||||
|
|
||||||
LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); }
|
LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); }
|
||||||
|
|
||||||
|
void refreshFavorites(); // <FS:PP> Group favorites / pinning
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setDirty(bool val = true) { mDirty = val; }
|
void setDirty(bool val = true) { mDirty = val; }
|
||||||
void refresh();
|
void refresh();
|
||||||
void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true);
|
// <FS:PP> Group favorites / pinning
|
||||||
|
// void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true);
|
||||||
|
void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true, bool is_favorite = false);
|
||||||
|
void addFavoritesSeparator();
|
||||||
|
void onFavoritesChanged();
|
||||||
|
// </FS:PP>
|
||||||
bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes
|
bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes
|
||||||
|
|
||||||
bool onContextMenuItemClick(const LLSD& userdata);
|
bool onContextMenuItemClick(const LLSD& userdata);
|
||||||
bool onContextMenuItemEnable(const LLSD& userdata);
|
bool onContextMenuItemEnable(const LLSD& userdata);
|
||||||
|
bool onContextMenuItemVisible(const LLSD& userdata); // <FS:PP> Group favorites / pinning
|
||||||
|
|
||||||
LLHandle<LLToggleableMenu> mContextMenuHandle;
|
LLHandle<LLToggleableMenu> mContextMenuHandle;
|
||||||
|
|
||||||
|
|
@ -91,12 +101,29 @@ private:
|
||||||
bool mShowNone;
|
bool mShowNone;
|
||||||
typedef std::map< std::string,LLUUID> group_map_t;
|
typedef std::map< std::string,LLUUID> group_map_t;
|
||||||
group_map_t mGroups;
|
group_map_t mGroups;
|
||||||
|
|
||||||
|
boost::signals2::connection mFavoritesChangedConnection; // <FS:PP> Group favorites / pinning
|
||||||
};
|
};
|
||||||
|
|
||||||
class LLButton;
|
class LLButton;
|
||||||
class LLGroupIconCtrl;
|
class LLGroupIconCtrl;
|
||||||
class LLTextBox;
|
class LLTextBox;
|
||||||
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
class LLGroupListSeparator : public LLPanel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLGroupListSeparator();
|
||||||
|
/*virtual*/ bool postBuild();
|
||||||
|
// Ignore all mouse interactions on the separator
|
||||||
|
/*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask) { return true; }
|
||||||
|
/*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask) { return true; }
|
||||||
|
/*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask) { return true; }
|
||||||
|
/*virtual*/ bool handleRightMouseUp(S32 x, S32 y, MASK mask) { return true; }
|
||||||
|
/*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask) { return true; }
|
||||||
|
};
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
class LLGroupListItem : public LLPanel
|
class LLGroupListItem : public LLPanel
|
||||||
, public LLGroupMgrObserver
|
, public LLGroupMgrObserver
|
||||||
{
|
{
|
||||||
|
|
@ -110,11 +137,13 @@ public:
|
||||||
|
|
||||||
const LLUUID& getGroupID() const { return mGroupID; }
|
const LLUUID& getGroupID() const { return mGroupID; }
|
||||||
const std::string& getGroupName() const { return mGroupName; }
|
const std::string& getGroupName() const { return mGroupName; }
|
||||||
|
bool isFavorite() const { return mIsFavorite; } // <FS:PP> Group favorites / pinning
|
||||||
|
|
||||||
void setName(const std::string& name, const std::string& highlight = LLStringUtil::null);
|
void setName(const std::string& name, const std::string& highlight = LLStringUtil::null);
|
||||||
void setGroupID(const LLUUID& group_id);
|
void setGroupID(const LLUUID& group_id);
|
||||||
void setGroupIconID(const LLUUID& group_icon_id);
|
void setGroupIconID(const LLUUID& group_icon_id);
|
||||||
void setGroupIconVisible(bool visible);
|
void setGroupIconVisible(bool visible);
|
||||||
|
void setFavorite(bool favorite) { mIsFavorite = favorite; } // <FS:PP> Group favorites / pinning
|
||||||
|
|
||||||
virtual void changed(LLGroupChange gc);
|
virtual void changed(LLGroupChange gc);
|
||||||
|
|
||||||
|
|
@ -137,6 +166,7 @@ private:
|
||||||
|
|
||||||
std::string mGroupName;
|
std::string mGroupName;
|
||||||
bool mForAgent;
|
bool mForAgent;
|
||||||
|
bool mIsFavorite{ false }; // <FS:PP> Group favorites / pinning
|
||||||
LLStyle::Params mGroupNameStyle;
|
LLStyle::Params mGroupNameStyle;
|
||||||
|
|
||||||
S32 mIconWidth;
|
S32 mIconWidth;
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@
|
||||||
#include "fscommon.h"
|
#include "fscommon.h"
|
||||||
#include "fscorehttputil.h"
|
#include "fscorehttputil.h"
|
||||||
#include "fsdata.h"
|
#include "fsdata.h"
|
||||||
|
#include "fsfavoritegroups.h" // <FS:PP> Group favorites / pinning
|
||||||
#include "fsfloatercontacts.h"
|
#include "fsfloatercontacts.h"
|
||||||
#include "fsfloaterimcontainer.h"
|
#include "fsfloaterimcontainer.h"
|
||||||
#include "fsfloaternearbychat.h"
|
#include "fsfloaternearbychat.h"
|
||||||
|
|
@ -3315,6 +3316,10 @@ bool idle_startup()
|
||||||
// Clean up the userauth stuff.
|
// Clean up the userauth stuff.
|
||||||
// LLUserAuth::getInstance()->reset();
|
// LLUserAuth::getInstance()->reset();
|
||||||
|
|
||||||
|
// <FS:PP> Group favorites / pinning
|
||||||
|
FSFavoriteGroups::getInstance()->loadFavorites();
|
||||||
|
// </FS:PP>
|
||||||
|
|
||||||
LLStartUp::setStartupState( STATE_STARTED );
|
LLStartUp::setStartupState( STATE_STARTED );
|
||||||
do_startup_frame();
|
do_startup_frame();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,12 @@
|
||||||
<string
|
<string
|
||||||
name="no_groups_msg"
|
name="no_groups_msg"
|
||||||
value="Looking for Groups to join? Try [secondlife:///app/search/groups Search]." />
|
value="Looking for Groups to join? Try [secondlife:///app/search/groups Search]." />
|
||||||
|
<string
|
||||||
|
name="favorite_label"
|
||||||
|
value="Pin" />
|
||||||
|
<string
|
||||||
|
name="unfavorite_label"
|
||||||
|
value="Unpin" />
|
||||||
<tab_container
|
<tab_container
|
||||||
follows="all"
|
follows="all"
|
||||||
height="390"
|
height="390"
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,32 @@
|
||||||
function="People.Groups.Enable"
|
function="People.Groups.Enable"
|
||||||
parameter="call" />
|
parameter="call" />
|
||||||
</menu_item_call>
|
</menu_item_call>
|
||||||
|
<menu_item_call
|
||||||
|
label="Pin group"
|
||||||
|
name="Favorite">
|
||||||
|
<menu_item_call.on_click
|
||||||
|
function="People.Groups.Action"
|
||||||
|
parameter="favorite" />
|
||||||
|
<menu_item_call.on_enable
|
||||||
|
function="People.Groups.Enable"
|
||||||
|
parameter="favorite" />
|
||||||
|
<menu_item_call.on_visible
|
||||||
|
function="People.Groups.Visible"
|
||||||
|
parameter="favorite" />
|
||||||
|
</menu_item_call>
|
||||||
|
<menu_item_call
|
||||||
|
label="Unpin group"
|
||||||
|
name="Unfavorite">
|
||||||
|
<menu_item_call.on_click
|
||||||
|
function="People.Groups.Action"
|
||||||
|
parameter="unfavorite" />
|
||||||
|
<menu_item_call.on_enable
|
||||||
|
function="People.Groups.Enable"
|
||||||
|
parameter="unfavorite" />
|
||||||
|
<menu_item_call.on_visible
|
||||||
|
function="People.Groups.Visible"
|
||||||
|
parameter="unfavorite" />
|
||||||
|
</menu_item_call>
|
||||||
<menu_item_separator />
|
<menu_item_separator />
|
||||||
<menu_item_call
|
<menu_item_call
|
||||||
label="Leave"
|
label="Leave"
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
<button
|
<button
|
||||||
top="2"
|
top="2"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
label="IM/Call"
|
label="IM/Call"
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
right="-1"
|
right="-1"
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
<button
|
<button
|
||||||
top_delta="25"
|
top_delta="25"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
label="Profile"
|
label="Profile"
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
name="info_btn"
|
name="info_btn"
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
<button
|
<button
|
||||||
top_delta="25"
|
top_delta="25"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
label="Group Titles"
|
label="Group Titles"
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
name="titles_btn"
|
name="titles_btn"
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
<button
|
<button
|
||||||
top_delta="25"
|
top_delta="25"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
label="Activate"
|
label="Activate"
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
name="activate_btn"
|
name="activate_btn"
|
||||||
|
|
@ -83,15 +83,24 @@
|
||||||
<button
|
<button
|
||||||
top_delta="25"
|
top_delta="25"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
|
label="Pin"
|
||||||
|
layout="topleft"
|
||||||
|
name="favorite_btn"
|
||||||
|
tool_tip="Add or remove group from favorites"
|
||||||
|
width="80" />
|
||||||
|
<button
|
||||||
|
top_delta="25"
|
||||||
|
follows="top|right"
|
||||||
|
height="20"
|
||||||
label="Leave"
|
label="Leave"
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
name="leave_btn"
|
name="leave_btn"
|
||||||
width="80" />
|
width="80" />
|
||||||
<button
|
<button
|
||||||
top_delta="35"
|
top_delta="31"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
label="Create..."
|
label="Create..."
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
name="create_btn"
|
name="create_btn"
|
||||||
|
|
@ -99,7 +108,7 @@
|
||||||
<button
|
<button
|
||||||
top_delta="25"
|
top_delta="25"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
label="Search..."
|
label="Search..."
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
name="search_btn"
|
name="search_btn"
|
||||||
|
|
@ -107,7 +116,7 @@
|
||||||
<button
|
<button
|
||||||
top_delta="25"
|
top_delta="25"
|
||||||
follows="top|right"
|
follows="top|right"
|
||||||
height="22"
|
height="20"
|
||||||
label="Invite..."
|
label="Invite..."
|
||||||
layout="topleft"
|
layout="topleft"
|
||||||
name="invite_btn"
|
name="invite_btn"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||||
|
<panel
|
||||||
|
follows="left|top|right"
|
||||||
|
height="10"
|
||||||
|
layout="topleft"
|
||||||
|
left="0"
|
||||||
|
name="group_list_separator"
|
||||||
|
top="0"
|
||||||
|
width="300">
|
||||||
|
<view_border
|
||||||
|
bevel_style="none"
|
||||||
|
follows="left|right|top"
|
||||||
|
height="1"
|
||||||
|
layout="topleft"
|
||||||
|
left="5"
|
||||||
|
name="separator_line"
|
||||||
|
right="-5"
|
||||||
|
top="5" />
|
||||||
|
</panel>
|
||||||
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
<string name="no_friends" value="Brak znajomych" />
|
<string name="no_friends" value="Brak znajomych" />
|
||||||
<string name="no_filtered_groups_msg" value="Nie znaleziono grup zawierających frazę "[SEARCH_TERM]"." />
|
<string name="no_filtered_groups_msg" value="Nie znaleziono grup zawierających frazę "[SEARCH_TERM]"." />
|
||||||
<string name="no_groups_msg" value="Szukasz grup, do jakich można by dołączyć? Spróbuj [secondlife:///app/search/groups wyszukać]." />
|
<string name="no_groups_msg" value="Szukasz grup, do jakich można by dołączyć? Spróbuj [secondlife:///app/search/groups wyszukać]." />
|
||||||
|
<string name="favorite_label" value="Przypnij" />
|
||||||
|
<string name="unfavorite_label" value="Odepnij" />
|
||||||
<tab_container name="friends_and_groups">
|
<tab_container name="friends_and_groups">
|
||||||
<panel label="Znajomi" name="friends_panel" />
|
<panel label="Znajomi" name="friends_panel" />
|
||||||
<panel label="Grupy" name="groups_panel" />
|
<panel label="Grupy" name="groups_panel" />
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,7 @@
|
||||||
<menu_item_call label="Kopiuj SLurl do schowka" name="Copy SLurl to clipboard"/>
|
<menu_item_call label="Kopiuj SLurl do schowka" name="Copy SLurl to clipboard"/>
|
||||||
<menu_item_call label="Czat" name="Chat"/>
|
<menu_item_call label="Czat" name="Chat"/>
|
||||||
<menu_item_call label="Rozmowa głosowa" name="Call"/>
|
<menu_item_call label="Rozmowa głosowa" name="Call"/>
|
||||||
|
<menu_item_call label="Przypnij grupę" name="Favorite" />
|
||||||
|
<menu_item_call label="Odepnij grupę" name="Unfavorite" />
|
||||||
<menu_item_call label="Opuść" name="Leave"/>
|
<menu_item_call label="Opuść" name="Leave"/>
|
||||||
</toggleable_menu>
|
</toggleable_menu>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
<button label="Profil" name="info_btn"/>
|
<button label="Profil" name="info_btn"/>
|
||||||
<button label="Tytuły grup" name="titles_btn"/>
|
<button label="Tytuły grup" name="titles_btn"/>
|
||||||
<button label="Aktywuj" name="activate_btn"/>
|
<button label="Aktywuj" name="activate_btn"/>
|
||||||
|
<button label="Przypnij" name="favorite_btn" tool_tip="Dodaj lub usuń grupę z ulubionych" />
|
||||||
<button label="Opuść" name="leave_btn"/>
|
<button label="Opuść" name="leave_btn"/>
|
||||||
<button label="Utwórz..." name="create_btn"/>
|
<button label="Utwórz..." name="create_btn"/>
|
||||||
<button label="Szukaj..." name="search_btn"/>
|
<button label="Szukaj..." name="search_btn"/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue