summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/commands.xml10
-rw-r--r--indra/newview/app_settings/settings.xml19
-rw-r--r--indra/newview/llappearancemgr.cpp18
-rw-r--r--indra/newview/llappviewer.cpp6
-rw-r--r--indra/newview/llcontrolavatar.cpp10
-rw-r--r--indra/newview/llconversationlog.cpp4
-rw-r--r--indra/newview/llface.cpp2
-rw-r--r--indra/newview/llfavoritesbar.cpp70
-rw-r--r--indra/newview/llfavoritesbar.h9
-rw-r--r--indra/newview/llfloaterconversationpreview.cpp7
-rw-r--r--indra/newview/llfloaterconversationpreview.h1
-rw-r--r--indra/newview/llfloaterforgetuser.cpp154
-rw-r--r--indra/newview/llfloaterforgetuser.h46
-rw-r--r--indra/newview/llfloatergroupinvite.cpp11
-rw-r--r--indra/newview/llfloatergroupinvite.h2
-rw-r--r--indra/newview/llfloaterland.cpp2
-rw-r--r--indra/newview/llfloaterlinkreplace.cpp85
-rw-r--r--indra/newview/llfloaterlinkreplace.h1
-rw-r--r--indra/newview/llfloaterpreference.cpp14
-rw-r--r--indra/newview/llfloaterpreference.h2
-rw-r--r--indra/newview/llimprocessing.cpp2
-rw-r--r--indra/newview/llimview.cpp11
-rw-r--r--indra/newview/llimview.h1
-rw-r--r--indra/newview/llinventorypanel.cpp1
-rw-r--r--indra/newview/lllogchat.cpp47
-rw-r--r--indra/newview/lllogchat.h3
-rw-r--r--indra/newview/llloginhandler.cpp7
-rw-r--r--indra/newview/llmediactrl.cpp14
-rw-r--r--indra/newview/llmediactrl.h1
-rw-r--r--indra/newview/llmoveview.cpp2
-rw-r--r--indra/newview/llpanelclassified.cpp1
-rw-r--r--indra/newview/llpanelgrouproles.cpp2
-rw-r--r--indra/newview/llpanellogin.cpp426
-rw-r--r--indra/newview/llpanellogin.h17
-rw-r--r--indra/newview/llpanelnearbymedia.cpp23
-rw-r--r--indra/newview/llpanelplaces.cpp6
-rw-r--r--indra/newview/llpanelvolumepulldown.cpp2
-rw-r--r--indra/newview/llsecapi.h46
-rw-r--r--indra/newview/llsechandler_basic.cpp176
-rw-r--r--indra/newview/llsechandler_basic.h61
-rw-r--r--indra/newview/llstartup.cpp46
-rw-r--r--indra/newview/lltoastalertpanel.cpp72
-rw-r--r--indra/newview/lltoastalertpanel.h5
-rw-r--r--indra/newview/lltoastnotifypanel.cpp23
-rw-r--r--indra/newview/lltoastnotifypanel.h2
-rw-r--r--indra/newview/lltoastpanel.cpp108
-rw-r--r--indra/newview/lltoastpanel.h19
-rw-r--r--indra/newview/lltool.cpp6
-rw-r--r--indra/newview/lltool.h1
-rw-r--r--indra/newview/lltooldraganddrop.cpp2
-rw-r--r--indra/newview/lltoolmgr.cpp2
-rw-r--r--indra/newview/lltoolpie.cpp5
-rw-r--r--indra/newview/lltoolpie.h1
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewerinventory.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp14
-rw-r--r--indra/newview/llviewermedia.h2
-rw-r--r--indra/newview/llviewermenu.cpp27
-rw-r--r--indra/newview/llviewerparcelaskplay.cpp301
-rw-r--r--indra/newview/llviewerparcelaskplay.h89
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.cpp53
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.h3
-rw-r--r--indra/newview/llviewerparcelmgr.cpp57
-rw-r--r--indra/newview/llviewerparcelmgr.h3
-rw-r--r--indra/newview/llviewerstats.cpp21
-rw-r--r--indra/newview/llviewerwindow.cpp48
-rw-r--r--indra/newview/llviewerwindow.h2
-rw-r--r--indra/newview/pipeline.cpp6
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/xui/de/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_textures.xml137
-rw-r--r--indra/newview/skins/default/xui/en/floater_forget_user.xml40
-rw-r--r--indra/newview/skins/default/xui/en/floater_merchant_outbox.xml156
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_trash.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml9
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml48
-rw-r--r--indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_classified.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml54
-rw-r--r--indra/newview/skins/default/xui/en/panel_outbox_inventory.xml31
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_info.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml23
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_chat.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml45
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_about_land.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_setup.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_about_land.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_about_land.xml6
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_about_land.xml4
-rw-r--r--indra/newview/skins/default/xui/ru/floater_about_land.xml10
-rw-r--r--indra/newview/skins/default/xui/ru/panel_preferences_chat.xml6
-rw-r--r--indra/newview/skins/default/xui/ru/panel_preferences_setup.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/floater_about_land.xml4
-rw-r--r--indra/newview/tests/llsecapi_test.cpp9
105 files changed, 2276 insertions, 600 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 694e89ab99..6089162190 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -246,6 +246,7 @@ set(viewer_SOURCE_FILES
llfloaterexperiences.cpp
llfloaterflickr.cpp
llfloaterfonttest.cpp
+ llfloaterforgetuser.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
llfloatergotoline.cpp
@@ -663,6 +664,7 @@ set(viewer_SOURCE_FILES
llviewerobject.cpp
llviewerobjectlist.cpp
llvieweroctree.cpp
+ llviewerparcelaskplay.cpp
llviewerparcelmedia.cpp
llviewerparcelmediaautoplay.cpp
llviewerparcelmgr.cpp
@@ -871,6 +873,7 @@ set(viewer_HEADER_FILES
llfloaterexperiences.h
llfloaterflickr.h
llfloaterfonttest.h
+ llfloaterforgetuser.h
llfloatergesture.h
llfloatergodtools.h
llfloatergotoline.h
@@ -1282,6 +1285,7 @@ set(viewer_HEADER_FILES
llviewerobject.h
llviewerobjectlist.h
llvieweroctree.h
+ llviewerparcelaskplay.h
llviewerparcelmedia.h
llviewerparcelmediaautoplay.h
llviewerparcelmgr.h
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index cab0c523b2..dae397a3b6 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -150,16 +150,6 @@
is_running_function="Floater.IsOpen"
is_running_parameters="moveview"
/>
- <command name="outbox"
- available_in_toybox="false"
- icon="Command_Outbox_Icon"
- label_ref="Command_Outbox_Label"
- tooltip_ref="Command_Outbox_Tooltip"
- execute_function="Floater.ToggleOrBringToFront"
- execute_parameters="outbox"
- is_running_function="Floater.IsOpen"
- is_running_parameters="outbox"
- />
<command name="people"
available_in_toybox="true"
icon="Command_People_Icon"
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index b4919c6e48..68e39899f0 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4913,7 +4913,7 @@
<key>InventoryOutboxDisplayBoth</key>
<map>
<key>Comment</key>
- <string>Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string>
+ <string>(Deprecated) Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -7494,11 +7494,11 @@
<key>ParcelMediaAutoPlayEnable</key>
<map>
<key>Comment</key>
- <string>Auto play parcel media when available</string>
+ <string>Auto play parcel media when available. 0 - Do not autoplay; 1- Autoplay; 2 - Ask</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>S32</string>
<key>Value</key>
<integer>1</integer>
</map>
@@ -8434,6 +8434,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RememberUser</key>
+ <map>
+ <key>Comment</key>
+ <string>Keep user name for next login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RememberPassword</key>
<map>
<key>Comment</key>
@@ -9276,7 +9287,7 @@
<key>RenderShadowResolutionScale</key>
<map>
<key>Comment</key>
- <string>Scale of shadow map resolution vs. screen resolution</string>
+ <string>Scale of shadow map resolution vs. screen resolution (only positivie values are allowed)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 22bcbad7da..18c0cedba8 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1713,6 +1713,24 @@ void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_
LLInventoryModel::item_array_t* items;
LLSD contents = LLSD::emptyArray();
gInventory.getDirectDescendentsOf(src_id, cats, items);
+ if (!cats || !items)
+ {
+ // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean
+ // that the cat just doesn't have any items or subfolders).
+ LLViewerInventoryCategory* category = gInventory.getCategory(src_id);
+ if (category)
+ {
+ LL_WARNS() << "Category '" << category->getName() << "' descendents corrupted, linking content failed." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "Category could not be retrieved, linking content failed." << LL_ENDL;
+ }
+ llassert(cats != NULL && items != NULL);
+
+ return;
+ }
+
LL_INFOS() << "copying " << items->size() << " items" << LL_ENDL;
for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
iter != items->end();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 12a459b2b8..2a928a47a2 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -68,6 +68,7 @@
#include "llviewerwindow.h"
#include "llviewerdisplay.h"
#include "llviewermedia.h"
+#include "llviewerparcelaskplay.h"
#include "llviewerparcelmedia.h"
#include "llviewermediafocus.h"
#include "llviewermessage.h"
@@ -1938,6 +1939,11 @@ bool LLAppViewer::cleanup()
{
gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
LL_INFOS() << "Saved settings" << LL_ENDL;
+
+ if (LLViewerParcelAskPlay::instanceExists())
+ {
+ LLViewerParcelAskPlay::getInstance()->saveSettings();
+ }
}
std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 92eeebd705..f0682dc1ba 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -171,7 +171,10 @@ void LLControlAvatar::matchVolumeTransform()
if (attached_av)
{
LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp);
- setPositionAgent(mRootVolp->getRenderPosition());
+ if (getRegion() && !isDead())
+ {
+ setPositionAgent(mRootVolp->getRenderPosition());
+ }
attach->updateWorldPRSParent();
LLVector3 joint_pos = attach->getWorldPosition();
LLQuaternion joint_rot = attach->getWorldRotation();
@@ -227,7 +230,10 @@ void LLControlAvatar::matchVolumeTransform()
#endif
setRotation(bind_rot*obj_rot);
mRoot->setWorldRotation(bind_rot*obj_rot);
- setPositionAgent(vol_pos);
+ if (getRegion() && !isDead())
+ {
+ setPositionAgent(vol_pos);
+ }
mRoot->setPosition(vol_pos + mPositionConstraintFixup);
F32 global_scale = gSavedSettings.getF32("AnimatedObjectsGlobalScale");
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index 9ccf9b98f7..ba6b251d58 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -486,7 +486,7 @@ bool LLConversationLog::saveToFile(const std::string& filename)
(S32)conv_it->getConversationType(),
(S32)0,
(S32)conv_it->hasOfflineMessages(),
- conv_it->getConversationName().c_str(),
+ LLURI::escape(conv_it->getConversationName()).c_str(),
participant_id.c_str(),
conversation_id.c_str(),
LLURI::escape(conv_it->getHistoryFileName()).c_str());
@@ -541,7 +541,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
params.time(LLUnits::Seconds::fromValue(time))
.conversation_type((SessionType)stype)
.has_offline_ims(has_offline_ims)
- .conversation_name(conv_name_buffer)
+ .conversation_name(LLURI::unescape(conv_name_buffer))
.participant_id(LLUUID(part_id_buffer))
.session_id(LLUUID(conv_id_buffer))
.history_filename(LLURI::unescape(history_file_name));
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 912bde9986..1d782cdabe 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -462,7 +462,7 @@ void LLFace::setTextureIndex(U8 index)
}
else
{
- if (mDrawInfo && !mDrawInfo->mTextureList.empty())
+ if (mDrawInfo && mDrawInfo->mTextureList.size() <= 1)
{
LL_ERRS() << "Face with no texture index references indexed texture draw info." << LL_ENDL;
}
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 5b4b7789b4..17952349dc 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -1493,19 +1493,25 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
}
// static
-std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
+std::string LLFavoritesOrderStorage::getStoredFavoritesFilename(const std::string &grid)
{
- std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
+ std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
return (user_dir.empty() ? ""
: gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
"stored_favorites_"
- + LLGridManager::getInstance()->getGrid()
+ + grid
+ ".xml")
);
}
// static
+std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
+{
+ return getStoredFavoritesFilename(LLGridManager::getInstance()->getGrid());
+}
+
+// static
void LLFavoritesOrderStorage::destroyClass()
{
LLFavoritesOrderStorage::instance().cleanup();
@@ -1602,6 +1608,64 @@ void LLFavoritesOrderStorage::load()
}
}
+// static
+void LLFavoritesOrderStorage::removeFavoritesRecordOfUser(const std::string &user, const std::string &grid)
+{
+ std::string filename = getStoredFavoritesFilename(grid);
+ if (!filename.empty())
+ {
+ LLSD fav_llsd;
+ llifstream file;
+ file.open(filename.c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(fav_llsd, file);
+ file.close();
+
+ // Note : use the "John Doe" and not the "john.doe" version of the name.
+ // See saveFavoritesSLURLs() here above for the reason why.
+ if (fav_llsd.has(user))
+ {
+ LLSD user_llsd = fav_llsd[user];
+
+ if ((user_llsd.beginArray() != user_llsd.endArray()) && user_llsd.beginArray()->has("id"))
+ {
+ for (LLSD::array_iterator iter = user_llsd.beginArray(); iter != user_llsd.endArray(); ++iter)
+ {
+ LLSD value;
+ value["id"] = iter->get("id").asUUID();
+ iter->assign(value);
+ }
+ fav_llsd[user] = user_llsd;
+ llofstream file;
+ file.open(filename.c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(fav_llsd, file);
+ file.close();
+ }
+ }
+ else
+ {
+ LL_INFOS("FavoritesBar") << "Removed favorites for " << user << LL_ENDL;
+ fav_llsd.erase(user);
+ }
+ }
+
+ llofstream out_file;
+ out_file.open(filename.c_str());
+ if (out_file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(fav_llsd, out_file);
+ LL_INFOS("FavoritesBar") << "saved favorites to '" << filename << "' "
+ << LL_ENDL;
+ out_file.close();
+ }
+ }
+ }
+}
+
+// static
void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
{
std::string filename = getStoredFavoritesFilename();
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index cac32c7f2a..d93161fd7a 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -208,9 +208,15 @@ public:
* @see cleanup()
*/
static void destroyClass();
+ static std::string getStoredFavoritesFilename(const std::string &grid);
static std::string getStoredFavoritesFilename();
static std::string getSavedOrderFileName();
+ // Remove record of specified user's favorites from file on disk.
+ static void removeFavoritesRecordOfUser(const std::string &user, const std::string &grid);
+ // Remove record of current user's favorites from file on disk.
+ static void removeFavoritesRecordOfUser();
+
BOOL saveFavoritesRecord(bool pref_changed = false);
void showFavoritesOnLoginChanged(BOOL show);
@@ -232,9 +238,6 @@ private:
void load();
- // Remove record of current user's favorites from file on disk.
- void removeFavoritesRecordOfUser();
-
void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark);
void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl);
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index 66198b3bf6..37186ce3d5 100644
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -50,6 +50,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i
mShowHistory(false),
mMessages(NULL),
mHistoryThreadsBusy(false),
+ mIsGroup(false),
mOpened(false)
{
}
@@ -75,6 +76,7 @@ BOOL LLFloaterConversationPreview::postBuild()
{
name = conv->getConversationName();
file = conv->getHistoryFileName();
+ mIsGroup = (LLIMModel::LLIMSession::GROUP_SESSION == conv->getConversationType());
}
else
{
@@ -82,6 +84,10 @@ BOOL LLFloaterConversationPreview::postBuild()
file = "chat";
}
mChatHistoryFileName = file;
+ if (mIsGroup)
+ {
+ mChatHistoryFileName += GROUP_CHAT_SUFFIX;
+ }
LLStringUtil::format_map_t args;
args["[NAME]"] = name;
std::string title = getString("Title", args);
@@ -145,6 +151,7 @@ void LLFloaterConversationPreview::onOpen(const LLSD& key)
LLSD load_params;
load_params["load_all_history"] = true;
load_params["cut_off_todays_date"] = false;
+ load_params["is_group"] = mIsGroup;
// The temporary message list with "Loading..." text
// Will be deleted upon loading completion in setPages() method
diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h
index a8dbbc9ffe..7ca4ee6945 100644
--- a/indra/newview/llfloaterconversationpreview.h
+++ b/indra/newview/llfloaterconversationpreview.h
@@ -66,6 +66,7 @@ private:
bool mShowHistory;
bool mHistoryThreadsBusy;
bool mOpened;
+ bool mIsGroup;
};
#endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */
diff --git a/indra/newview/llfloaterforgetuser.cpp b/indra/newview/llfloaterforgetuser.cpp
new file mode 100644
index 0000000000..5659cb2f79
--- /dev/null
+++ b/indra/newview/llfloaterforgetuser.cpp
@@ -0,0 +1,154 @@
+/**
+ * @file llfloaterforgetuser.cpp
+ * @brief LLFloaterForgetUser class definition.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, Linden Research, 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterforgetuser.h"
+
+#include "llcheckboxctrl.h"
+#include "llfavoritesbar.h"
+#include "llpanellogin.h" // for helper function getUserName() and to repopulate list if nessesary
+#include "llscrolllistctrl.h"
+#include "llsecapi.h"
+#include "llviewernetwork.h"
+
+
+LLFloaterForgetUser::LLFloaterForgetUser(const LLSD &key)
+ : LLFloater("floater_forget_user"),
+ mLoginPanelDirty(false)
+{
+
+}
+
+LLFloaterForgetUser::~LLFloaterForgetUser()
+{
+ if (mLoginPanelDirty)
+ {
+ LLPanelLogin::resetFields();
+ }
+}
+
+BOOL LLFloaterForgetUser::postBuild()
+{
+ // Note, storage works per grid, watever is selected currently in login screen or logged in.
+ // Since login screen can change grid, store the value.
+ mGrid = LLGridManager::getInstance()->getGrid();
+
+ LLScrollListCtrl *scroll_list = getChild<LLScrollListCtrl>("user_list");
+ if (gSecAPIHandler->hasCredentialMap("login_list", mGrid))
+ {
+ LLSecAPIHandler::credential_map_t credencials;
+ gSecAPIHandler->loadCredentialMap("login_list", mGrid, credencials);
+
+ LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin();
+ LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end();
+ while (cr_iter != cr_end)
+ {
+ if (cr_iter->second.notNull()) // basic safety
+ {
+ LLScrollListItem::Params item_params;
+ item_params.value(cr_iter->first);
+ item_params.columns.add()
+ .value(LLPanelLogin::getUserName(cr_iter->second))
+ .column("user")
+ .font(LLFontGL::getFontSansSerifSmall());
+ scroll_list->addRow(item_params, ADD_BOTTOM);
+ }
+ cr_iter++;
+ }
+ scroll_list->selectFirstItem();
+ }
+ else
+ {
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
+ if (cred.notNull())
+ {
+ LLScrollListItem::Params item_params;
+ item_params.value(cred->userID());
+ item_params.columns.add()
+ .value(LLPanelLogin::getUserName(cred))
+ .column("user")
+ .font(LLFontGL::getFontSansSerifSmall());
+ scroll_list->addRow(item_params, ADD_BOTTOM);
+ scroll_list->selectFirstItem();
+ }
+ }
+
+ bool enable_button = scroll_list->getFirstSelectedIndex() != -1;
+ getChild<LLView>("delete_data")->setEnabled(enable_button);
+ LLButton *button = getChild<LLButton>("forget");
+ button->setEnabled(enable_button);
+ button->setCommitCallback(boost::bind(&LLFloaterForgetUser::onForgetClicked, this));
+
+ return TRUE;
+}
+
+void LLFloaterForgetUser::onForgetClicked()
+{
+ mLoginPanelDirty = true;
+ LLScrollListCtrl *scroll_list = getChild<LLScrollListCtrl>("user_list");
+ std::string user_key = scroll_list->getSelectedValue();
+
+ // remove creds
+ gSecAPIHandler->removeFromCredentialMap("login_list", mGrid, user_key);
+
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
+ if (cred.notNull() && cred->userID() == user_key)
+ {
+ gSecAPIHandler->deleteCredential(cred);
+ }
+
+ // Clean data
+ LLCheckBoxCtrl *chk_box = getChild<LLCheckBoxCtrl>("delete_data");
+ BOOL delete_data = chk_box->getValue();
+ if (delete_data)
+ {
+ // key is edentical to one we use for name of user's folder
+ std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + user_key;
+ gDirUtilp->deleteDirAndContents(user_path);
+
+ // Clean favorites, label is edentical to username
+ LLFavoritesOrderStorage::removeFavoritesRecordOfUser(scroll_list->getSelectedItemLabel(), mGrid);
+
+ // Note: we do not clean user-related files from cache because there are id dependent (inventory)
+ // files and cache has separate cleaning mechanism either way.
+ // Also this only cleans user from current grid, not all of them.
+ }
+
+
+ // Update UI
+ scroll_list->deleteSelectedItems();
+ scroll_list->selectFirstItem();
+ if (scroll_list->getFirstSelectedIndex() == -1)
+ {
+ LLButton *button = getChild<LLButton>("forget");
+ button->setEnabled(false);
+ chk_box->setEnabled(false);
+ }
+}
+
+
diff --git a/indra/newview/llfloaterforgetuser.h b/indra/newview/llfloaterforgetuser.h
new file mode 100644
index 0000000000..119aece2d1
--- /dev/null
+++ b/indra/newview/llfloaterforgetuser.h
@@ -0,0 +1,46 @@
+/**
+ * @file llfloaterforgetuser.h
+ * @brief LLFloaterForgetUser class declaration.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, Linden Research, 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERFORGETUSER_H
+#define LL_LLFLOATERFORGETUSER_H
+
+#include "llfloater.h"
+
+class LLFloaterForgetUser : public LLFloater
+{
+public:
+ LLFloaterForgetUser(const LLSD &key);
+ ~LLFloaterForgetUser();
+
+ BOOL postBuild();
+ void onForgetClicked();
+
+private:
+ bool mLoginPanelDirty;
+ std::string mGrid;
+};
+
+#endif
diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp
index 7fdba8734a..30c90ac184 100644
--- a/indra/newview/llfloatergroupinvite.cpp
+++ b/indra/newview/llfloatergroupinvite.cpp
@@ -108,7 +108,7 @@ LLFloaterGroupInvite::~LLFloaterGroupInvite()
}
// static
-void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agent_ids)
+void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agent_ids, bool request_update)
{
const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
S32 floater_header_size = floater_params.header_height;
@@ -126,9 +126,12 @@ void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agen
group_id,
(LLFloaterGroupInvite*)NULL);
- // refresh group information
- gAgent.sendAgentDataUpdateRequest();
- LLGroupMgr::getInstance()->clearGroupData(group_id);
+ if (request_update)
+ {
+ // refresh group information
+ gAgent.sendAgentDataUpdateRequest();
+ LLGroupMgr::getInstance()->clearGroupData(group_id);
+ }
if (!fgi)
diff --git a/indra/newview/llfloatergroupinvite.h b/indra/newview/llfloatergroupinvite.h
index f6a3ca5550..657e5711f0 100644
--- a/indra/newview/llfloatergroupinvite.h
+++ b/indra/newview/llfloatergroupinvite.h
@@ -37,7 +37,7 @@ class LLFloaterGroupInvite
public:
virtual ~LLFloaterGroupInvite();
- static void showForGroup(const LLUUID &group_id, uuid_vec_t *agent_ids = NULL);
+ static void showForGroup(const LLUUID &group_id, uuid_vec_t *agent_ids = NULL, bool request_update = true);
protected:
LLFloaterGroupInvite(const LLUUID& group_id = LLUUID::null);
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 3098c6d118..d8f4360142 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2209,7 +2209,7 @@ void LLPanelLandOptions::refreshSearch()
// effort to reduce search spam from small parcels. See also
// the search crawler "grid-crawl.py" in secondlife.com/doc/app/search/ JC
const S32 MIN_PARCEL_AREA_FOR_SEARCH = 128;
- bool large_enough = parcel->getArea() > MIN_PARCEL_AREA_FOR_SEARCH;
+ bool large_enough = parcel->getArea() >= MIN_PARCEL_AREA_FOR_SEARCH;
if (large_enough)
{
if (can_change)
diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index 10cce3bd22..595d584799 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -32,6 +32,8 @@
#include "llagent.h"
#include "llappearancemgr.h"
#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llnotifications.h"
#include "lltextbox.h"
#include "llviewercontrol.h"
@@ -142,37 +144,72 @@ void LLFloaterLinkReplace::onStartClicked()
LL_WARNS() << "Cannot replace. Source and target are identical." << LL_ENDL;
return;
}
+
+ const LLUUID& source_item_id = gInventory.getLinkedItemID(mSourceUUID);
+ LLViewerInventoryItem *source_item = gInventory.getItem(source_item_id);
+ const LLUUID& target_item_id = gInventory.getLinkedItemID(mTargetUUID);
+ LLViewerInventoryItem *target_item = gInventory.getItem(target_item_id);
- LLInventoryModel::cat_array_t cat_array;
- LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
- gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
- cat_array,
- mRemainingInventoryItems,
- LLInventoryModel::INCLUDE_TRASH,
- is_linked_item_match);
- LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
- if (mRemainingInventoryItems.size() > 0)
+ LLNotification::Params params("ConfirmReplaceLink");
+ params.functor.function(boost::bind(&LLFloaterLinkReplace::onStartClickedResponse, this, _1, _2));
+ if (source_item && source_item->isWearableType() && source_item->getWearableType() <= LLWearableType::WT_EYES)
{
- LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
- if (target_item)
+ if(target_item && target_item->isWearableType() && source_item->getWearableType() == target_item->getWearableType())
{
- mRemainingItems = (U32)mRemainingInventoryItems.size();
-
- LLStringUtil::format_map_t args;
- args["NUM"] = llformat("%d", mRemainingItems);
- mStatusText->setText(getString("ItemsRemaining", args));
-
- mStartBtn->setEnabled(FALSE);
- mRefreshBtn->setEnabled(FALSE);
-
- mEventTimer.start();
- tick();
+ LLNotifications::instance().forceResponse(params, 0);
}
else
{
- mStatusText->setText(getString("TargetNotFound"));
- LL_WARNS() << "Link replace target not found." << LL_ENDL;
+ LLSD args;
+ args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType());
+ params.substitutions(args);
+ LLNotifications::instance().add(params);
+ }
+ }
+ else
+ {
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+}
+
+void LLFloaterLinkReplace::onStartClickedResponse(const LLSD& notification, const LLSD& response)
+{
+
+ if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
+ {
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+ cat_array,
+ mRemainingInventoryItems,
+ LLInventoryModel::INCLUDE_TRASH,
+ is_linked_item_match);
+ LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
+
+ if (mRemainingInventoryItems.size() > 0)
+ {
+ LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
+ if (target_item)
+ {
+ mRemainingItems = (U32)mRemainingInventoryItems.size();
+
+ LLStringUtil::format_map_t args;
+ args["NUM"] = llformat("%d", mRemainingItems);
+ mStatusText->setText(getString("ItemsRemaining", args));
+
+ mStartBtn->setEnabled(FALSE);
+ mRefreshBtn->setEnabled(FALSE);
+
+ mEventTimer.start();
+ tick();
+ }
+ else
+ {
+ mStatusText->setText(getString("TargetNotFound"));
+ LL_WARNS() << "Link replace target not found." << LL_ENDL;
+ }
}
}
}
diff --git a/indra/newview/llfloaterlinkreplace.h b/indra/newview/llfloaterlinkreplace.h
index dd5c301206..060773f93e 100644
--- a/indra/newview/llfloaterlinkreplace.h
+++ b/indra/newview/llfloaterlinkreplace.h
@@ -94,6 +94,7 @@ public:
private:
void checkEnableStart();
void onStartClicked();
+ void onStartClickedResponse(const LLSD& notification, const LLSD& response);
void decreaseOpenItemCount();
void updateFoundLinks();
void processBatch(LLInventoryModel::item_array_t items);
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 27a597a631..b48495b5b2 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -419,6 +419,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.TranslationSettings", boost::bind(&LLFloaterPreference::onClickTranslationSettings, this));
mCommitCallbackRegistrar.add("Pref.AutoReplace", boost::bind(&LLFloaterPreference::onClickAutoReplace, this));
mCommitCallbackRegistrar.add("Pref.PermsDefault", boost::bind(&LLFloaterPreference::onClickPermsDefault, this));
+ mCommitCallbackRegistrar.add("Pref.RememberedUsernames", boost::bind(&LLFloaterPreference::onClickRememberedUsernames, this));
mCommitCallbackRegistrar.add("Pref.SpellChecker", boost::bind(&LLFloaterPreference::onClickSpellChecker, this));
mCommitCallbackRegistrar.add("Pref.Advanced", boost::bind(&LLFloaterPreference::onClickAdvanced, this));
@@ -1241,7 +1242,7 @@ void LLFloaterPreference::buildPopupLists()
LLNotificationFormPtr formp = templatep->mForm;
LLNotificationForm::EIgnoreType ignore = formp->getIgnoreType();
- if (ignore == LLNotificationForm::IGNORE_NO)
+ if (ignore <= LLNotificationForm::IGNORE_NO)
continue;
LLSD row;
@@ -1823,7 +1824,7 @@ void LLFloaterPreference::resetAllIgnored()
iter != LLNotifications::instance().templatesEnd();
++iter)
{
- if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+ if (iter->second->mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO)
{
iter->second->mForm->setIgnored(false);
}
@@ -1836,7 +1837,7 @@ void LLFloaterPreference::setAllIgnored()
iter != LLNotifications::instance().templatesEnd();
++iter)
{
- if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+ if (iter->second->mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO)
{
iter->second->mForm->setIgnored(true);
}
@@ -2256,6 +2257,11 @@ void LLFloaterPreference::onClickPermsDefault()
LLFloaterReg::showInstance("perms_default");
}
+void LLFloaterPreference::onClickRememberedUsernames()
+{
+ LLFloaterReg::showInstance("forget_username");
+}
+
void LLFloaterPreference::onDeleteTranscripts()
{
LLSD args;
@@ -2668,7 +2674,7 @@ void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)
bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
- getChild<LLCheckBoxCtrl>("media_auto_play_btn")->setEnabled(music_enabled || media_enabled);
+ getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled);
}
}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index d46f0deb7a..4412c95473 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -168,7 +168,6 @@ public:
void refreshUI();
- void onCommitParcelMediaAutoPlayEnable();
void onCommitMediaEnabled();
void onCommitMusicEnabled();
void applyResolution();
@@ -181,6 +180,7 @@ public:
void onClickProxySettings();
void onClickTranslationSettings();
void onClickPermsDefault();
+ void onClickRememberedUsernames();
void onClickAutoReplace();
void onClickSpellChecker();
void onClickRenderExceptions();
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index 322a5f410c..24f40c8182 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -29,6 +29,7 @@
#include "llimprocessing.h"
#include "llagent.h"
+#include "llappviewer.h"
#include "llavatarnamecache.h"
#include "llfirstuse.h"
#include "llfloaterreg.h"
@@ -1453,6 +1454,7 @@ void LLIMProcessing::requestOfflineMessages()
static BOOL requested = FALSE;
if (!requested
&& gMessageSystem
+ && !gDisconnected
&& LLMuteList::getInstance()->isLoaded()
&& isAgentAvatarValid()
&& gAgent.getRegion()
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 0f5d514660..c07064389b 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -848,7 +848,7 @@ void LLIMModel::LLIMSession::loadHistory()
std::list<LLSD> chat_history;
//involves parsing of a chat history
- LLLogChat::loadChatHistory(mHistoryFileName, chat_history);
+ LLLogChat::loadChatHistory(mHistoryFileName, chat_history, LLSD(), isGroupChat());
addMessagesFromHistory(chat_history);
}
}
@@ -912,6 +912,11 @@ bool LLIMModel::LLIMSession::isP2P()
return IM_NOTHING_SPECIAL == mType;
}
+bool LLIMModel::LLIMSession::isGroupChat()
+{
+ return IM_SESSION_GROUP_START == mType || (IM_SESSION_INVITE == mType && gAgent.isInGroup(mSessionID));
+}
+
bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
{
return !mOtherParticipantIsAvatar;
@@ -969,6 +974,10 @@ void LLIMModel::LLIMSession::buildHistoryFileName()
mHistoryFileName = LLCacheName::buildUsername(mName);
}
}
+ else if (isGroupChat())
+ {
+ mHistoryFileName = mName + GROUP_CHAT_SUFFIX;
+ }
}
//static
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 81d3ffa1a6..344f6d9a83 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -91,6 +91,7 @@ public:
bool isOutgoingAdHoc() const;
bool isAdHoc();
bool isP2P();
+ bool isGroupChat();
bool isOtherParticipantAvaline();
bool isP2PSessionType() const { return mSessionType == P2P_SESSION;}
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index d4993a1091..6f461673ee 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -291,7 +291,6 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible"))
{
getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX));
- getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX));
}
// hide marketplace listing box, unless we are a marketplace panel
if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible") && !mParams.use_marketplace_folders)
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 1bdeddbcfe..e2f253d2bd 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -67,6 +67,8 @@ const std::string LL_IM_FROM("from");
const std::string LL_IM_FROM_ID("from_id");
const std::string LL_TRANSCRIPT_FILE_EXTENSION("txt");
+const std::string GROUP_CHAT_SUFFIX(" (group)");
+
const static char IM_SYMBOL_SEPARATOR(':');
const static std::string IM_SEPARATOR(std::string() + IM_SYMBOL_SEPARATOR + " ");
const static std::string NEW_LINE("\n");
@@ -345,7 +347,7 @@ void LLLogChat::saveHistory(const std::string& filename,
}
// static
-void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
+void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params, bool is_group)
{
if (file_name.empty())
{
@@ -358,10 +360,25 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
if (!fptr)
{
- fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (is_group)
+ {
+ std::string old_name(file_name);
+ old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r");
+ if (fptr)
+ {
+ fclose(fptr);
+ LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
+ }
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");
+ }
if (!fptr)
{
- return; //No previous conversation with this name.
+ fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ return; //No previous conversation with this name.
+ }
}
}
@@ -1047,12 +1064,28 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LL
if (!fptr)
{
- fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ bool is_group = load_params.has("is_group") ? load_params["is_group"].asBoolean() : false;
+ if (is_group)
+ {
+ std::string old_name(file_name);
+ old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r");
+ if (fptr)
+ {
+ fclose(fptr);
+ LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
+ }
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");
+ }
if (!fptr)
{
- mNewLoad = false;
- (*mLoadEndSignal)(messages, file_name);
- return; //No previous conversation with this name.
+ fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ mNewLoad = false;
+ (*mLoadEndSignal)(messages, file_name);
+ return; //No previous conversation with this name.
+ }
}
}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index fcbd38a044..6ccb2caf43 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -104,7 +104,7 @@ public:
static void getListOfTranscriptFiles(std::vector<std::string>& list);
static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
- static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());
+ static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD(), bool is_group = false);
typedef boost::signals2::signal<void ()> save_history_signal_t;
static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb);
@@ -192,6 +192,7 @@ protected:
virtual ~LLChatLogParser() {};
};
+extern const std::string GROUP_CHAT_SUFFIX;
// LLSD map lookup constants
extern const std::string LL_IM_TIME; //("time");
diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp
index eca34c0d4d..22cedf450e 100644
--- a/indra/newview/llloginhandler.cpp
+++ b/indra/newview/llloginhandler.cpp
@@ -139,8 +139,11 @@ LLPointer<LLCredential> LLLoginHandler::initializeLoginInfo()
// so try to load it from the UserLoginInfo
result = loadSavedUserLoginInfo();
if (result.isNull())
- {
- result = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ {
+ // Since legacy viewer store login info one per grid, newer viewers have to
+ // reuse same information to remember last user and for compatibility,
+ // but otherwise login info is stored in separate map in gSecAPIHandler
+ result = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
}
return result;
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 7f6955d08c..b7947288c6 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -208,6 +208,20 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
}
////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ if (LLPanel::handleScrollHWheel(x, y, clicks)) return TRUE;
+ if (mMediaSource && mMediaSource->hasMedia())
+ {
+ convertInputCoords(x, y);
+ mMediaSource->scrollWheel(x, y, clicks, 0, gKeyboard->currentMask(TRUE));
+ }
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// virtual
BOOL LLMediaCtrl::handleToolTip(S32 x, S32 y, MASK mask)
{
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 11400c8274..958c76f261 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -92,6 +92,7 @@ public:
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+ virtual BOOL handleScrollHWheel( S32 x, S32 y, S32 clicks );
virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
// navigation
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 19f238d99a..28201b7345 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -574,6 +574,8 @@ BOOL LLPanelStandStopFlying::postBuild()
//mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));
mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));
mStopFlyingButton->setVisible(FALSE);
+
+ gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelStandStopFlying::updatePosition, this));
return TRUE;
}
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 6d0c30fbf3..c0342eef4e 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -764,6 +764,7 @@ void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType t
setClassifiedName(c_info->name);
setDescription(c_info->description);
setSnapshotId(c_info->snapshot_id);
+ setParcelId(c_info->parcel_id);
setPosGlobal(c_info->pos_global);
setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global));
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 0efb234015..e3d75d5604 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1153,7 +1153,7 @@ void LLPanelGroupMembersSubTab::onInviteMember(void *userdata)
void LLPanelGroupMembersSubTab::handleInviteMember()
{
- LLFloaterGroupInvite::showForGroup(mGroupID);
+ LLFloaterGroupInvite::showForGroup(mGroupID, NULL, false);
}
void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index e253557797..d7c189271e 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -77,6 +77,60 @@ LLPanelLogin *LLPanelLogin::sInstance = NULL;
BOOL LLPanelLogin::sCapslockDidNotification = FALSE;
BOOL LLPanelLogin::sCredentialSet = FALSE;
+// Helper functions
+
+LLPointer<LLCredential> load_user_credentials(std::string &user_key)
+{
+ if (gSecAPIHandler->hasCredentialMap("login_list", LLGridManager::getInstance()->getGrid()))
+ {
+ // user_key should be of "name Resident" format
+ return gSecAPIHandler->loadFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), user_key);
+ }
+ else
+ {
+ // legacy (or legacy^2, since it also tries to load from settings)
+ return gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ }
+}
+
+// keys are lower case to be case insensitive so they are not always
+// identical to names which retain user input, like:
+// "AwEsOmE Resident" -> "awesome_resident"
+std::string get_user_key_from_name(const std::string &username)
+{
+ std::string key = username;
+ LLStringUtil::trim(key);
+ LLStringUtil::toLower(key);
+ if (!LLGridManager::getInstance()->isSystemGrid())
+ {
+ size_t separator_index = username.find_first_of(" ");
+ if (separator_index == username.npos)
+ {
+ // CRED_IDENTIFIER_TYPE_ACCOUNT
+ return key;
+ }
+ }
+ // CRED_IDENTIFIER_TYPE_AGENT
+ size_t separator_index = username.find_first_of(" ._");
+ std::string first = username.substr(0, separator_index);
+ std::string last;
+ if (separator_index != username.npos)
+ {
+ last = username.substr(separator_index + 1, username.npos);
+ LLStringUtil::trim(last);
+ }
+ else
+ {
+ // ...on Linden grids, single username users as considered to have
+ // last name "Resident"
+ // *TODO: Make login.cgi support "account_name" like above
+ last = "resident";
+ }
+
+ key = first + "_" + last;
+ return key;
+}
+
class LLLoginLocationAutoHandler : public LLCommandHandler
{
public:
@@ -168,6 +222,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
mCallback(callback),
mCallbackData(cb_data),
mListener(new LLPanelLoginListener(this)),
+ mFirstLoginThisInstall(gSavedSettings.getBOOL("FirstLoginThisInstall")),
mUsernameLength(0),
mPasswordLength(0),
mLocationLength(0),
@@ -186,7 +241,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
login_holder->addChild(this);
}
- if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+ if (mFirstLoginThisInstall)
{
buildFromFile( "panel_login_first.xml");
}
@@ -206,35 +261,39 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
sendChildToBack(getChildView("forgot_password_text"));
sendChildToBack(getChildView("sign_up_text"));
- LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
- updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
- favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
- favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));
-
- LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo");
- server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectServer, this));
-
- // Load all of the grids, sorted, and then add a bar and the current grid at the top
- server_choice_combo->removeall();
-
- std::string current_grid = LLGridManager::getInstance()->getGrid();
- std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
- for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
- grid_choice != known_grids.end();
- grid_choice++)
- {
- if (!grid_choice->first.empty() && current_grid != grid_choice->first)
- {
- LL_DEBUGS("AppInit")<<"adding "<<grid_choice->first<<LL_ENDL;
- server_choice_combo->add(grid_choice->second, grid_choice->first);
- }
- }
- server_choice_combo->sortByName();
- LL_DEBUGS("AppInit")<<"adding current "<<current_grid<<LL_ENDL;
- server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(),
- current_grid,
- ADD_TOP);
- server_choice_combo->selectFirstItem();
+ std::string current_grid = LLGridManager::getInstance()->getGrid();
+ if (!mFirstLoginThisInstall)
+ {
+ LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
+ updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
+ favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+ favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));
+
+ LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo");
+ server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectServer, this));
+
+ // Load all of the grids, sorted, and then add a bar and the current grid at the top
+ server_choice_combo->removeall();
+
+ std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
+ for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
+ grid_choice != known_grids.end();
+ grid_choice++)
+ {
+ if (!grid_choice->first.empty() && current_grid != grid_choice->first)
+ {
+ LL_DEBUGS("AppInit") << "adding " << grid_choice->first << LL_ENDL;
+ server_choice_combo->add(grid_choice->second, grid_choice->first);
+ }
+ }
+ server_choice_combo->sortByName();
+
+ LL_DEBUGS("AppInit") << "adding current " << current_grid << LL_ENDL;
+ server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(),
+ current_grid,
+ ADD_TOP);
+ server_choice_combo->selectFirstItem();
+ }
LLSLURL start_slurl(LLStartUp::getStartSLURL());
// The StartSLURL might have been set either by an explicit command-line
@@ -297,14 +356,30 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
loadLoginPage();
LLComboBox* username_combo(getChild<LLComboBox>("username_combo"));
- username_combo->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this));
+ username_combo->setTextChangedCallback(boost::bind(&LLPanelLogin::onUserNameTextEnty, this));
// STEAM-14: When user presses Enter with this field in focus, initiate login
- username_combo->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+ username_combo->setCommitCallback(boost::bind(&LLPanelLogin::onUserListCommit, this));
+ username_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
username_combo->setKeystrokeOnEsc(TRUE);
+
+ if (!mFirstLoginThisInstall)
+ {
+ LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
+ remember_name->setCommitCallback(boost::bind(&LLPanelLogin::onRememberUserCheck, this));
+ }
}
void LLPanelLogin::addFavoritesToStartLocation()
{
+ if (mFirstLoginThisInstall)
+ {
+ // first login panel has no favorites, just update name length and buttons
+ std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
+ mUsernameLength = user_defined_name.length();
+ updateLoginButtons();
+ return;
+ }
+
// Clear the combo.
LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
if (!combo) return;
@@ -316,14 +391,14 @@ void LLPanelLogin::addFavoritesToStartLocation()
// Load favorites into the combo.
std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
+ LLStringUtil::trim(user_defined_name);
LLStringUtil::toLower(user_defined_name);
- std::replace(user_defined_name.begin(), user_defined_name.end(), '.', ' ');
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + LLGridManager::getInstance()->getGrid() + ".xml");
std::string old_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
mUsernameLength = user_defined_name.length();
updateLoginButtons();
- std::string::size_type index = user_defined_name.find(' ');
+ std::string::size_type index = user_defined_name.find_first_of(" ._");
if (index != std::string::npos)
{
std::string username = user_defined_name.substr(0, index);
@@ -332,6 +407,10 @@ void LLPanelLogin::addFavoritesToStartLocation()
{
user_defined_name = username;
}
+ else
+ {
+ user_defined_name = username + " " + lastname;
+ }
}
LLSD fav_llsd;
@@ -443,24 +522,6 @@ void LLPanelLogin::giveFocus()
}
// static
-void LLPanelLogin::showLoginWidgets()
-{
- if (sInstance)
- {
- // *NOTE: Mani - This may or may not be obselete code.
- // It seems to be part of the defunct? reg-in-client project.
- sInstance->getChildView("login_widgets")->setVisible( true);
- LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-
- // *TODO: Append all the usual login parameters, like first_login=Y etc.
- std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
- web_browser->navigateTo( splash_screen_url, "text/html" );
- LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
- username_combo->setFocus(TRUE);
- }
-}
-
-// static
void LLPanelLogin::show(const LLRect &rect,
void (*callback)(S32 option, void* user_data),
void* callback_data)
@@ -480,9 +541,55 @@ void LLPanelLogin::show(const LLRect &rect,
gFocusMgr.setDefaultKeyboardFocus(sInstance);
}
+//static
+void LLPanelLogin::populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd)
+{
+ if (!sInstance)
+ {
+ LL_WARNS() << "Attempted fillFields with no login view shown" << LL_ENDL;
+ return;
+ }
+ LLUICtrl* remember_check = sInstance->getChild<LLUICtrl>("remember_check");
+ remember_check->setValue(remember_psswrd);
+ if (sInstance->mFirstLoginThisInstall)
+ {
+ // no list to populate
+ setFields(credential, remember_psswrd);
+ }
+ else
+ {
+ sInstance->getChild<LLUICtrl>("remember_name")->setValue(remember_user);
+ sInstance->populateUserList(credential, remember_psswrd);
+ remember_check->setEnabled(remember_user);
+ }
+}
+
+//static
+void LLPanelLogin::resetFields()
+{
+ if (!sInstance)
+ {
+ // class not existing at this point might happen since this
+ // function is used to reset list in case of changes by external sources
+ return;
+ }
+ if (sInstance->mFirstLoginThisInstall)
+ {
+ // no list to populate
+ LL_WARNS() << "Shouldn't happen, user should have no ability to modify list on first install" << LL_ENDL;
+ }
+ else
+ {
+ LLUICtrl* remember_check = sInstance->getChild<LLUICtrl>("remember_check");
+ bool remember_psswrd = remember_check->getValue();
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ sInstance->populateUserList(cred, remember_psswrd);
+ }
+}
+
// static
void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
- BOOL remember)
+ bool remember_psswrd)
{
if (!sInstance)
{
@@ -492,13 +599,15 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
sCredentialSet = TRUE;
LL_INFOS("Credentials") << "Setting login fields to " << *credential << LL_ENDL;
- LLSD identifier = credential->getIdentifier();
- if((std::string)identifier["type"] == "agent")
+ LLSD identifier = credential.notNull() ? credential->getIdentifier() : LLSD();
+
+ if(identifier.has("type") && (std::string)identifier["type"] == "agent")
{
+ // not nessesary for panel_login.xml, needed for panel_login_first.xml
std::string firstname = identifier["first_name"].asString();
std::string lastname = identifier["last_name"].asString();
std::string login_id = firstname;
- if (!lastname.empty() && lastname != "Resident")
+ if (!lastname.empty() && lastname != "Resident" && lastname != "resident")
{
// support traditional First Last name SLURLs
login_id += " ";
@@ -506,22 +615,23 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
}
sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id);
}
- else if((std::string)identifier["type"] == "account")
+ else if(identifier.has("type") && (std::string)identifier["type"] == "account")
{
sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]);
}
else
{
- sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());
+ sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());
}
+
sInstance->addFavoritesToStartLocation();
// if the password exists in the credential, set the password field with
// a filler to get some stars
- LLSD authenticator = credential->getAuthenticator();
+ LLSD authenticator = credential.notNull() ? credential->getAuthenticator() : LLSD();
LL_INFOS("Credentials") << "Setting authenticator field " << authenticator["type"].asString() << LL_ENDL;
if(authenticator.isMap() &&
authenticator.has("secret") &&
- (authenticator["secret"].asString().size() > 0) && remember)
+ (authenticator["secret"].asString().size() > 0) && remember_psswrd)
{
// This is a MD5 hex digest of a password.
@@ -537,36 +647,25 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
{
sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());
}
- sInstance->getChild<LLUICtrl>("remember_check")->setValue(remember);
}
-
// static
void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
- BOOL& remember)
+ bool& remember_user,
+ bool& remember_psswrd)
{
if (!sInstance)
{
LL_WARNS() << "Attempted getFields with no login view shown" << LL_ENDL;
return;
}
-
- // load the credential so we can pass back the stored password or hash if the user did
- // not modify the password field.
-
- credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
LLSD identifier = LLSD::emptyMap();
LLSD authenticator = LLSD::emptyMap();
-
- if(credential.notNull())
- {
- authenticator = credential->getAuthenticator();
- }
- std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
- LLStringUtil::trim(username);
+ std::string username = sInstance->getChild<LLComboBox>("username_combo")->getValue().asString();
std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+ LLStringUtil::trim(username);
LL_INFOS("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
// determine if the username is a first/last form or not.
@@ -586,6 +685,14 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR;
authenticator["secret"] = password;
}
+ else
+ {
+ credential = load_user_credentials(username);
+ if (credential.notNull())
+ {
+ authenticator = credential->getAuthenticator();
+ }
+ }
}
else
{
@@ -597,7 +704,7 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
if (separator_index != username.npos)
{
last = username.substr(separator_index+1, username.npos);
- LLStringUtil::trim(last);
+ LLStringUtil::trim(last);
}
else
{
@@ -625,10 +732,28 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
pass.hex_digest(md5pass);
authenticator["secret"] = md5pass;
}
+ else
+ {
+ std::string key = first + "_" + last;
+ LLStringUtil::toLower(key);
+ credential = load_user_credentials(key);
+ if (credential.notNull())
+ {
+ authenticator = credential->getAuthenticator();
+ }
+ }
}
}
credential = gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGrid(), identifier, authenticator);
- remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ if (!sInstance->mFirstLoginThisInstall)
+ {
+ remember_user = sInstance->getChild<LLUICtrl>("remember_name")->getValue();
+ }
+ else
+ {
+ remember_user = true;
+ }
}
@@ -898,8 +1023,8 @@ void LLPanelLogin::onClickConnect(void *)
{
sCredentialSet = FALSE;
LLPointer<LLCredential> cred;
- BOOL remember;
- getFields(cred, remember);
+ bool remember_1, remember_2;
+ getFields(cred, remember_1, remember_2);
std::string identifier_type;
cred->identifierType(identifier_type);
LLSD allowed_credential_types;
@@ -953,6 +1078,57 @@ void LLPanelLogin::onClickSignUp(void*)
}
// static
+void LLPanelLogin::onUserNameTextEnty(void*)
+{
+ sInstance->mPasswordModified = true;
+ sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());
+ sInstance->addFavoritesToStartLocation(); //will call updateLoginButtons()
+}
+
+// static
+void LLPanelLogin::onUserListCommit(void*)
+{
+ if (sInstance)
+ {
+ LLComboBox* username_combo(sInstance->getChild<LLComboBox>("username_combo"));
+ static S32 ind = -1;
+ if (ind != username_combo->getCurrentIndex())
+ {
+ std::string user_key = username_combo->getSelectedValue();
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), user_key);
+ bool remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ setFields(cred, remember_psswrd);
+ sInstance->mPasswordModified = false;
+ }
+ else
+ {
+ std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+ if (pass.empty())
+ {
+ sInstance->giveFocus();
+ }
+ else
+ {
+ onClickConnect(NULL);
+ }
+ }
+ }
+}
+
+// static
+void LLPanelLogin::onRememberUserCheck(void*)
+{
+ if (sInstance)
+ {
+ LLCheckBoxCtrl* remember_name(sInstance->getChild<LLCheckBoxCtrl>("remember_name"));
+ LLCheckBoxCtrl* remember_psswrd(sInstance->getChild<LLCheckBoxCtrl>("remember_check"));
+
+ bool remember = remember_name->getValue().asBoolean();
+ remember_psswrd->setEnabled(remember);
+ }
+}
+
+// static
void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
{
LLPanelLogin *self = (LLPanelLogin *)user_data;
@@ -979,9 +1155,11 @@ void LLPanelLogin::updateServer()
// for that grid and set them to the UI.
if(!sInstance->areCredentialFieldsDirty())
{
- LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
- bool remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
- sInstance->setFields(credential, remember);
+ // populate dropbox and setFields
+ bool remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ // Note: following call is related to initializeLoginInfo()
+ LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ sInstance->populateUserList(credential, remember_psswrd);
}
// update the login panel links
@@ -1011,14 +1189,63 @@ void LLPanelLogin::updateLoginButtons()
LLButton* login_btn = getChild<LLButton>("connect_btn");
login_btn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0);
+
+ if (!mFirstLoginThisInstall)
+ {
+ LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
+ LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
+ remember_name->setEnabled(user_combo->getCurrentIndex() == -1);
+ }
+}
+
+void LLPanelLogin::populateUserList(LLPointer<LLCredential> credential, bool remember_psswrd)
+{
+ LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
+ user_combo->removeall();
+ user_combo->clear();
+
+ if (gSecAPIHandler->hasCredentialMap("login_list", LLGridManager::getInstance()->getGrid()))
+ {
+ LLSecAPIHandler::credential_map_t credencials;
+ gSecAPIHandler->loadCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), credencials);
+
+ LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin();
+ LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end();
+ while (cr_iter != cr_end)
+ {
+ if (cr_iter->second.notNull()) // basic safety in case of future changes
+ {
+ // cr_iter->first == user_id , to be able to be find it in case we select it
+ user_combo->add(LLPanelLogin::getUserName(cr_iter->second), cr_iter->first, ADD_BOTTOM, TRUE);
+ }
+ cr_iter++;
+ }
+
+ if (credential.isNull() || !user_combo->setSelectedByValue(LLSD(credential->userID()), true))
+ {
+ // selection failed, just deselect whatever might be selected
+ user_combo->setValue(std::string());
+ }
+ else
+ {
+ setFields(credential, remember_psswrd);
+ }
+ }
+ else
+ {
+ if (credential.notNull())
+ {
+ user_combo->add(LLPanelLogin::getUserName(credential), credential->userID(), ADD_BOTTOM, TRUE);
+ setFields(credential, remember_psswrd);
+ }
+ }
}
+
void LLPanelLogin::onSelectServer()
{
// The user twiddled with the grid choice ui.
// apply the selection to the grid setting.
- LLPointer<LLCredential> credential;
-
LLComboBox* server_combo = getChild<LLComboBox>("server_combo");
LLSD server_combo_val = server_combo->getSelectedValue();
LL_INFOS("AppInit") << "grid "<<server_combo_val.asString()<< LL_ENDL;
@@ -1077,3 +1304,34 @@ bool LLPanelLogin::getShowFavorites()
{
return gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin");
}
+
+// static
+std::string LLPanelLogin::getUserName(LLPointer<LLCredential> &cred)
+{
+ if (cred.isNull())
+ {
+ return "unknown";
+ }
+ const LLSD &ident = cred->getIdentifier();
+
+ if (!ident.isMap())
+ {
+ return "unknown";
+ }
+ else if ((std::string)ident["type"] == "agent")
+ {
+ std::string second_name = ident["last_name"];
+ if (second_name == "resident" || second_name == "Resident")
+ {
+ return (std::string)ident["first_name"];
+ }
+ return (std::string)ident["first_name"] + " " + (std::string)ident["last_name"];
+ }
+ else if ((std::string)ident["type"] == "account")
+ {
+ return LLCacheName::cleanFullName((std::string)ident["account_name"]);
+ }
+
+ return "unknown";
+}
+
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index c633582d89..3eb7b68949 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -55,9 +55,9 @@ public:
void (*callback)(S32 option, void* user_data),
void* callback_data);
- static void setFields(LLPointer<LLCredential> credential, BOOL remember);
-
- static void getFields(LLPointer<LLCredential>& credential, BOOL& remember);
+ static void populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd);
+ static void resetFields();
+ static void getFields(LLPointer<LLCredential>& credential, bool& remember_user, bool& remember_psswrd);
static BOOL isCredentialSet() { return sCredentialSet; }
@@ -72,8 +72,6 @@ public:
void setSiteIsAlive( bool alive );
- void showLoginWidgets();
-
static void loadLoginPage();
static void giveFocus();
static void setAlwaysRefresh(bool refresh);
@@ -88,6 +86,9 @@ public:
// called from prefs when initializing panel
static bool getShowFavorites();
+ // extract name from cred in a format apropriate for username field
+ static std::string getUserName(LLPointer<LLCredential> &cred);
+
private:
friend class LLPanelLoginListener;
void addFavoritesToStartLocation();
@@ -95,11 +96,16 @@ private:
void onSelectServer();
void onLocationSLURL();
+ static void setFields(LLPointer<LLCredential> credential, bool remember_psswrd);
+
static void onClickConnect(void*);
static void onClickNewAccount(void*);
static void onClickVersion(void*);
static void onClickForgotPassword(void*);
static void onClickSignUp(void*);
+ static void onUserNameTextEnty(void*);
+ static void onUserListCommit(void*);
+ static void onRememberUserCheck(void*);
static void onPassKey(LLLineEditor* caller, void* user_data);
static void updateServerCombo();
@@ -107,6 +113,7 @@ private:
boost::scoped_ptr<LLPanelLoginListener> mListener;
void updateLoginButtons();
+ void populateUserList(LLPointer<LLCredential> credential, bool remember_psswrd);
void (*mCallback)(S32 option, void *userdata);
void* mCallbackData;
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
index f3a2ed9408..af28ff8e61 100644
--- a/indra/newview/llpanelnearbymedia.cpp
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -43,6 +43,7 @@
#include "llbutton.h"
#include "lltextbox.h"
#include "llviewermedia.h"
+#include "llviewerparcelaskplay.h"
#include "llviewerparcelmedia.h"
#include "llviewerregion.h"
#include "llviewermediafocus.h"
@@ -83,10 +84,11 @@ LLPanelNearByMedia::LLPanelNearByMedia()
{
mHoverTimer.stop();
- mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
- gSavedSettings.getBOOL("MediaTentativeAutoPlay");
+ // This is just an initial value, mParcelAudioAutoStart does not affect ParcelMediaAutoPlayEnable
+ mParcelAudioAutoStart = gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0
+ && gSavedSettings.getBOOL("MediaTentativeAutoPlay");
- gSavedSettings.getControl(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2));
+ gSavedSettings.getControl("ParcelMediaAutoPlayEnable")->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2));
mCommitCallbackRegistrar.add("MediaListCtrl.EnableAll", boost::bind(&LLPanelNearByMedia::onClickEnableAll, this));
mCommitCallbackRegistrar.add("MediaListCtrl.DisableAll", boost::bind(&LLPanelNearByMedia::onClickDisableAll, this));
@@ -177,9 +179,18 @@ BOOL LLPanelNearByMedia::postBuild()
void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue)
{
- // update mParcelAudioAutoStart if AUTO_PLAY_MEDIA_SETTING changes
- mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
- gSavedSettings.getBOOL("MediaTentativeAutoPlay");
+ // update mParcelAudioAutoStartMode if "ParcelMediaAutoPlayEnable" changes
+ S32 value = gSavedSettings.getS32("ParcelMediaAutoPlayEnable");
+ mParcelAudioAutoStart = value != 0
+ && gSavedSettings.getBOOL("MediaTentativeAutoPlay");
+
+ LLViewerParcelAskPlay *inst = LLViewerParcelAskPlay::getInstance();
+ if (value == 2 && !inst->hasData())
+ {
+ // Init if nessesary
+ inst->loadSettings();
+ }
+ inst->cancelNotification();
}
/*virtual*/
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 48dd45480e..25961e0054 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -675,6 +675,12 @@ void LLPanelPlaces::onShowOnMapButtonClicked()
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
+ if (mItem.isNull())
+ {
+ LL_WARNS() << "NULL landmark item" << LL_ENDL;
+ llassert(mItem.notNull());
+ return;
+ }
LLLandmark* landmark = gLandmarkList.getAsset(mItem->getAssetUUID());
if (!landmark)
return;
diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp
index 6792137350..f063d84272 100644
--- a/indra/newview/llpanelvolumepulldown.cpp
+++ b/indra/newview/llpanelvolumepulldown.cpp
@@ -140,7 +140,7 @@ void LLPanelVolumePulldown::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)
bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
- getChild<LLCheckBoxCtrl>("media_auto_play_btn")->setEnabled(music_enabled || media_enabled);
+ getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled);
}
}
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index d207f3b5b7..c0f0a367c7 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -464,7 +464,19 @@ public:
// delete a protected data item from the store
virtual void deleteProtectedData(const std::string& data_type,
const std::string& data_id)=0;
-
+
+ // persist data in a protected store's map
+ virtual void addToProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem,
+ const LLSD& data)=0;
+
+ // remove data from protected store's map
+ virtual void removeFromProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem)=0;
+
+public:
virtual LLPointer<LLCredential> createCredential(const std::string& grid,
const LLSD& identifier,
const LLSD& authenticator)=0;
@@ -474,6 +486,38 @@ public:
virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)=0;
virtual void deleteCredential(LLPointer<LLCredential> cred)=0;
+
+ // has map of credentials declared as specific storage
+ virtual bool hasCredentialMap(const std::string& storage,
+ const std::string& grid)=0;
+
+ // load map of credentials from specific storage
+ typedef std::map<std::string, LLPointer<LLCredential> > credential_map_t;
+ virtual void loadCredentialMap(const std::string& storage,
+ const std::string& grid,
+ credential_map_t& credential_map)=0;
+
+ // load single username from map of credentials from specific storage
+ virtual LLPointer<LLCredential> loadFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid)=0;
+
+ // add item to map of credentials from specific storage
+ virtual void addToCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred,
+ bool save_authenticator)=0;
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred)=0;
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid)=0;
+
+ virtual void removeCredentialMap(const std::string& storage,
+ const std::string& grid)=0;
};
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 9ab9e4a1a2..a8bb54a90e 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -52,6 +52,7 @@
#include "llmachineid.h"
+static const std::string DEFAULT_CREDENTIAL_STORAGE = "credential";
// 128 bits of salt data...
#define STORE_SALT_SIZE 16
@@ -1533,6 +1534,38 @@ void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type,
mProtectedDataMap[data_type][data_id] = data;
}
+// persist data in a protected store's map
+void LLSecAPIBasicHandler::addToProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem,
+ const LLSD& data)
+{
+ if (!mProtectedDataMap.has(data_type) || !mProtectedDataMap[data_type].isMap()) {
+ mProtectedDataMap[data_type] = LLSD::emptyMap();
+ }
+
+ if (!mProtectedDataMap[data_type].has(data_id) || !mProtectedDataMap[data_type][data_id].isMap()) {
+ mProtectedDataMap[data_type][data_id] = LLSD::emptyMap();
+ }
+
+ mProtectedDataMap[data_type][data_id][map_elem] = data;
+}
+
+// remove data from protected store's map
+void LLSecAPIBasicHandler::removeFromProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem)
+{
+ if (mProtectedDataMap.has(data_type) &&
+ mProtectedDataMap[data_type].isMap() &&
+ mProtectedDataMap[data_type].has(data_id) &&
+ mProtectedDataMap[data_type][data_id].isMap() &&
+ mProtectedDataMap[data_type][data_id].has(map_elem))
+ {
+ mProtectedDataMap[data_type][data_id].erase(map_elem);
+ }
+}
+
//
// Create a credential object from an identifier and authenticator. credentials are
// per grid.
@@ -1545,10 +1578,10 @@ LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string
return result;
}
-// Load a credential from the credential store, given the grid
+// Load a credential from default credential store, given the grid
LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid)
{
- LLSD credential = getProtectedData("credential", grid);
+ LLSD credential = getProtectedData(DEFAULT_CREDENTIAL_STORAGE, grid);
LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
if(credential.isMap() &&
credential.has("identifier"))
@@ -1603,7 +1636,7 @@ void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool sav
credential["authenticator"] = cred->getAuthenticator();
}
LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
- setProtectedData("credential", cred->getGrid(), credential);
+ setProtectedData(DEFAULT_CREDENTIAL_STORAGE, cred->getGrid(), credential);
//*TODO: If we're saving Agni credentials, should we write the
// credentials to the legacy password.dat/etc?
_writeProtectedData();
@@ -1613,11 +1646,137 @@ void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool sav
void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred)
{
LLSD undefVal;
- deleteProtectedData("credential", cred->getGrid());
+ deleteProtectedData(DEFAULT_CREDENTIAL_STORAGE, cred->getGrid());
cred->setCredentialData(undefVal, undefVal);
_writeProtectedData();
}
+// has map of credentials declared as specific storage
+bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const std::string& grid)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD credential = getProtectedData(storage, grid);
+
+ return credential.isMap();
+}
+
+// Load map of credentials from specified credential store, given the grid
+void LLSecAPIBasicHandler::loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD credential = getProtectedData(storage, grid);
+ if (credential.isMap())
+ {
+ LLSD::map_const_iterator crd_it = credential.beginMap();
+ for (; crd_it != credential.endMap(); crd_it++)
+ {
+ LLSD::String name = crd_it->first;
+ const LLSD &link_map = crd_it->second;
+ LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
+ if (link_map.has("identifier"))
+ {
+ LLSD identifier = link_map["identifier"];
+ LLSD authenticator;
+ if (link_map.has("authenticator"))
+ {
+ authenticator = link_map["authenticator"];
+ }
+ result->setCredentialData(identifier, authenticator);
+ }
+ credential_map[name] = result;
+ }
+ }
+}
+
+LLPointer<LLCredential> LLSecAPIBasicHandler::loadFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
+
+ LLSD credential = getProtectedData(storage, grid);
+ if (credential.isMap() && credential.has(userkey) && credential[userkey].has("identifier"))
+ {
+ LLSD identifier = credential[userkey]["identifier"];
+ LLSD authenticator;
+ if (credential[userkey].has("authenticator"))
+ {
+ authenticator = credential[userkey]["authenticator"];
+ }
+ result->setCredentialData(identifier, authenticator);
+ }
+
+ return result;
+}
+
+// add item to map of credentials from specific storage
+void LLSecAPIBasicHandler::addToCredentialMap(const std::string& storage, LLPointer<LLCredential> cred, bool save_authenticator)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ std::string user_id = cred->userID();
+ LLSD credential = LLSD::emptyMap();
+ credential["identifier"] = cred->getIdentifier();
+ if (save_authenticator)
+ {
+ credential["authenticator"] = cred->getAuthenticator();
+ }
+ LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
+ addToProtectedMap(storage, cred->getGrid(), user_id, credential);
+
+ _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, LLPointer<LLCredential> cred)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD undefVal;
+ removeFromProtectedMap(storage, cred->getGrid(), cred->userID());
+ cred->setCredentialData(undefVal, undefVal);
+ _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD undefVal;
+ LLPointer<LLCredential> cred = loadFromCredentialMap(storage, grid, userkey);
+ removeFromProtectedMap(storage, grid, userkey);
+ cred->setCredentialData(undefVal, undefVal);
+ _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeCredentialMap(const std::string& storage, const std::string& grid)
+{
+ deleteProtectedData(storage, grid);
+ _writeProtectedData();
+}
+
// load the legacy hash for agni, and decrypt it given the
// mac address
std::string LLSecAPIBasicHandler::_legacyLoadPassword()
@@ -1656,15 +1815,18 @@ std::string LLSecAPIBasicCredential::userID() const
}
else if ((std::string)mIdentifier["type"] == "agent")
{
- return (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
+ std::string id = (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
+ LLStringUtil::toLower(id);
+ return id;
}
else if ((std::string)mIdentifier["type"] == "account")
{
- return (std::string)mIdentifier["account_name"];
+ std::string id = (std::string)mIdentifier["account_name"];
+ LLStringUtil::toLower(id);
+ return id;
}
return "unknown";
-
}
// return a printable user identifier
diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h
index c35617f564..426b5d392a 100644
--- a/indra/newview/llsechandler_basic.h
+++ b/indra/newview/llsechandler_basic.h
@@ -211,8 +211,9 @@ class LLSecAPIBasicCredential : public LLCredential
public:
LLSecAPIBasicCredential(const std::string& grid) : LLCredential(grid) {}
virtual ~LLSecAPIBasicCredential() {}
- // return a value representing the user id, (could be guid, name, whatever)
- virtual std::string userID() const;
+ // return a value representing the user id, used for server and voice
+ // (could be guid, name in format "name_resident", whatever)
+ virtual std::string userID() const;
// printible string identifying the credential.
virtual std::string asString() const;
@@ -246,7 +247,10 @@ public:
// exists, it'll be loaded. If not, one will be created (but not
// persisted)
virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id);
-
+
+ // protectedData functions technically should be pretected or private,
+ // they are not because of llsechandler_basic_test imlementation
+
// persist data in a protected store
virtual void setProtectedData(const std::string& data_type,
const std::string& data_id,
@@ -259,19 +263,64 @@ public:
// delete a protected data item from the store
virtual void deleteProtectedData(const std::string& data_type,
const std::string& data_id);
-
+
+ // persist data in a protected store's map
+ virtual void addToProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem,
+ const LLSD& data);
+
+ // remove data from protected store's map
+ virtual void removeFromProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem);
+
// credential management routines
virtual LLPointer<LLCredential> createCredential(const std::string& grid,
const LLSD& identifier,
const LLSD& authenticator);
-
+
+ // load single credencial from default storage
virtual LLPointer<LLCredential> loadCredential(const std::string& grid);
+ // save credencial to default storage
virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator);
virtual void deleteCredential(LLPointer<LLCredential> cred);
-
+
+ // has map of credentials declared as specific storage
+ virtual bool hasCredentialMap(const std::string& storage,
+ const std::string& grid);
+
+ // load map of credentials from specific storage
+ virtual void loadCredentialMap(const std::string& storage,
+ const std::string& grid,
+ credential_map_t& credential_map);
+
+ // load single username from map of credentials from specific storage
+ virtual LLPointer<LLCredential> loadFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid);
+
+ // add item to map of credentials from specific storage
+ virtual void addToCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred,
+ bool save_authenticator);
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred);
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid);
+
+ virtual void removeCredentialMap(const std::string& storage,
+ const std::string& grid);
+
+
protected:
void _readProtectedData();
void _writeProtectedData();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index bef27cfb99..5f235c05a6 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -158,6 +158,7 @@
#include "llviewermessage.h"
#include "llviewernetwork.h"
#include "llviewerobjectlist.h"
+#include "llviewerparcelaskplay.h"
#include "llviewerparcelmedia.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
@@ -236,7 +237,8 @@ LLSLURL LLStartUp::sStartSLURL;
static LLPointer<LLCredential> gUserCredential;
static std::string gDisplayName;
-static BOOL gRememberPassword = TRUE;
+static bool gRememberPassword = true;
+static bool gRememberUser = true;
static U64 gFirstSimHandle = 0;
static LLHost gFirstSim;
@@ -701,19 +703,23 @@ bool idle_startup()
else if (gSavedSettings.getBOOL("AutoLogin"))
{
// Log into last account
- gRememberPassword = TRUE;
- gSavedSettings.setBOOL("RememberPassword", TRUE);
+ gRememberPassword = true;
+ gRememberUser = true;
+ gSavedSettings.setBOOL("RememberPassword", TRUE);
+ gSavedSettings.setBOOL("RememberUser", TRUE);
show_connect_box = false;
}
else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
{
// Console provided login&password
gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+ gRememberUser = gSavedSettings.getBOOL("RememberUser");
show_connect_box = false;
}
else
{
gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+ gRememberUser = gSavedSettings.getBOOL("RememberUser");
show_connect_box = TRUE;
}
@@ -781,10 +787,7 @@ bool idle_startup()
// Show the login dialog
login_show();
// connect dialog is already shown, so fill in the names
- if (gUserCredential.notNull() && !LLPanelLogin::isCredentialSet())
- {
- LLPanelLogin::setFields( gUserCredential, gRememberPassword);
- }
+ LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword);
LLPanelLogin::giveFocus();
// MAINT-3231 Show first run dialog only for Desura viewer
@@ -873,7 +876,7 @@ bool idle_startup()
{
// TODO if not use viewer auth
// Load all the name information out of the login view
- LLPanelLogin::getFields(gUserCredential, gRememberPassword);
+ LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword);
// end TODO
// HACK: Try to make not jump on login
@@ -885,14 +888,21 @@ bool idle_startup()
// STATE_LOGIN_SHOW state if we've gone backwards
mLoginStatePastUI = true;
- // save the credentials
- std::string userid = "unknown";
- if(gUserCredential.notNull())
- {
- userid = gUserCredential->userID();
- gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);
- }
- gSavedSettings.setBOOL("RememberPassword", gRememberPassword);
+ // save the credentials
+ std::string userid = "unknown";
+ if (gUserCredential.notNull())
+ {
+ userid = gUserCredential->userID();
+ if (gRememberUser)
+ {
+ gSecAPIHandler->addToCredentialMap("login_list", gUserCredential, gRememberPassword);
+ // Legacy viewers use this method to store user credentials, newer viewers
+ // reuse it to be compatible and to remember last session
+ gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);
+ }
+ }
+ gSavedSettings.setBOOL("RememberPassword", gRememberPassword);
+ gSavedSettings.setBOOL("RememberUser", gRememberUser);
LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;
gDebugInfo["LoginName"] = userid;
@@ -1416,6 +1426,10 @@ bool idle_startup()
// create a container's instance for start a controlling conversation windows
// by the voice's events
LLFloaterIMContainer::getInstance();
+ if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2)
+ {
+ LLViewerParcelAskPlay::getInstance()->loadSettings();
+ }
// *Note: this is where gWorldMap used to be initialized.
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 495c9c1f44..8df83c64cd 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -34,7 +34,6 @@
#include "llfontgl.h"
#include "lltextbox.h"
#include "llbutton.h"
-#include "llcheckboxctrl.h"
#include "llkeyboard.h"
#include "llfocusmgr.h"
#include "lliconctrl.h"
@@ -62,9 +61,8 @@ static const S32 HPAD = 25;
static const S32 BTN_HPAD = 8;
LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal)
- : LLToastPanel(notification),
+ : LLCheckBoxToastPanel(notification),
mDefaultOption( 0 ),
- mCheck(NULL),
mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
mLabel(notification->getName()),
mLineEditor(NULL)
@@ -347,20 +345,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
button_left += button_width + BTN_HPAD;
}
- std::string ignore_label;
-
- if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
- }
- if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label);
- }
- else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
- }
+ setCheckBoxes(HPAD, VPAD);
// *TODO: check necessity of this code
//gFloaterView->adjustToFitScreen(this, FALSE);
@@ -380,46 +365,6 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
LLTransientFloaterMgr::GLOBAL, this);
}
-bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::string& check_control )
-{
- mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
-
- if(!mCheck)
- {
- return false;
- }
-
- const LLFontGL* font = mCheck->getFont();
- const S32 LINE_HEIGHT = font->getLineHeight();
-
- std::vector<std::string> lines;
- boost::split(lines, check_title, boost::is_any_of("\n"));
-
- // Extend dialog for "check next time"
- S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
- S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
- max_msg_width = llmax(max_msg_width, check_width);
- S32 dialog_width = max_msg_width + 2 * HPAD;
-
- S32 dialog_height = LLToastPanel::getRect().getHeight();
- dialog_height += LINE_HEIGHT * lines.size();
- dialog_height += LINE_HEIGHT / 2;
-
- LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
-
- S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
-
- // set check_box's attributes
- LLRect check_rect;
- mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT*lines.size()));
- mCheck->setLabel(check_title);
- mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1));
-
- LLToastPanel::addChild(mCheck);
-
- return true;
-}
-
void LLToastAlertPanel::setVisible( BOOL visible )
{
// only make the "ding" sound if it's newly visible
@@ -562,16 +507,3 @@ void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button )
mNotification->respond(response); // new notification reponse
}
-
-void LLToastAlertPanel::onClickIgnore(LLUICtrl* ctrl)
-{
- // checkbox sometimes means "hide and do the default" and
- // other times means "warn me again". Yuck. JC
- BOOL check = ctrl->getValue().asBoolean();
- if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
- {
- // question was "show again" so invert value to get "ignore"
- check = !check;
- }
- mNotification->setIgnored(check);
-}
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index d1be5e018e..21310822c4 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -46,7 +46,7 @@ class LLLineEditor;
*/
class LLToastAlertPanel
- : public LLToastPanel
+ : public LLCheckBoxToastPanel
{
LOG_CLASS(LLToastAlertPanel);
public:
@@ -75,13 +75,11 @@ public:
virtual void draw();
virtual void setVisible( BOOL visible );
- bool setCheckBox( const std::string&, const std::string& );
void setCaution(BOOL val = TRUE) { mCaution = val; }
// If mUnique==TRUE only one copy of this message should exist
void setUnique(BOOL val = TRUE) { mUnique = val; }
void setEditTextArgs(const LLSD& edit_args);
- void onClickIgnore(LLUICtrl* ctrl);
void onButtonPressed(const LLSD& data, S32 button);
private:
@@ -106,7 +104,6 @@ private:
std::vector<ButtonData> mButtonData;
S32 mDefaultOption;
- LLCheckBoxCtrl* mCheck;
BOOL mCaution;
BOOL mUnique;
LLUIString mLabel;
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index a2116817a2..bccf88128d 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -33,6 +33,7 @@
// library includes
#include "lldbstrings.h"
+#include "llcheckboxctrl.h"
#include "lllslconstants.h"
#include "llnotifications.h"
#include "lluiconstants.h"
@@ -55,7 +56,7 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal;
LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)
-: LLToastPanel(notification),
+: LLCheckBoxToastPanel(notification),
LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID())
{
init(rect, show_images);
@@ -162,6 +163,11 @@ void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair
{
left = (max_width - btn_rect.getWidth()) / 2;
}
+ else if (left == 0 && buttons.size() == 2)
+ {
+ // Note: this and "size() == 1" shouldn't be inside the cycle, might be good idea to refactor whole placing process
+ left = (max_width - (btn_rect.getWidth() * 2) - h_pad) / 2;
+ }
else if (left + btn_rect.getWidth() > max_width)// whether there is still some place for button+h_pad in the mControlPanel
{
// looks like we need to add button to the next row
@@ -409,7 +415,20 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
//.xml file intially makes info panel only follow left/right/top. This is so that when control buttons are added the info panel
//can shift upward making room for the buttons inside mControlPanel. After the buttons are added, the info panel can then be set to follow 'all'.
mInfoPanel->setFollowsAll();
- snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
+
+ // Add checkbox (one of couple types) if nessesary.
+ setCheckBoxes(HPAD * 2, 0, mInfoPanel);
+ if (mCheck)
+ {
+ mCheck->setFollows(FOLLOWS_BOTTOM | FOLLOWS_LEFT);
+ }
+ // Snap to message, then to checkbox if present
+ snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
+ if (mCheck)
+ {
+ S32 new_panel_height = mCheck->getRect().getHeight() + getRect().getHeight() + VPAD;
+ reshape(getRect().getWidth(), new_panel_height);
+ }
// reshape the panel to its previous size
if (current_rect.notEmpty())
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index e4a75acfda..a5a637c6fa 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -47,7 +47,7 @@ class LLNotificationForm;
* @deprecated this class will be removed after all toast panel types are
* implemented in separate classes.
*/
-class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>
+class LLToastNotifyPanel: public LLCheckBoxToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>
{
public:
/**
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index 7c624d5b50..100d5ee713 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "lldbstrings.h"
+#include "llcheckboxctrl.h"
#include "llpanelgenerictip.h"
#include "llpanelonlinestatus.h"
#include "llnotifications.h"
@@ -34,6 +35,8 @@
#include "lltoastpanel.h"
#include "lltoastscriptquestion.h"
+#include <boost/algorithm/string.hpp>
+
//static
const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32)
// 'magic numbers', consider initializing (512+20) part from xml/notifications
@@ -145,3 +148,108 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(
return res;
}
+
+LLCheckBoxToastPanel::LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf)
+: LLToastPanel(p_ntf),
+mCheck(NULL)
+{
+
+}
+
+void LLCheckBoxToastPanel::setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view)
+{
+ std::string ignore_label;
+ LLNotificationFormPtr form = mNotification->getForm();
+
+ if (form->getIgnoreType() == LLNotificationForm::IGNORE_CHECKBOX_ONLY)
+ {
+ // Normally text is only used to describe notification in preferences,
+ // but this one is not displayed in preferences and works on case by case
+ // basis.
+ // Display text if present, display 'always chose' if not.
+ std::string ignore_message = form->getIgnoreMessage();
+ if (ignore_message.empty())
+ {
+ ignore_message = LLNotifications::instance().getGlobalString("alwayschoose");
+ }
+ setCheckBox(ignore_message, ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+}
+
+bool LLCheckBoxToastPanel::setCheckBox(const std::string& check_title,
+ const std::string& check_control,
+ const commit_signal_t::slot_type& cb,
+ const S32 &h_pad,
+ const S32 &v_pad,
+ LLView *parent_view)
+{
+ mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
+
+ if (!mCheck)
+ {
+ return false;
+ }
+
+ const LLFontGL* font = mCheck->getFont();
+ const S32 LINE_HEIGHT = font->getLineHeight();
+
+ std::vector<std::string> lines;
+ boost::split(lines, check_title, boost::is_any_of("\n"));
+
+ // Extend dialog for "check next time"
+ S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * h_pad;
+ S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
+ max_msg_width = llmax(max_msg_width, check_width);
+ S32 dialog_width = max_msg_width + 2 * h_pad;
+
+ S32 dialog_height = LLToastPanel::getRect().getHeight();
+ dialog_height += LINE_HEIGHT * lines.size();
+ dialog_height += LINE_HEIGHT / 2;
+
+ LLToastPanel::reshape(dialog_width, dialog_height, FALSE);
+
+ S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
+
+ // set check_box's attributes
+ LLRect check_rect;
+ // if we are part of the toast, we need to leave space for buttons
+ S32 msg_y = v_pad + (parent_view ? 0 : (BTN_HEIGHT + LINE_HEIGHT / 2));
+ mCheck->setRect(check_rect.setOriginAndSize(msg_x, msg_y, max_msg_width, LINE_HEIGHT*lines.size()));
+ mCheck->setLabel(check_title);
+ mCheck->setCommitCallback(cb);
+
+ if (parent_view)
+ {
+ // assume that width and height autoadjusts to toast
+ parent_view->addChild(mCheck);
+ }
+ else
+ {
+ LLToastPanel::addChild(mCheck);
+ }
+
+ return true;
+}
+
+void LLCheckBoxToastPanel::onCommitCheckbox(LLUICtrl* ctrl)
+{
+ BOOL check = ctrl->getValue().asBoolean();
+ if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+ {
+ // question was "show again" so invert value to get "ignore"
+ check = !check;
+ }
+ mNotification->setIgnored(check);
+}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 6a9b72a5ae..f4c758ade9 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -64,4 +64,23 @@ protected:
S32 computeSnappedToMessageHeight(LLTextBase* message, S32 maxLineCount);
};
+class LLCheckBoxCtrl;
+
+// Wrapper with support for 'don't ask again' checkbox
+class LLCheckBoxToastPanel : public LLToastPanel
+{
+public:
+ LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf);
+ virtual ~LLCheckBoxToastPanel() {};
+
+ // set checkboxes acording to defaults from form
+ void setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+ // set single checkbox
+ bool setCheckBox(const std::string&, const std::string&, const commit_signal_t::slot_type& cb, const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+protected:
+ void onCommitCheckbox(LLUICtrl* ctrl);
+
+ LLCheckBoxCtrl* mCheck;
+};
+
#endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index b5d78f3654..c5e31ff8e6 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -115,6 +115,12 @@ BOOL LLTool::handleScrollWheel(S32 x, S32 y, S32 clicks)
return FALSE;
}
+BOOL LLTool::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ // by default, didn't handle it
+ return FALSE;
+}
+
BOOL LLTool::handleDoubleClick(S32 x,S32 y,MASK mask)
{
// LL_INFOS() << "LLTool::handleDoubleClick" << LL_ENDL;
diff --git a/indra/newview/lltool.h b/indra/newview/lltool.h
index c5bad9d532..308983afda 100644
--- a/indra/newview/lltool.h
+++ b/indra/newview/lltool.h
@@ -57,6 +57,7 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index f66211ef34..7d77a8983f 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1728,6 +1728,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id))
{
+ // Legacy
return ACCEPT_NO;
}
@@ -2154,6 +2155,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
if(gInventory.isObjectDescendentOf(category->getUUID(), outbox_id))
{
+ // Legacy
return ACCEPT_NO;
}
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index f6eb290bc3..3fcf193dec 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -355,7 +355,7 @@ bool LLToolMgr::inBuildMode()
bool LLToolMgr::canAccessMarketplace()
{
- return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT) || gSavedSettings.getBOOL("InventoryOutboxDisplayBoth");
+ return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT);
}
void LLToolMgr::toggleMarketplace(const LLSD& sdname)
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 47227f987d..6c1ae7159b 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -208,6 +208,11 @@ BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks)
return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
}
+BOOL LLToolPie::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+}
+
// True if you selected an object.
BOOL LLToolPie::handleLeftClickPick()
{
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 95d155a474..fe0acfe473 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -50,6 +50,7 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual void render();
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index f475ab7d66..846a8e62a1 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -69,6 +69,7 @@
#include "llfloaterevent.h"
#include "llfloaterflickr.h"
#include "llfloaterfonttest.h"
+#include "llfloaterforgetuser.h"
#include "llfloatergesture.h"
#include "llfloatergodtools.h"
#include "llfloatergridstatus.h"
@@ -235,6 +236,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>);
LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);
+ LLFloaterReg::add("forget_username", "floater_forget_user.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterForgetUser>);
LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 61857d6fb1..394af27dc6 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1745,7 +1745,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
{
std::string type_name = userdata.asString();
- if (("inbox" == type_name) || ("outbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
+ if (("inbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
{
LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index a27a083a2a..2365f050b3 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -57,6 +57,7 @@
#include "llviewercontrol.h"
#include "llviewermenufile.h" // LLFilePickerThread
#include "llviewernetwork.h"
+#include "llviewerparcelaskplay.h"
#include "llviewerparcelmedia.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
@@ -77,7 +78,6 @@
#include <boost/bind.hpp> // for SkinFolder listener
#include <boost/signals2.hpp>
-/*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable";
/*static*/ const char* LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING = "MediaShowOnOthers";
/*static*/ const char* LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING = "MediaShowWithinParcel";
/*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel";
@@ -1005,12 +1005,14 @@ void LLViewerMedia::setAllMediaPaused(bool val)
}
}
+ LLParcel *agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
// Also do Parcel Media and Parcel Audio
if (!val)
{
if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
{
- LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+ LLViewerParcelMedia::play(agent_parcel);
}
static LLCachedControl<bool> audio_streaming_music(gSavedSettings, "AudioStreamingMusic", true);
@@ -1038,6 +1040,12 @@ void LLViewerMedia::setAllMediaPaused(bool val)
LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
}
}
+
+ // remove play choice for current parcel
+ if (agent_parcel && gAgent.getRegion())
+ {
+ LLViewerParcelAskPlay::getInstance()->resetSetting(gAgent.getRegion()->getRegionID(), agent_parcel->getLocalID());
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -3778,7 +3786,7 @@ void LLViewerMediaImpl::setTextureID(LLUUID id)
bool LLViewerMediaImpl::isAutoPlayable() const
{
return (mMediaAutoPlay &&
- gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+ gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0 &&
gSavedSettings.getBOOL("MediaTentativeAutoPlay"));
}
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index e2e758befb..b25358ae6c 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -76,7 +76,6 @@ class LLViewerMedia
public:
// String to get/set media autoplay in gSavedSettings
- static const char* AUTO_PLAY_MEDIA_SETTING;
static const char* SHOW_MEDIA_ON_OTHERS_SETTING;
static const char* SHOW_MEDIA_WITHIN_PARCEL_SETTING;
static const char* SHOW_MEDIA_OUTSIDE_PARCEL_SETTING;
@@ -315,6 +314,7 @@ public:
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; };
+ /*virtual*/ BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks) { return FALSE; };
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; };
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 1566736f17..8ef37b9143 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -401,23 +401,20 @@ void set_merchant_SLM_menu()
void check_merchant_status(bool force)
{
- if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth"))
+ if (force)
{
- if (force)
- {
- // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
- LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
- }
- // Hide SLM related menu item
- gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);
-
- // Also disable the toolbar button for Marketplace Listings
- LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
- gToolBarView->enableCommand(command->id(), false);
-
- // Launch an SLM test connection to get the merchant status
- LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
+ // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
+ LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
}
+ // Hide SLM related menu item
+ gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);
+
+ // Also disable the toolbar button for Marketplace Listings
+ LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
+ gToolBarView->enableCommand(command->id(), false);
+
+ // Launch an SLM test connection to get the merchant status
+ LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
}
void init_menus()
diff --git a/indra/newview/llviewerparcelaskplay.cpp b/indra/newview/llviewerparcelaskplay.cpp
new file mode 100644
index 0000000000..d4aa783f12
--- /dev/null
+++ b/indra/newview/llviewerparcelaskplay.cpp
@@ -0,0 +1,301 @@
+/**
+ * @file llviewerparcelaskplay.cpp
+ * @brief stores data about parcel media user wants to auto-play and shows related notifications
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, Linden Research, 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerparcelaskplay.h"
+
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llparcel.h"
+#include "llstartup.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llagent.h"
+#include "llsdserialize.h"
+
+#include <boost/lexical_cast.hpp>
+
+
+// class LLViewerParcelAskPlay
+
+LLViewerParcelAskPlay::LLViewerParcelAskPlay() :
+pNotification(NULL)
+{
+}
+
+LLViewerParcelAskPlay::~LLViewerParcelAskPlay()
+{
+
+}
+
+void LLViewerParcelAskPlay::initSingleton()
+{
+
+}
+void LLViewerParcelAskPlay::cleanupSingleton()
+{
+ cancelNotification();
+}
+
+void LLViewerParcelAskPlay::askToPlay(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, ask_callback cb)
+{
+ EAskPlayMode mode = getPlayMode(region_id, parcel_id);
+
+ switch (mode)
+ {
+ case ASK_PLAY_IGNORE:
+ cb(region_id, parcel_id, url, false);
+ break;
+ case ASK_PLAY_PLAY:
+ cb(region_id, parcel_id, url, true);
+ break;
+ case ASK_PLAY_ASK:
+ default:
+ {
+ // create or re-create notification
+ cancelNotification();
+
+ if (LLStartUp::getStartupState() > STATE_PRECACHE)
+ {
+ LLSD args;
+ args["URL"] = url;
+ LLSD payload;
+ payload["url"] = url; // or we can extract it from notification["substitutions"]
+ payload["parcel_id"] = parcel_id;
+ payload["region_id"] = region_id;
+ pNotification = LLNotificationsUtil::add("ParcelPlayingMedia", args, payload, boost::bind(onAskPlayResponse, _1, _2, cb));
+ }
+ else
+ {
+ // workaround: avoid 'new notifications arrived' on startup and just play
+ // (alternative: move to different channel, may be create new one...)
+ cb(region_id, parcel_id, url, true);
+ }
+ }
+ }
+}
+
+void LLViewerParcelAskPlay::cancelNotification()
+{
+ if (pNotification)
+ {
+ if (!pNotification->isCancelled())
+ {
+ // Force a responce
+ // Alternative is to mark notification as unique
+ pNotification->setIgnored(false);
+ LLNotifications::getInstance()->cancel(pNotification);
+ }
+ pNotification = NULL;
+ }
+}
+
+void LLViewerParcelAskPlay::resetCurrentParcelSetting()
+{
+ LLParcel *agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (agent_parcel && gAgent.getRegion())
+ {
+ LLViewerParcelAskPlay::resetSetting(gAgent.getRegion()->getRegionID(), agent_parcel->getLocalID());
+ }
+}
+
+void LLViewerParcelAskPlay::resetSetting(const LLUUID &region_id, const S32 &parcel_id)
+{
+ region_map_t::iterator found = mRegionMap.find(region_id);
+ if (found != mRegionMap.end())
+ {
+ found->second.erase(parcel_id);
+ }
+}
+
+void LLViewerParcelAskPlay::resetSettings()
+{
+ if (LLViewerParcelAskPlay::instanceExists())
+ {
+ LLViewerParcelAskPlay::getInstance()->mRegionMap.clear();
+ }
+ LLFile::remove(getAskPlayFilename());
+}
+
+void LLViewerParcelAskPlay::setSetting(const LLUUID &region_id, const S32 &parcel_id, const LLViewerParcelAskPlay::ParcelData &data)
+{
+ mRegionMap[region_id][parcel_id] = data;
+}
+
+LLViewerParcelAskPlay::ParcelData* LLViewerParcelAskPlay::getSetting(const LLUUID &region_id, const S32 &parcel_id)
+{
+ region_map_t::iterator found = mRegionMap.find(region_id);
+ if (found != mRegionMap.end())
+ {
+ parcel_data_map_t::iterator found_parcel = found->second.find(parcel_id);
+ if (found_parcel != found->second.end())
+ {
+ return &(found_parcel->second);
+ }
+ }
+ return NULL;
+}
+
+LLViewerParcelAskPlay::EAskPlayMode LLViewerParcelAskPlay::getPlayMode(const LLUUID &region_id, const S32 &parcel_id)
+{
+ EAskPlayMode mode = ASK_PLAY_ASK;
+ ParcelData* data = getSetting(region_id, parcel_id);
+ if (data)
+ {
+ mode = data->mMode;
+ // refresh date
+ data->mDate = LLDate::now();
+ }
+ return mode;
+}
+
+void LLViewerParcelAskPlay::setPlayMode(const LLUUID &region_id, const S32 &parcel_id, LLViewerParcelAskPlay::EAskPlayMode mode)
+{
+ ParcelData data;
+ data.mMode = mode;
+ data.mDate = LLDate::now();
+ setSetting(region_id, parcel_id, data);
+}
+
+//static
+void LLViewerParcelAskPlay::onAskPlayResponse(const LLSD& notification, const LLSD& response, ask_callback cb)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ LLUUID region_id = notification["payload"]["region_id"];
+ S32 parcel_id = notification["payload"]["parcel_id"];
+ std::string url = notification["payload"]["url"];
+
+ bool play = option == 1;
+
+ cb(region_id, parcel_id, url, play);
+
+ LLViewerParcelAskPlay *inst = getInstance();
+ bool save_choice = inst->pNotification->isIgnored(); // checkbox selected
+ if (save_choice)
+ {
+ EAskPlayMode mode = (play) ? ASK_PLAY_PLAY : ASK_PLAY_IGNORE;
+ inst->setPlayMode(region_id, parcel_id, mode);
+ }
+}
+
+// static
+std::string LLViewerParcelAskPlay::getAskPlayFilename()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "media_autoplay.xml");
+}
+
+void LLViewerParcelAskPlay::loadSettings()
+{
+ mRegionMap.clear();
+
+ std::string path = getAskPlayFilename();
+ if (!gDirUtilp->fileExists(path))
+ {
+ return;
+ }
+
+ LLSD autoplay_llsd;
+ llifstream file;
+ file.open(path.c_str());
+ if (!file.is_open())
+ {
+ return;
+ }
+ S32 status = LLSDSerialize::fromXML(autoplay_llsd, file);
+ file.close();
+
+ if (status == LLSDParser::PARSE_FAILURE || !autoplay_llsd.isMap())
+ {
+ return;
+ }
+
+ for (LLSD::map_const_iterator iter_region = autoplay_llsd.beginMap();
+ iter_region != autoplay_llsd.endMap(); ++iter_region)
+ {
+ LLUUID region_id = LLUUID(iter_region->first);
+ mRegionMap[region_id] = parcel_data_map_t();
+
+ const LLSD &parcel_map = iter_region->second;
+
+ if (parcel_map.isMap())
+ {
+ for (LLSD::map_const_iterator iter_parcel = parcel_map.beginMap();
+ iter_parcel != parcel_map.endMap(); ++iter_parcel)
+ {
+ if (!iter_parcel->second.isMap())
+ {
+ break;
+ }
+ S32 parcel_id = boost::lexical_cast<S32>(iter_parcel->first.c_str());
+ ParcelData data;
+ data.mMode = (EAskPlayMode)(iter_parcel->second["mode"].asInteger());
+ data.mDate = iter_parcel->second["date"].asDate();
+ mRegionMap[region_id][parcel_id] = data;
+ }
+ }
+ }
+}
+
+void LLViewerParcelAskPlay::saveSettings()
+{
+ LLSD write_llsd;
+ std::string key;
+ for (region_map_t::iterator iter_region = mRegionMap.begin();
+ iter_region != mRegionMap.end(); ++iter_region)
+ {
+ if (iter_region->second.empty())
+ {
+ continue;
+ }
+ key = iter_region->first.asString();
+ write_llsd[key] = LLSD();
+
+ for (parcel_data_map_t::iterator iter_parcel = iter_region->second.begin();
+ iter_parcel != iter_region->second.end(); ++iter_parcel)
+ {
+ if ((iter_parcel->second.mDate.secondsSinceEpoch() + (F64SecondsImplicit)U32Days(30)) > LLTimer::getTotalSeconds())
+ {
+ // write unexpired parcels
+ std::string parcel_id = boost::lexical_cast<std::string>(iter_parcel->first);
+ write_llsd[key][parcel_id] = LLSD();
+ write_llsd[key][parcel_id]["mode"] = (LLSD::Integer)iter_parcel->second.mMode;
+ write_llsd[key][parcel_id]["date"] = iter_parcel->second.mDate;
+ }
+ }
+ }
+
+ llofstream file;
+ file.open(getAskPlayFilename().c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(write_llsd, file);
+ file.close();
+ }
+}
+
diff --git a/indra/newview/llviewerparcelaskplay.h b/indra/newview/llviewerparcelaskplay.h
new file mode 100644
index 0000000000..dc711917d2
--- /dev/null
+++ b/indra/newview/llviewerparcelaskplay.h
@@ -0,0 +1,89 @@
+/**
+ * @file llviewerparcelaskplay.h
+ * @brief stores data about parcel media user wants to auto-play and shows related notifications
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, Linden Research, 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LLVIEWERPARCELASKPLAY_H
+#define LLVIEWERPARCELASKPLAY_H
+
+#include "llnotificationptr.h"
+#include "lluuid.h"
+
+class LLViewerParcelAskPlay : public LLSingleton<LLViewerParcelAskPlay>
+{
+ LLSINGLETON(LLViewerParcelAskPlay);
+ ~LLViewerParcelAskPlay();
+ void initSingleton();
+ void cleanupSingleton();
+public:
+ // functor expects functor(region_id, parcel_id, url, play/stop)
+ typedef boost::function<void(const LLUUID&, const S32&, const std::string&, const bool&)> ask_callback;
+ void askToPlay(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, ask_callback cb);
+ void cancelNotification();
+
+ void resetCurrentParcelSetting();
+ void resetSetting(const LLUUID &region_id, const S32 &parcel_id);
+ static void resetSettings();
+
+ void loadSettings();
+ void saveSettings();
+
+ S32 hasData() { return !mRegionMap.empty(); } // subsitution for 'isInitialized'
+
+private:
+ enum EAskPlayMode{
+ ASK_PLAY_IGNORE = 0,
+ ASK_PLAY_PLAY,
+ ASK_PLAY_ASK
+ };
+
+ class ParcelData
+ {
+ public:
+ LLDate mDate;
+ EAskPlayMode mMode;
+ };
+
+ void setSetting(const LLUUID &region_id, const S32 &parcel_id, const ParcelData &data);
+ ParcelData* getSetting(const LLUUID &region_id, const S32 &parcel_id);
+ EAskPlayMode getPlayMode(const LLUUID &region_id, const S32 &parcel_id);
+ void setPlayMode(const LLUUID &region_id, const S32 &parcel_id, EAskPlayMode);
+
+ static void onAskPlayResponse(const LLSD& notification, const LLSD& response, ask_callback cb);
+
+ static std::string getAskPlayFilename();
+
+private:
+ // Variables
+
+ typedef std::map<S32, ParcelData> parcel_data_map_t;
+ typedef std::map<LLUUID, parcel_data_map_t> region_map_t;
+ region_map_t mRegionMap;
+
+ // only one notification is supposed to exists and be visible
+ LLNotificationPtr pNotification;
+};
+
+
+#endif // LLVIEWERPARCELASKPLAY_H
diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp
index 57ee583eae..b4dc6932be 100644
--- a/indra/newview/llviewerparcelmediaautoplay.cpp
+++ b/indra/newview/llviewerparcelmediaautoplay.cpp
@@ -24,17 +24,20 @@
* $/LicenseInfo$
*/
+
#include "llviewerprecompiledheaders.h"
+
#include "llviewerparcelmediaautoplay.h"
-#include "llviewerparcelmedia.h"
+
+#include "llparcel.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
-#include "llviewerregion.h"
-#include "llparcel.h"
+#include "llviewerparcelaskplay.h"
+#include "llviewerparcelmedia.h"
#include "llviewerparcelmgr.h"
-#include "lluuid.h"
-#include "message.h"
+#include "llviewerregion.h"
#include "llviewertexturelist.h" // for texture stats
+#include "message.h"
#include "llagent.h"
#include "llmimetypes.h"
@@ -141,11 +144,28 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
{
if (this_parcel)
{
- if (gSavedSettings.getBOOL("ParcelMediaAutoPlayEnable"))
+ static LLCachedControl<S32> autoplay_mode(gSavedSettings, "ParcelMediaAutoPlayEnable");
+
+ switch (autoplay_mode())
{
- // and last but not least, only play when autoplay is enabled
- LLViewerParcelMedia::play(this_parcel);
- }
+ case 0:
+ // Disabled
+ break;
+ case 1:
+ // Play, default value for ParcelMediaAutoPlayEnable
+ LLViewerParcelMedia::play(this_parcel);
+ break;
+ case 2:
+ default:
+ {
+ // Ask
+ LLViewerParcelAskPlay::getInstance()->askToPlay(this_region->getRegionID(),
+ this_parcel->getLocalID(),
+ this_parcel->getMediaURL(),
+ onStartMusicResponse);
+ break;
+ }
+ }
}
mPlayed = TRUE;
@@ -158,5 +178,18 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
return FALSE; // continue ticking forever please.
}
-
+//static
+void LLViewerParcelMediaAutoPlay::onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play)
+{
+ if (play)
+ {
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ // make sure we are still there
+ if (parcel->getLocalID() == parcel_id && gAgent.getRegion()->getRegionID() == region_id)
+ {
+ LLViewerParcelMedia::play(parcel);
+ }
+ }
+}
diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h
index a052362829..a404f60da1 100644
--- a/indra/newview/llviewerparcelmediaautoplay.h
+++ b/indra/newview/llviewerparcelmediaautoplay.h
@@ -41,6 +41,9 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer
static void playStarted();
private:
+ static void onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play);
+
+ private:
S32 mLastParcelID;
LLUUID mLastRegionID;
BOOL mPlayed;
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 416d5d8e2e..86cdf96e21 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -42,6 +42,7 @@
// Viewer includes
#include "llagent.h"
#include "llagentaccess.h"
+#include "llviewerparcelaskplay.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
//#include "llfirstuse.h"
@@ -1832,6 +1833,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
// Only update stream if parcel changed (recreated) or music is playing (enabled)
if (!agent_parcel_update || gSavedSettings.getBOOL("MediaTentativeAutoPlay"))
{
+ LLViewerParcelAskPlay::getInstance()->cancelNotification();
std::string music_url_raw = parcel->getMusicURL();
// Trim off whitespace from front and back
@@ -1843,7 +1845,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
{
if (music_url.substr(0, 7) == "http://")
{
- optionally_start_music(music_url);
+ LLViewerRegion *region = LLWorld::getInstance()->getRegion(msg->getSender());
+ optionally_start_music(music_url, parcel->mLocalID, region->getRegionID());
}
else
{
@@ -1864,25 +1867,61 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
else
{
// Public land has no music
+ LLViewerParcelAskPlay::getInstance()->cancelNotification();
LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
}
}//if gAudiop
};
}
-void LLViewerParcelMgr::optionally_start_music(const std::string& music_url)
+//static
+void LLViewerParcelMgr::onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play)
{
- if (gSavedSettings.getBOOL("AudioStreamingMusic"))
+ if (play)
+ {
+ LL_INFOS("ParcelMgr") << "Starting parcel music " << url << LL_ENDL;
+ LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(url);
+ }
+}
+
+void LLViewerParcelMgr::optionally_start_music(const std::string &music_url, const S32 &local_id, const LLUUID &region_id)
+{
+ static LLCachedControl<bool> streaming_music(gSavedSettings, "AudioStreamingMusic", true);
+ if (streaming_music)
{
+ static LLCachedControl<S32> autoplay_mode(gSavedSettings, "ParcelMediaAutoPlayEnable", 1);
+ static LLCachedControl<bool> tentative_autoplay(gSavedSettings, "MediaTentativeAutoPlay", true);
// only play music when you enter a new parcel if the UI control for this
// was not *explicitly* stopped by the user. (part of SL-4878)
LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();
- if ((nearby_media_panel &&
- nearby_media_panel->getParcelAudioAutoStart()) ||
- // or they have expressed no opinion in the UI, but have autoplay on...
- (!nearby_media_panel &&
- gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
- gSavedSettings.getBOOL("MediaTentativeAutoPlay")))
+
+ // ask mode //todo constants
+ if (autoplay_mode == 2)
+ {
+ // stop previous stream
+ LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
+
+ // if user set media to play - ask
+ if ((nearby_media_panel && nearby_media_panel->getParcelAudioAutoStart())
+ || (!nearby_media_panel && tentative_autoplay))
+ {
+ LLViewerParcelAskPlay::getInstance()->askToPlay(region_id,
+ local_id,
+ music_url,
+ onStartMusicResponse);
+ }
+ else
+ {
+ LLViewerParcelAskPlay::getInstance()->cancelNotification();
+ }
+ }
+ // autoplay
+ else if ((nearby_media_panel
+ && nearby_media_panel->getParcelAudioAutoStart())
+ // or they have expressed no opinion in the UI, but have autoplay on...
+ || (!nearby_media_panel
+ && autoplay_mode == 1
+ && tentative_autoplay))
{
LL_INFOS("ParcelMgr") << "Starting parcel music " << music_url << LL_ENDL;
LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(music_url);
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 29219843c9..288077fafc 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -268,7 +268,8 @@ public:
// *NOTE: Taken out 2005-03-21. Phoenix.
//void makeLandmarkAtSelection();
- static void optionally_start_music(const std::string& music_url);
+ static void onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play);
+ static void optionally_start_music(const std::string &music_url, const S32 &local_id, const LLUUID &region_id);
static void processParcelOverlay(LLMessageSystem *msg, void **user_data);
static void processParcelProperties(LLMessageSystem *msg, void **user_data);
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 15b2ac8acf..85d87a43af 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -359,16 +359,19 @@ void update_statistics()
record(LLStatViewer::REBUILD_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Sort Draw State")));
record(LLStatViewer::RENDER_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Render Geometry")));
- LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
- if (cdp)
+ if (gAgent.getRegion() && isAgentAvatarValid())
{
- sample(LLStatViewer::SIM_PING, F64Milliseconds (cdp->getPingDelay()));
- gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1);
- gSimPingCount++;
- }
- else
- {
- sample(LLStatViewer::SIM_PING, U32Seconds(10));
+ LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
+ if (cdp)
+ {
+ sample(LLStatViewer::SIM_PING, F64Milliseconds(cdp->getPingDelay()));
+ gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1);
+ gSimPingCount++;
+ }
+ else
+ {
+ sample(LLStatViewer::SIM_PING, U32Seconds(10));
+ }
}
if (LLViewerStats::instance().getRecording().getSum(LLStatViewer::FPS))
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ea846805c2..72df31cb5f 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1587,6 +1587,11 @@ void LLViewerWindow::handleScrollWheel(LLWindow *window, S32 clicks)
handleScrollWheel( clicks );
}
+void LLViewerWindow::handleScrollHWheel(LLWindow *window, S32 clicks)
+{
+ handleScrollHWheel(clicks);
+}
+
void LLViewerWindow::handleWindowBlock(LLWindow *window)
{
send_agent_pause();
@@ -3004,6 +3009,49 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
return;
}
+void LLViewerWindow::handleScrollHWheel(S32 clicks)
+{
+ LLUI::resetMouseIdleTimer();
+
+ LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+ if (mouse_captor)
+ {
+ S32 local_x;
+ S32 local_y;
+ mouse_captor->screenPointToLocal(mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y);
+ mouse_captor->handleScrollHWheel(local_x, local_y, clicks);
+ if (LLView::sDebugMouseHandling)
+ {
+ LL_INFOS() << "Scroll Horizontal Wheel handled by captor " << mouse_captor->getName() << LL_ENDL;
+ }
+ return;
+ }
+
+ LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+ if (top_ctrl)
+ {
+ S32 local_x;
+ S32 local_y;
+ top_ctrl->screenPointToLocal(mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y);
+ if (top_ctrl->handleScrollHWheel(local_x, local_y, clicks)) return;
+ }
+
+ if (mRootView->handleScrollHWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks))
+ {
+ if (LLView::sDebugMouseHandling)
+ {
+ LL_INFOS() << "Scroll Horizontal Wheel" << LLView::sMouseHandlerMessage << LL_ENDL;
+ }
+ return;
+ }
+ else if (LLView::sDebugMouseHandling)
+ {
+ LL_INFOS() << "Scroll Horizontal Wheel not handled by view" << LL_ENDL;
+ }
+
+ return;
+}
+
void LLViewerWindow::addPopup(LLView* popup)
{
if (mPopupView)
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index d084642fdc..385bbd57e5 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -208,6 +208,7 @@ public:
/*virtual*/ void handleMenuSelect(LLWindow *window, S32 menu_item);
/*virtual*/ BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height);
/*virtual*/ void handleScrollWheel(LLWindow *window, S32 clicks);
+ /*virtual*/ void handleScrollHWheel(LLWindow *window, S32 clicks);
/*virtual*/ BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ void handleWindowBlock(LLWindow *window);
/*virtual*/ void handleWindowUnblock(LLWindow *window);
@@ -326,6 +327,7 @@ public:
BOOL handleKey(KEY key, MASK mask);
BOOL handleKeyUp(KEY key, MASK mask);
void handleScrollWheel (S32 clicks);
+ void handleScrollHWheel (S32 clicks);
// add and remove views from "popup" layer
void addPopup(LLView* popup);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bd73c234a6..eb2d3bf873 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -973,7 +973,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
mDeferredLight.release();
}
- F32 scale = RenderShadowResolutionScale;
+ F32 scale = llmax(0.f, RenderShadowResolutionScale);
if (shadow_detail > 0)
{ //allocate 4 sun shadow maps
@@ -8685,8 +8685,8 @@ void LLPipeline::renderDeferredLighting()
}
const LLViewerObject *vobj = drawablep->getVObj();
- if(vobj && vobj->getAvatar()
- && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()))
+ if((vobj && vobj->getAvatar() && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()))
+ || (vobj && dist_vec(vobj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip))
{
continue;
}
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 5aba0546f3..9b18dbc2e2 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -144,7 +144,6 @@ with the same filename but different name
<texture name="Command_MiniCart_Icon" file_name="toolbar_icons/mini_cart.png" preload="true" />
<texture name="Command_MiniMap_Icon" file_name="toolbar_icons/mini_map.png" preload="true" />
<texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" />
- <texture name="Command_Outbox_Icon" file_name="toolbar_icons/outbox.png" preload="true" />
<texture name="Command_People_Icon" file_name="toolbar_icons/people.png" preload="true" />
<texture name="Command_Picks_Icon" file_name="toolbar_icons/picks.png" preload="true" />
<texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" />
diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml
index 4dd64cba2a..8f55b3297f 100644
--- a/indra/newview/skins/default/xui/de/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_about_land.xml
@@ -30,7 +30,7 @@
<floater.string name="Always">
Immer
</floater.string>
- <tab_container name="landtab" tab_min_width="40" width="489">
+ <tab_container name="landtab" tab_min_width="40">
<panel label="ALLGEMEIN" name="land_general_panel">
<panel.string name="new users only">
Nur neue Benutzer
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
index 550a99fe0a..51c82c97f8 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
@@ -13,7 +13,7 @@
<item label="Mittel" name="Medium" value="1"/>
<item label="Groß" name="Large" value="2"/>
</combo_box>
- <check_box label="Blasen-Chat" name="bubble_text_chat"/>
+ <check_box label="Blasen-Chat" name="bubble_text_chat" left_delta="8"/>
</panel>
<panel name="im_notification_settings">
<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
index ff0a6614bd..e0aa9fe4a9 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
@@ -3,10 +3,10 @@
<text name="preset_text">
(Keine)
</text>
- <text name="QualitySpeed">
+ <text name="QualitySpeed" top_delta="20">
Qualität und Geschwindigkeit:
</text>
- <text name="ShadersPrefText">
+ <text name="ShadersPrefText" top_delta="15">
Niedrig
</text>
<text name="ShadersPrefText2">
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 9f853fd960..a143adfa06 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1800,7 +1800,7 @@ Only large parcels can be listed in search.
Music URL:
</text>
<line_editor
- follows="left|top"
+ follows="left|top|right"
height="23"
layout="topleft"
left="100"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
index bac3ea86f1..6540f5e348 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
@@ -28,11 +28,13 @@
name="scroll_content_panel"
follows="left|top"
min_height="300"
+ min_width="300"
layout="topleft"
top="0"
background_visible="false"
left="0"
- height="680">
+ height="1165"
+ width="1015">
<text
type="string"
length="1"
@@ -102,6 +104,14 @@ Textures
name="hair_alpha"
top_delta="0"
width="92" />
+ <texture_picker
+ height="103"
+ label="Hair Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="hair_tattoo"
+ top_delta="0"
+ width="92" />
<texture_picker
height="103"
@@ -135,6 +145,14 @@ Textures
name="head_tattoo"
top_delta="0"
width="92" />
+ <texture_picker
+ height="103"
+ label="Head Unv Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="head_universal_tattoo"
+ top_delta="0"
+ width="92" />
<texture_picker
height="103"
@@ -160,6 +178,14 @@ Textures
name="eyes_alpha"
top_delta="0"
width="92" />
+ <texture_picker
+ height="103"
+ label="Eyes Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="eyes_tattoo"
+ top_delta="0"
+ width="92" />
<texture_picker
height="103"
@@ -225,6 +251,14 @@ Textures
name="upper_tattoo"
top_delta="0"
width="92" />
+ <texture_picker
+ height="103"
+ label="Upper Unv Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="upper_universal_tattoo"
+ top_delta="0"
+ width="92" />
<texture_picker
height="103"
@@ -298,6 +332,14 @@ Textures
name="lower_tattoo"
top_delta="0"
width="92" />
+ <texture_picker
+ height="103"
+ label="Lower Unv Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="lower_universal_tattoo"
+ top_delta="0"
+ width="92" />
<texture_picker
height="103"
@@ -315,6 +357,99 @@ Textures
name="skirt"
top_delta="0"
width="92" />
+ <texture_picker
+ height="103"
+ label="Skirt Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="skirt_tattoo"
+ top_delta="0"
+ width="92" />
+
+ <texture_picker
+ height="103"
+ label="Left Arm"
+ layout="topleft"
+ left="10"
+ name="leftarm-baked"
+ top_delta="100"
+ width="92" />
+ <texture_picker
+ height="103"
+ label="Left Arm Tattoo"
+ layout="topleft"
+ left_pad="21"
+ name="leftarm_tattoo"
+ top_delta="0"
+ width="92" />
+
+ <texture_picker
+ height="103"
+ label="Left Leg"
+ layout="topleft"
+ left="10"
+ name="leftleg-baked"
+ top_delta="100"
+ width="92" />
+ <texture_picker
+ height="103"
+ label="Left Leg Tattoo"
+ layout="topleft"
+ left_pad="21"
+ name="leftleg_tattoo"
+ top_delta="0"
+ width="92" />
+
+ <texture_picker
+ height="103"
+ label="AUX 1"
+ layout="topleft"
+ left="10"
+ name="aux1-baked"
+ top_delta="100"
+ width="92" />
+ <texture_picker
+ height="103"
+ label="AUX 1 Tattoo"
+ layout="topleft"
+ left_pad="21"
+ name="aux1_tattoo"
+ top_delta="0"
+ width="92" />
+
+ <texture_picker
+ height="103"
+ label="AUX 2"
+ layout="topleft"
+ left="10"
+ name="aux2-baked"
+ top_delta="100"
+ width="92" />
+ <texture_picker
+ height="103"
+ label="AUX 2 Tattoo"
+ layout="topleft"
+ left_pad="21"
+ name="aux2_tattoo"
+ top_delta="0"
+ width="92" />
+
+ <texture_picker
+ height="103"
+ label="AUX 3"
+ layout="topleft"
+ left="10"
+ name="aux3-baked"
+ top_delta="100"
+ width="92" />
+ <texture_picker
+ height="103"
+ label="AUX 3 Tattoo"
+ layout="topleft"
+ left_pad="21"
+ name="aux3_tattoo"
+ top_delta="0"
+ width="92" />
</panel>
</panel>
</scroll_container>
diff --git a/indra/newview/skins/default/xui/en/floater_forget_user.xml b/indra/newview/skins/default/xui/en/floater_forget_user.xml
new file mode 100644
index 0000000000..f2e894733f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_forget_user.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="258"
+ layout="topleft"
+ name="groups"
+ help_topic="forget_username"
+ title="REMEMBERED USERNAMES"
+ width="280">
+ <scroll_list
+ height="173"
+ layout="topleft"
+ left="12"
+ name="user_list"
+ top="24"
+ width="256">
+ <scroll_list.columns
+ name="user"
+ width="248" />
+ </scroll_list>
+ <button
+ height="20"
+ label="Forget"
+ label_selected="Forget"
+ layout="topleft"
+ left_delta="90"
+ name="forget"
+ top_pad="8"
+ width="80" />
+ <check_box
+ height="20"
+ label="Also delete local data for this username"
+ layout="topleft"
+ left="15"
+ name="delete_data"
+ top_pad="5"
+ width="260"
+ initial_value="1"
+ tooltip="Deletes local files: chat history, last session screenshot, browser cookies, teleport history, toolbar settings, e t c"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
deleted file mode 100644
index 7802f65902..0000000000
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<floater
- positioning="cascading"
- can_close="true"
- can_resize="true"
- height="440"
- help_topic="floater_merchant_outbox"
- min_width="300"
- min_height="200"
- name="floater_merchant_outbox"
- save_rect="true"
- save_visibility="false"
- reuse_instance="true"
- title="MERCHANT OUTBOX"
- width="333">
- <string name="OutboxFolderCount0"></string>
- <string name="OutboxFolderCount1">1 folder</string>
- <string name="OutboxFolderCountN">[NUM] folders</string>
- <string name="OutboxImporting">Sending folders...</string>
- <string name="OutboxInitializing">Initializing...</string>
- <panel
- name="panel_1"
- follows="all"
- layout="topleft"
- left="0"
- top="0"
- label=""
- height="440"
- width="333">
- <panel
- name="panel_2"
- follows="all"
- left="10"
- bottom="370"
- width="313"
- top="0"
- bg_opaque_color="InventoryBackgroundColor">
- <panel
- name="outbox_inventory_placeholder_panel"
- follows="all"
- layout="topleft"
- top="0"
- left="0"
- width="308"
- height="370"
- bg_opaque_color="InventoryBackgroundColor">
- <text
- name="outbox_inventory_placeholder_title"
- type="string"
- follows="top|left|right"
- layout="topleft"
- top="10"
- left="0"
- width="308"
- height="25"
- wrap="true"
- halign="center"
- font="SansSerifBold">
- Loading...
- </text>
- <text
- name="outbox_inventory_placeholder_text"
- type="string"
- follows="top|left|right"
- layout="topleft"
- top="35"
- left="0"
- width="308"
- height="130"
- wrap="true"
- halign="left" />
- </panel>
- </panel>
- <panel
- name="panel_3"
- follows="bottom|left|right"
- left="10"
- bottom="435"
- width="313"
- top="370">
- <panel
- name="outbox_generic_drag_target"
- mouse_opaque="false"
- follows="all"
- top="5"
- left="5"
- width="303"
- height="25"
- background_visible="false"
- bg_alpha_color="EmphasisColor_35"
- border="true"
- bevel_style="in"
- visible="true">
- <text
- name="text_1"
- type="string"
- follows="all"
- layout="topleft"
- top="6"
- height="20"
- left="5"
- width="293"
- halign="center"
- font="SansSerifMedium"
- font_shadow="hard"
- valign="top">
- Drag items here to create folders
- </text>
- </panel>
- <text
- name="outbox_folder_count"
- type="string"
- follows="all"
- layout="topleft"
- top="40"
- left="5"
- width="150"
- height="20"
- wrap="true"
- halign="left"
- valign="center"
- font="SansSerif"/>
- <button
- label="Send to Marketplace"
- tool_tip="Push to my Marketplace Storefront"
- is_toggle="false"
- name="outbox_import_btn"
- follows="bottom|right"
- tab_stop="false"
- halign="center"
- top="37"
- left="160"
- height="25"
- width="150"
- enabled="false" />
- </panel>
- <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
- <layout_panel />
- <layout_panel height="24" auto_resize="false">
- <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all">
- <layout_panel width="0" />
- <layout_panel width="24" auto_resize="false">
- <loading_indicator
- height="24"
- layout="topleft"
- left="0"
- top="0"
- width="24" />
- </layout_panel>
- <layout_panel width="0" />
- </layout_stack>
- </layout_panel>
- <layout_panel />
- </layout_stack>
- </panel>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_trash.xml b/indra/newview/skins/default/xui/en/floater_preview_trash.xml
index 9e50e89ac9..3fa71e7bfe 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_trash.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_trash.xml
@@ -14,7 +14,7 @@
reuse_instance="true"
can_minimize="false">
<inventory_panel
- name="inventory_outbox"
+ name="inventory_trash"
start_folder.name="Trash"
show_empty_message="false"
start_folder.type="trash"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index ab42b76b3b..af185d43b0 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -154,13 +154,16 @@
<menu_item_call.on_click
function="Tools.StopAllAnimations" />
</menu_item_call>
- <menu_item_call
+ <menu_item_check
label="Walk / run / fly..."
name="WalkRunFly">
- <menu_item_call.on_click
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="moveview" />
+ <menu_item_check.on_click
function="Floater.ToggleOrBringToFront"
parameter="moveview" />
- </menu_item_call>
+ </menu_item_check>
</menu>
<menu
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 30e8f7cedc..a757a4beaa 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2180,7 +2180,7 @@ Wrong chunk size in WAV file:
icon="alertmodal.tga"
name="SoundFileInvalidTooLong"
type="alertmodal">
-Audio file is too long (10 second maximum):
+Audio file is too long (30 second maximum):
[FILE]
<tag>fail</tag>
</notification>
@@ -2259,6 +2259,7 @@ Unable to create output file: [FILE]
icon="alertmodal.tga"
name="DoNotSupportBulkAnimationUpload"
type="alertmodal">
+ <unique/>
[APP_NAME] does not currently support bulk upload of BVH format animation files.
<tag>fail</tag>
</notification>
@@ -3440,6 +3441,9 @@ Display settings have been set to recommended levels because of a change to the
icon="alertmodal.tga"
name="ErrorMessage"
type="alertmodal">
+ <unique>
+ <context>ERROR_MESSAGE</context>
+ </unique>
[ERROR_MESSAGE]
<tag>fail</tag>
<usetemplate
@@ -6053,6 +6057,34 @@ Would you like to turn off Do Not Disturb before completing this transaction?
</notification>
<notification
+ icon="notify.tga"
+ label="Parcel is Playing Media"
+ name="ParcelPlayingMedia"
+ persist="false"
+ type="notify">
+This land has media:
+[URL]
+Would you like to play it?
+ <tag>confirm</tag>
+ <form name="form">
+ <ignore name="ignore"
+ checkbox_only="true"
+ text="Always choose this option for this land."/>
+ <button
+ ignore="Play Media"
+ index="1"
+ name="Yes"
+ text="Play"/>
+ <button
+ default="true"
+ ignore="Ignore Media"
+ index="0"
+ name="No"
+ text="Ignore"/>
+ </form>
+ </notification>
+
+ <notification
icon="alertmodal.tga"
name="ConfirmDeleteProtectedCategory"
type="alertmodal">
@@ -6164,6 +6196,20 @@ Are you sure you want to permanently delete the contents of your Lost And Found?
<notification
icon="alertmodal.tga"
+ name="ConfirmReplaceLink"
+ type="alertmodal">
+You're about to replace '[TYPE]' body part link with the item which doesn't match the type.
+Are you sure you want to proceed?
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm before I replace link"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CopySLURL"
type="alertmodal">
The following SLurl has been copied to your clipboard:
diff --git a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
index 27c653bc35..d1175a9fe1 100644
--- a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
@@ -32,7 +32,6 @@
width="308"/>
<texture_picker
allow_no_texture="true"
- border_enabled="true"
fallback_image="default_land_picture.j2c"
enabled="false"
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
index 3509eaa285..e846edf1d4 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
@@ -144,7 +144,6 @@
follows="left|top|right"
height="100"
width="273"
- hide_scrollbar="false"
layout="topleft"
left="10"
top_pad="2"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 7759d4fdb2..d601b36ce5 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -57,19 +57,15 @@
combo_editor.prevalidate_callback="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
- width="232">
+ width="206">
<combo_box.combo_editor
text_pad_left="8"
bg_image_always_focused="true"/>
- <combo_box.combo_button
- visible="false" />
- <combo_box.drop_down_button
- visible="false" />
</combo_box>
<line_editor
follows="left|top"
height="32"
- left_pad="-11"
+ left_pad="15"
max_length_chars="16"
text_pad_left="8"
name="password_edit"
@@ -119,36 +115,49 @@
width="120"
height="32"
left_pad="15"
- bottom_delta="0" />
+ bottom_delta="0" />
+ <text
+ follows="left|top"
+ font="SansSerifLarge"
+ font.style="BOLD"
+ text_color="EmphasisColor"
+ height="34"
+ name="sign_up_text"
+ left_pad="10"
+ width="200"
+ valign="center">
+ Sign up
+ </text>
<check_box
- control_name="RememberPassword"
follows="left|top"
font="SansSerifMedium"
left="185"
- bottom_delta="21"
+ bottom_delta="21"
height="24"
label="Remember me"
check_button.bottom="3"
- name="remember_check"
+ name="remember_name"
+ tooltip="Already recorded user can be forgotten from preferences."
width="145" />
- <text
+ <check_box
+ control_name="RememberPassword"
follows="left|top"
font="SansSerifMedium"
text_color="EmphasisColor"
height="16"
- name="forgot_password_text"
- left="408"
+ left="408"
bottom_delta="0"
- width="200">
- Forgotten password
- </text>
+ label="Remember password"
+ check_button.bottom="3"
+ name="remember_check"
+ width="145" />
<combo_box
allow_text_entry="false"
font="SansSerifTiny"
follows="left|top"
height="26"
left="588"
- bottom_delta="10"
+ bottom_delta="8"
max_chars="128"
label="Select grid"
layout="topleft"
@@ -159,12 +168,13 @@
font="SansSerifMedium"
text_color="EmphasisColor"
height="16"
- name="sign_up_text"
+ name="forgot_password_text"
left="778"
- bottom_delta="-10"
- width="200">
- Sign up
- </text>
+ bottom_delta="-8"
+ width="120"
+ halign="center">
+ Password help
+ </text>
</layout_panel>
<layout_panel
height="172"
diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
deleted file mode 100644
index b2d8bb874b..0000000000
--- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<inventory_panel
- name="inventory_outbox"
- start_folder.name="Outbox"
- show_empty_message="false"
- start_folder.type="outbox"
- follows="all" layout="topleft"
- top="0" left="0" height="165" width="308"
- top_pad="0"
- bg_opaque_color="DkGray2"
- bg_alpha_color="DkGray2"
- background_visible="true"
- border="false"
- bevel_style="none"
- show_item_link_overlays="true"
- tool_tip="Drag and drop items here to prepare them for sale on your storefront"
- scroll.reserve_scroll_corner="false">
- <folder folder_arrow_image="Folder_Arrow"
- folder_indentation="8"
- item_height="20"
- item_top_pad="4"
- selection_image="Rounded_Square"
- left_pad="5"
- icon_pad="2"
- icon_width="16"
- text_pad="1"
- text_pad_right="4"
- arrow_size="12"
- max_folder_item_overlap="2"/>
- <item allow_wear="false"/>
-</inventory_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml
index 79d190e1e0..99c47eb825 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -103,7 +103,6 @@
height="100"
width="280"
parse_urls="true"
- hide_scrollbar="false"
layout="topleft"
left="10"
top_pad="2"
diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
index 43d580844f..4c0cdd321e 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
@@ -32,7 +32,6 @@
width="308" />
<texture_picker
allow_no_texture="true"
- border_enabled="true"
fallback_image="default_land_picture.j2c"
enabled="false"
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 8296438d4c..d0518aa245 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -248,14 +248,27 @@
top_pad="5"
width="237"/>
<button
+ follows="top|left"
+ layout="topleft"
+ label="Remembered Usernames"
+ name="remembered_usernames"
height="20"
- label="Default Creation Permissions"
+ left="30"
+ top_pad="16"
+ width="200">
+ <button.commit_callback
+ function="Pref.RememberedUsernames" />
+ </button>
+ <button
+ follows="top|left"
layout="topleft"
+ label="Default Creation Permissions"
name="default_creation_permissions"
+ height="20"
left="30"
- top_pad = "20"
- width="250">
- <button.commit_callback
- function="Pref.PermsDefault" />
+ top_pad="16"
+ width="200">
+ <button.commit_callback
+ function="Pref.PermsDefault" />
</button>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index 9e7023d2f2..ece6c95080 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -99,6 +99,7 @@
label="Bubble Chat"
layout="topleft"
top_pad="4"
+ left_delta="0"
name="bubble_text_chat"
width="330">
</check_box>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 649403184d..90f2ca2713 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -322,17 +322,40 @@
name="enable_voice_check"
width="110"/>
<!-- -->
- <check_box
- name="media_auto_play_btn"
- control_name="ParcelMediaAutoPlayEnable"
- enabled_control="AudioStreamingMedia"
- value="true"
- follows="left|bottom|right"
- height="15"
- tool_tip="Check this to let media auto-play if it wants"
- label="Allow Media to auto-play"
- top_pad="1"
- left="25"/>
+ <text
+ follows="left|top"
+ layout="topleft"
+ height="15"
+ left="0"
+ top_pad="3"
+ width="120"
+ halign="right"
+ name="media_autoplay_label">
+ Media auto-play
+ </text>
+ <combo_box
+ control_name="ParcelMediaAutoPlayEnable"
+ enabled_control="AudioStreamingMedia"
+ follows="left|top"
+ layout="topleft"
+ height="23"
+ left_pad="7"
+ top_delta="-4"
+ name="media_auto_play_combo"
+ width="100">
+ <item
+ label="Disabled"
+ name="autoplay_disabled"
+ value="0"/>
+ <item
+ label="Enabled"
+ name="autoplay_enabled"
+ value="1"/>
+ <item
+ label="Ask"
+ name="autoplay_ask"
+ value="2"/>
+ </combo_box>
<check_box
name="media_show_on_others_btn"
control_name="MediaShowOnOthers"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 292c2a6293..3a311db25c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2821,7 +2821,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="BuyingCosts">Buying this costs L$ [AMOUNT]</string>
<string name="UnknownFileExtension">
Unknown file extension .%s
-Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
+Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
</string>
<string name="MuteObject2">Block</string>
<string name="MuteAvatar">Block</string>
@@ -4098,7 +4098,6 @@ Try enclosing path to the editor with double quotes.
<string name="Command_MarketplaceListings_Label">Marketplace</string>
<string name="Command_MiniMap_Label">Mini-map</string>
<string name="Command_Move_Label">Walk / run / fly</string>
- <string name="Command_Outbox_Label">Merchant outbox</string>
<string name="Command_People_Label">People</string>
<string name="Command_Picks_Label">Picks</string>
<string name="Command_Places_Label">Places</string>
@@ -4130,7 +4129,6 @@ Try enclosing path to the editor with double quotes.
<string name="Command_MarketplaceListings_Tooltip">Sell your creation</string>
<string name="Command_MiniMap_Tooltip">Show nearby people</string>
<string name="Command_Move_Tooltip">Moving your avatar</string>
- <string name="Command_Outbox_Tooltip">Transfer items to your marketplace for sale</string>
<string name="Command_People_Tooltip">Friends, groups, and nearby people</string>
<string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string>
<string name="Command_Places_Tooltip">Places you've saved</string>
diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml
index 998d2a8863..57a1b2ec1e 100644
--- a/indra/newview/skins/default/xui/es/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_about_land.xml
@@ -362,7 +362,7 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
Foto:
</text>
<texture_picker label="" name="snapshot_ctrl" tool_tip="Pulse para elegir una imagen"/>
- <text name="allow_see_label">
+ <text name="allow_see_label" top="170">
Los avatares de otras parcelas pueden ver a los avatares de esta parcela y chatear con ellos
</text>
<check_box label="Ver los avatares" name="SeeAvatarsCheck" tool_tip="Permite que los avatares de otras parcelas vean a los avatares de ésta y chateen con ellos, y también que tú puedas verles y chatear con ellos." top="170"/>
@@ -444,7 +444,7 @@ los media:
<panel.string name="estate_override">
Una o más de esta opciones está configurada a nivel del estado
</panel.string>
- <check_box label="Cualquiera puede visitar (Si no seleccionas esta opción, se crearán líneas de prohibición)" name="public_access"/>
+ <check_box label="Cualquiera puede visitar" name="public_access" tool_tip="Si no seleccionas esta opción, se crearán líneas de prohibición"/>
<check_box label="Debe ser mayor de 18 [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Para poder acceder a esta parcela los Residentes deben ser mayores de 18 años. Para más información, consulta [SUPPORT_SITE]."/>
<check_box label="Debe haber información archivada sobre el pago [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Para poder acceder a esta parcela los Residentes deben haber aportado información de pago en su cuenta. Para más información, ver [SUPPORT_SITE]."/>
<check_box label="Permitir grupo [GROUP] sin restricciones" name="GroupCheck" tool_tip="Elija el grupo en la pestaña General."/>
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index 2c8848265f..dbff3fcf0e 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -60,7 +60,7 @@ no el objeto.
</text>
<button label="Comprar ahora" name="buy_btn"/>
<button label="Cancelar" name="cancel_btn"/>
- <text left="5" name="info_cannot_buy" right="-5">
+ <text name="info_cannot_buy" left="150" font="SansSerifBig">
No se pudo hacer la compra
</text>
<button label="Ir a la web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
index f7e036efd7..388a5d84d2 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
@@ -13,7 +13,7 @@
<item label="Medio" name="Medium" value="1"/>
<item label="Grande" name="Large" value="2"/>
</combo_box>
- <check_box label="Bocadillos del chat" name="bubble_text_chat"/>
+ <check_box label="Bocadillos del chat" name="bubble_text_chat" left_delta="30"/>
</panel>
<panel name="im_notification_settings">
<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
index 1b191d3e46..36888850c4 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
@@ -30,7 +30,7 @@
<combo_box.item label="Preguntarme cuando una actualización opcional está disponible para instalar" name="Install_ask"/>
<combo_box.item label="Instalar sólo actualizaciones obligatorias" name="Install_manual"/>
</combo_box>
- <check_box label="Admitir candidatos a la versión comercial a la hora de realizar actualizaciones" name="update_willing_to_test"/>
+ <check_box label="Admitir candidatos a la versión comercial a la hora de realizar actualizaciones" name="update_willing_to_test" left_delta="-20"/>
<check_box label="Mostrar las notas de la versión después de la actualización" name="update_show_release_notes"/>
<text name="Proxy Settings:">
Configuración de proxy:
diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml
index 219857eb99..fb65e71ee1 100644
--- a/indra/newview/skins/default/xui/fr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml
@@ -366,10 +366,10 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.
Photo :
</text>
<texture_picker label="" name="snapshot_ctrl" tool_tip="Cliquez pour sélectionner une image"/>
- <text name="allow_see_label">
+ <text name="allow_see_label" top="170">
Les avatars sur d&apos;autres parcelles peuvent voir et chatter avec les avatars sur cette parcelle.
</text>
- <check_box label="Voir les avatars" name="SeeAvatarsCheck" tool_tip="Permettre aux avatars présents sur d&apos;autres parcelles de voir et chatter avec les avatars présents sur cette parcelle et à vous de les voir et de chatter avec eux."/>
+ <check_box label="Voir les avatars" name="SeeAvatarsCheck" top="170" tool_tip="Permettre aux avatars présents sur d&apos;autres parcelles de voir et chatter avec les avatars présents sur cette parcelle et à vous de les voir et de chatter avec eux."/>
<text name="landing_point">
Lieu d&apos;arrivée : [LANDING]
</text>
@@ -449,7 +449,7 @@ musique :
<panel.string name="estate_override">
Au moins une de ces options est définie au niveau du domaine.
</panel.string>
- <check_box label="Tout le monde peut rendre visite (Des lignes d&apos;interdiction seront créées si cette case n&apos;est pas cochée)" name="public_access"/>
+ <check_box label="Tout le monde peut rendre visite" tool_tip="Des lignes d&apos;interdiction seront créées si cette case n&apos;est pas cochée" name="public_access"/>
<check_box label="Doit avoir plus de 18 ans [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Pour accéder à cette parcelle, les résidents doivent avoir au moins 18 ans. Consultez le [SUPPORT_SITE] pour plus d&apos;informations."/>
<check_box label="Les infos de paiement doivent être enregistrées dans le dossier [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Pour pouvoir accéder à cette parcelle, les résidents doivent avoir enregistré des informations de paiement. Consultez le [SUPPORT_SITE] pour plus d&apos;informations."/>
<check_box label="Autoriser le groupe [GROUP] sans restrictions" name="GroupCheck" tool_tip="Définir le groupe à l&apos;onglet Général."/>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index 148a5a35d2..c295172abf 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -60,7 +60,7 @@ le Lindex...
</text>
<button label="Acheter" name="buy_btn"/>
<button label="Annuler" name="cancel_btn"/>
- <text left="5" name="info_cannot_buy" right="-5" width="200">
+ <text name="info_cannot_buy" left="160" width="200">
Achat impossible
</text>
<button label="Accéder au Web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
index 422243445b..a0f2e0eba7 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
@@ -13,7 +13,7 @@
<item label="Moyenne" name="Medium" value="1"/>
<item label="Grande" name="Large" value="2"/>
</combo_box>
- <check_box label="Bulles de chat" name="bubble_text_chat"/>
+ <check_box label="Bulles de chat" name="bubble_text_chat" left_delta="45"/>
</panel>
<panel name="im_notification_settings">
<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml
index 0a7837e122..50e2d1a8de 100644
--- a/indra/newview/skins/default/xui/it/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_about_land.xml
@@ -367,10 +367,10 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
Fotografia:
</text>
<texture_picker label="" name="snapshot_ctrl" tool_tip="Clicca per scegliere una immagine"/>
- <text name="allow_see_label">
+ <text name="allow_see_label" top="170">
Gli avatar di altri lotti possono vedere gli avatar che si trovano in questo lotto e chattare con loro
</text>
- <check_box label="Vedi avatar" name="SeeAvatarsCheck" tool_tip="Consente ad avatar in altri lotti di vedere e chattare con avatar in questo lotto e viceversa."/>
+ <check_box label="Vedi avatar" top="170" name="SeeAvatarsCheck" tool_tip="Consente ad avatar in altri lotti di vedere e chattare con avatar in questo lotto e viceversa."/>
<text name="landing_point">
Punto di atterraggio: [LANDING]
</text>
@@ -449,7 +449,7 @@ Media:
<panel.string name="estate_override">
Una o più di queste impostazioni sono già impostate a livello regionale
</panel.string>
- <check_box label="Chiunque può visitare (Se si rimuove la selezione vengono create linee di espulsione)" name="public_access"/>
+ <check_box label="Chiunque può visitare" tool_tip="Se si rimuove la selezione vengono create linee di espulsione" name="public_access"/>
<check_box label="È necessario avere più di 18 anni [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Per poter visitare questo lotto i Residenti devono avere almeno 18 anni. Vedi [SUPPORT_SITE] per maggiori informazioni."/>
<check_box label="È necessario aver registrato le informazioni di pagamento [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Per poter visitare questo lotto i Residenti devono aver fornito informazioni di pagamento a Linden Lab. Vedi [SUPPORT_SITE] per maggiori informazioni."/>
<check_box label="Consenti gruppo [GRUPPO] senza restrizioni" name="GroupCheck" tool_tip="Imposta il gruppo nel pannello generale."/>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 743969f557..53a2057455 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -60,7 +60,7 @@ l&apos;oggetto.
</text>
<button label="Acquista" name="buy_btn"/>
<button label="Annulla" name="cancel_btn"/>
- <text left="5" name="info_cannot_buy" right="-5">
+ <text name="info_cannot_buy" left="160" font="SansSerifBig">
Non in grado di acquistare
</text>
<button label="Continua sul Web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml
index ef71baa0b6..96e54bb9bc 100644
--- a/indra/newview/skins/default/xui/pt/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml
@@ -362,10 +362,10 @@ Apenas lotes maiores podem ser listados na busca.
Foto:
</text>
<texture_picker label="" name="snapshot_ctrl" tool_tip="Clique para escolher uma imagem"/>
- <text name="allow_see_label">
+ <text name="allow_see_label" top="170">
Avatares em outros lotes podem ver e conversar com avatares neste lote
</text>
- <check_box label="Ver avatares" name="SeeAvatarsCheck" tool_tip="Permite que os avatares em outros lotes vejam e batam papo com avatares neste lote. Você poderá vê-los e conversar com eles."/>
+ <check_box label="Ver avatares" name="SeeAvatarsCheck" top="170" tool_tip="Permite que os avatares em outros lotes vejam e batam papo com avatares neste lote. Você poderá vê-los e conversar com eles."/>
<text name="landing_point">
Ponto de Aterrissagem: [LANDING]
</text>
diff --git a/indra/newview/skins/default/xui/ru/floater_about_land.xml b/indra/newview/skins/default/xui/ru/floater_about_land.xml
index 1ae6df76d9..222572b4bf 100644
--- a/indra/newview/skins/default/xui/ru/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about_land.xml
@@ -338,7 +338,7 @@
<check_box label="Все" name="check other scripts" tool_tip="Если установлен флажок, то жители могут выполнять скрипты на вашем участке, включая приложения."/>
<check_box label="Группа" name="check group scripts" tool_tip="Если установлен флажок, то члены группы могут выполнять скрипты на вашем участке, включая приложения."/>
<check_box label="Безопасно (нет повреждений)" name="check safe" tool_tip="Если отмечено, то земля считается безопасной, отключены боевые повреждения. Если не отмечено, то боевые повреждения включены."/>
- <check_box label="Не толкать" name="PushRestrictCheck" tool_tip="Запрещает скриптам функцию толкания. Этот параметр может оказаться полезным для предотвращения нежелательного поведения на вашей земле."/>
+ <check_box label="Не толкать" name="PushRestrictCheck" left_pad="44" tool_tip="Запрещает скриптам функцию толкания. Этот параметр может оказаться полезным для предотвращения нежелательного поведения на вашей земле."/>
<check_box label="Показать место в поиске (L$30/неделя)" name="ShowDirectoryCheck" tool_tip="Позволить людям видеть участок в результатах поиска"/>
<combo_box name="land category">
<combo_box.item label="Любая категория" name="item0"/>
@@ -360,10 +360,10 @@
Снимок:
</text>
<texture_picker name="snapshot_ctrl" tool_tip="Щелкните для выбора изображения"/>
- <text name="allow_see_label">
+ <text name="allow_see_label" left="283">
Аватары с других участков могут видеть аватары на этом участке и общаться с ними
</text>
- <check_box label="Видны аватары" name="SeeAvatarsCheck" tool_tip="Аватары с других участков смогут видеть аватары на этом участке и общаться с ними в чате, а вы также сможете видеть их и общаться с ними."/>
+ <check_box label="Видны аватары" left="262" name="SeeAvatarsCheck" tool_tip="Аватары с других участков смогут видеть аватары на этом участке и общаться с ними в чате, а вы также сможете видеть их и общаться с ними."/>
<text name="landing_point">
В точку телепортации: [LANDING]
</text>
@@ -372,7 +372,7 @@
<text name="Teleport Routing: ">
Вариант телепортации:
</text>
- <combo_box name="landing type" tool_tip="Вариант телепортации – выберите, каким образом будет производиться телепортация на вашу землю">
+ <combo_box name="landing type" width="150" tool_tip="Вариант телепортации – выберите, каким образом будет производиться телепортация на вашу землю">
<combo_box.item label="В черном списке" name="Blocked"/>
<combo_box.item label="В точку телепортации" name="LandingPoint"/>
<combo_box.item label="В любое место" name="Anywhere"/>
@@ -439,7 +439,7 @@
<panel.string name="estate_override">
Часть этих параметров установлена на уровне землевладения
</panel.string>
- <check_box label="Доступ открыт для всех (При снятия выделения будет создана запись в строке запрета)" name="public_access"/>
+ <check_box label="Доступ открыт для всех" tool_tip="При снятия выделения будет создана запись в строке запрета" name="public_access"/>
<check_box label="Должен быть 18 и старше [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Доступ к этому участку имеют только жители 18 лет и старше. Более подробная информация находится здесь: [SUPPORT_SITE]."/>
<check_box label="Информация о платежах должна быть в файле [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Для доступа к этому участку у жителя должна быть зарегистрирована информация об оплате. Более подробная информация находится здесь: [SUPPORT_SITE]."/>
<check_box label="Разрешить группе [GROUP] без всяких ограничений" name="GroupCheck" tool_tip="Группа устанавливается на основной вкладке."/>
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml b/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
index c2fcac8840..03a714f266 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_chat.xml
@@ -5,15 +5,15 @@
<check_box initial_value="true" label="Воспроизводить анимацию ввода текста при общении" name="play_typing_animation"/>
<check_box label="Отправлять мне сообщения по почте, когда меня нет в сети" name="send_im_to_email"/>
<check_box label="Только друзья и группы могут звонить мне и отправлять IM" name="voice_call_friends_only_check"/>
- <text name="font_size">
+ <text name="font_size" left="361">
Размер шрифта:
</text>
- <combo_box name="chat_font_size">
+ <combo_box name="chat_font_size" left="361">
<item label="Мелкий" name="Small" value="0"/>
<item label="Средний" name="Medium" value="1"/>
<item label="Крупный" name="Large" value="2"/>
</combo_box>
- <check_box label="Чат в пузырьках" name="bubble_text_chat"/>
+ <check_box label="Чат в пузырьках" name="bubble_text_chat" left_delta="19"/>
</panel>
<panel name="im_notification_settings">
<text name="friend_ims">
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
index d4d0ef9e7c..137e047d97 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml
@@ -14,7 +14,7 @@
<text name="Web:">
Браузер:
</text>
- <radio_group name="preferred_browser_behavior">
+ <radio_group name="preferred_browser_behavior" left_delta="30">
<radio_item label="Используйте встроенный браузер для всех ссылок" name="internal" tool_tip="Будет использоваться браузер, заданный в системе по умолчанию. Не рекомендуется, если [APP_NAME] работает в полноэкранном режиме." value="0"/>
<radio_item label="Для ссылок Second Life следует использовать только встроенный браузер" name="external" tool_tip="Используйте встроенный браузер для справки, веб-ссылок и т.д. Для ссылок LindenLab/Second Life следует использовать только встроенный браузер." value="1"/>
<radio_item label="Для всех ссылок следует использовать встроенный браузер" name="external_all" tool_tip="Для просмотра справки, ссылок на веб-страницы и т. д. будет использоваться встроенный браузер. Этот браузер открывается как новое окно в [APP_NAME]." value="2"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_about_land.xml b/indra/newview/skins/default/xui/tr/floater_about_land.xml
index 48b16e2fde..1101e5055a 100644
--- a/indra/newview/skins/default/xui/tr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about_land.xml
@@ -360,10 +360,10 @@ Sadece büyük parseller aramada görünür.
Anlık Görüntü:
</text>
<texture_picker name="snapshot_ctrl" tool_tip="Bir resim seçmek için tıklayın"/>
- <text name="allow_see_label">
+ <text name="allow_see_label" top="170">
Diğer parsellerdeki avatarlar bu parseldeki avatarları görebilir ve onlarla sohbet edebilir
</text>
- <check_box label="Avatarları Gör" name="SeeAvatarsCheck" tool_tip="Diğer parsellerdeki avatarların bu parseldeki avatarları görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/>
+ <check_box label="Avatarları Gör" name="SeeAvatarsCheck" top="170" tool_tip="Diğer parsellerdeki avatarların bu parseldeki avatarları görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/>
<text name="landing_point">
İniş Noktası: [LANDING]
</text>
diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp
index d7e87ed52e..a1005c654c 100644
--- a/indra/newview/tests/llsecapi_test.cpp
+++ b/indra/newview/tests/llsecapi_test.cpp
@@ -60,12 +60,21 @@ LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(X509* openssl_cert
LLPointer<LLCertificateChain> LLSecAPIBasicHandler::getCertificateChain(const X509_STORE_CTX* chain) { return NULL; }
LLPointer<LLCertificateStore> LLSecAPIBasicHandler::getCertificateStore(const std::string& store_id) { return NULL; }
void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type, const std::string& data_id, const LLSD& data) {}
+void LLSecAPIBasicHandler::addToProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem, const LLSD& data) {}
+void LLSecAPIBasicHandler::removeFromProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem) {}
LLSD LLSecAPIBasicHandler::getProtectedData(const std::string& data_type, const std::string& data_id) { return LLSD(); }
void LLSecAPIBasicHandler::deleteProtectedData(const std::string& data_type, const std::string& data_id) {}
LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string& grid, const LLSD& identifier, const LLSD& authenticator) { return NULL; }
LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid) { return NULL; }
void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool save_authenticator) {}
void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred) {}
+bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const std::string& grid) { return false; }
+void LLSecAPIBasicHandler::loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map) {}
+LLPointer<LLCredential> LLSecAPIBasicHandler::loadFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey) { return NULL; }
+void LLSecAPIBasicHandler::addToCredentialMap(const std::string& storage, LLPointer<LLCredential> cred, bool save_authenticator) {}
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, LLPointer<LLCredential> cred) {}
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey) {}
+void LLSecAPIBasicHandler::removeCredentialMap(const std::string& storage, const std::string& grid) {}
// -------------------------------------------------------------------------------------------
// TUT