diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index 0aa1d9da6e..73c59bc62b 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -90,18 +90,27 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) } mLabel = LLUICtrlFactory::create (tbparams); mLabel->reshapeToFitText(); + LLRect label_rect = mLabel->getRect(); + if (mLabel->getLineCount() > 1) + { + // reshapeToFitText uses LLView::reshape() which always reshapes + // from bottom to top, but we want to extend the bottom + // Note: might be better idea to use getRect().mTop of LLCheckBoxCtrl (+pad) as top point of new rect + S32 delta = ll_round((F32)mLabel->getFont()->getLineHeight() * mLabel->getLineSpacingMult()) - label_rect.getHeight(); + label_rect.translate(0, delta); + mLabel->setRect(label_rect); + } + addChild(mLabel); - LLRect label_rect = mLabel->getRect(); - // Button - // Note: button cover the label by extending all the way to the right. + // Note: button cover the label by extending all the way to the right and down. LLRect btn_rect = p.check_button.rect(); btn_rect.setOriginAndSize( btn_rect.mLeft, - btn_rect.mBottom, + llmin(btn_rect.mBottom, label_rect.mBottom), llmax(btn_rect.mRight, label_rect.mRight - btn_rect.mLeft), - llmax( label_rect.getHeight(), btn_rect.mTop)); + llmax(label_rect.getHeight(), btn_rect.mTop)); std::string active_true_id, active_false_id; std::string inactive_true_id, inactive_false_id; @@ -162,17 +171,26 @@ void LLCheckBoxCtrl::clear() void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) { - + S32 label_top = mLabel->getRect().mTop; mLabel->reshapeToFitText(); LLRect label_rect = mLabel->getRect(); + if (label_top != label_rect.mTop) + { + // reshapeToFitText uses LLView::reshape() which always reshapes + // from bottom to top, but we want to extend the bottom so + // reposition control + S32 delta = label_top - label_rect.mTop; + label_rect.translate(0, delta); + mLabel->setRect(label_rect); + } // Button - // Note: button cover the label by extending all the way to the right. + // Note: button cover the label by extending all the way to the right and down. LLRect btn_rect = mButton->getRect(); btn_rect.setOriginAndSize( btn_rect.mLeft, - btn_rect.mBottom, + llmin(btn_rect.mBottom, label_rect.mBottom), llmax(btn_rect.getWidth(), label_rect.mRight - btn_rect.mLeft), llmax(label_rect.mTop - btn_rect.mBottom, btn_rect.getHeight())); mButton->setShape(btn_rect); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index ab921f008a..89652b5e6b 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -474,6 +474,8 @@ public: S32 getVPad() { return mVPad; } S32 getHPad() { return mHPad; } + F32 getLineSpacingMult() { return mLineSpacingMult; } + S32 getLineSpacingPixels() { return mLineSpacingPixels; } // only for multiline S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line = true) const; LLRect getLocalRectFromDocIndex(S32 pos) const; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9e0d45e4a4..10c810783e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -743,7 +743,8 @@ LLAppViewer::LLAppViewer() mReportedCrash(false), mNumSessions(0), mPurgeCache(false), - mPurgeOnExit(false), + mPurgeCacheOnExit(false), + mPurgeUserDataOnExit(false), mSecondInstance(false), mSavedFinalSnapshot(false), mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. @@ -2333,7 +2334,7 @@ bool LLAppViewer::cleanup() LLConversationLog::instance().cache(); } - if (mPurgeOnExit) + if (mPurgeCacheOnExit) { LL_INFOS() << "Purging all cache files on exit" << LL_ENDL; gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); @@ -2376,6 +2377,14 @@ bool LLAppViewer::cleanup() } } + if (mPurgeUserDataOnExit) + { + // Ideally we should not save anything from this session since it is going to be purged now, + // but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code + std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId(); + gDirUtilp->deleteDirAndContents(user_path); + } + // Delete workers first // shotdown all worker threads before deleting them in case of co-dependencies mAppCoreHttp.requestStop(); @@ -5312,7 +5321,7 @@ void LLAppViewer::badNetworkHandler() // Flush all of our caches on exit in the case of disconnect due to // invalid packets. - mPurgeOnExit = TRUE; + mPurgeCacheOnExit = TRUE; std::ostringstream message; message << diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 4471399ef1..cb85fd3276 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -202,6 +202,7 @@ public: void addOnIdleCallback(const boost::function& cb); // add a callback to fire (once) when idle + void purgeUserDataOnExit() { mPurgeUserDataOnExit = true; } void purgeCache(); // Clear the local cache. void purgeCacheImmediate(); //clear local cache immediately. S32 updateTextureThreads(F32 max_time); @@ -299,9 +300,10 @@ private: std::string mSerialNumber; bool mPurgeCache; + bool mPurgeCacheOnExit; + bool mPurgeUserDataOnExit; bool mPurgeSettings; // bool mPurgeTextures; // FIRE-13066 - bool mPurgeOnExit; LLViewerJoystick* joystick; bool mSavedFinalSnapshot; diff --git a/indra/newview/llfloaterforgetuser.cpp b/indra/newview/llfloaterforgetuser.cpp index 3b0d48a5d6..4e955c7e02 100644 --- a/indra/newview/llfloaterforgetuser.cpp +++ b/indra/newview/llfloaterforgetuser.cpp @@ -29,11 +29,15 @@ #if 0 #include "llfloaterforgetuser.h" +#include "llappviewer.h" #include "llcheckboxctrl.h" #include "llfavoritesbar.h" +#include "llnotificationsutil.h" #include "llpanellogin.h" // for helper function getUserName() and to repopulate list if nessesary #include "llscrolllistctrl.h" #include "llsecapi.h" +#include "llstartup.h" +#include "llviewercontrol.h" #include "llviewernetwork.h" @@ -54,55 +58,66 @@ LLFloaterForgetUser::~LLFloaterForgetUser() BOOL LLFloaterForgetUser::postBuild() { - // Note, storage works per grid, whatever is selected currently in login screen or logged in. - // Since login screen can change grid, store the value. - mGrid = LLGridManager::getInstance()->getGrid(); + mScrollList = getChild("user_list"); - LLScrollListCtrl *scroll_list = getChild("user_list"); - if (gSecAPIHandler->hasCredentialMap("login_list", mGrid)) + + bool show_grid_marks = gSavedSettings.getBOOL("ForceShowGrid"); + show_grid_marks |= !LLGridManager::getInstance()->isInProductionGrid(); + + std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); + + if (!show_grid_marks) { - 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) + // Figure out if there are records for more than one grid in storage + for (std::map::iterator grid_iter = known_grids.begin(); + grid_iter != known_grids.end(); + grid_iter++) { - if (cr_iter->second.notNull()) // basic safety + if (!grid_iter->first.empty() + && grid_iter->first != MAINGRID) // a workaround since 'mIsInProductionGrid' might not be set { - 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); + if (!gSecAPIHandler->emptyCredentialMap("login_list", grid_iter->first)) + { + show_grid_marks = true; + break; + } + + // "Legacy" viewer support + LLPointer cred = gSecAPIHandler->loadCredential(grid_iter->first); + if (cred.notNull()) + { + const LLSD &ident = cred->getIdentifier(); + if (ident.isMap() && ident.has("type")) + { + show_grid_marks = true; + break; + } + } } - cr_iter++; } - scroll_list->selectFirstItem(); + } + + mUserGridsCount.clear(); + if (!show_grid_marks) + { + // just load maingrid + loadGridToList(MAINGRID, false); } else { - LLPointer cred = gSecAPIHandler->loadCredential(mGrid); - if (cred.notNull()) + for (std::map::iterator grid_iter = known_grids.begin(); + grid_iter != known_grids.end(); + grid_iter++) { - const LLSD &ident = cred->getIdentifier(); - if (ident.isMap() && ident.has("type")) + if (!grid_iter->first.empty()) { - 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(); + loadGridToList(grid_iter->first, true); } } } - bool enable_button = scroll_list->getFirstSelectedIndex() != -1; + mScrollList->selectFirstItem(); + bool enable_button = mScrollList->getFirstSelectedIndex() != -1; LLCheckBoxCtrl *chk_box = getChild("delete_data"); chk_box->setEnabled(enable_button); chk_box->set(FALSE); @@ -115,36 +130,88 @@ BOOL LLFloaterForgetUser::postBuild() void LLFloaterForgetUser::onForgetClicked() { - mLoginPanelDirty = true; LLScrollListCtrl *scroll_list = getChild("user_list"); - std::string user_key = scroll_list->getSelectedValue(); + LLSD user_data = scroll_list->getSelectedValue(); + const std::string user_id = user_data["user_id"]; - // remove creds - gSecAPIHandler->removeFromCredentialMap("login_list", mGrid, user_key); - - LLPointer cred = gSecAPIHandler->loadCredential(mGrid); - if (cred.notNull() && cred->userID() == user_key) - { - gSecAPIHandler->deleteCredential(cred); - } - - // Clean data LLCheckBoxCtrl *chk_box = getChild("delete_data"); BOOL delete_data = chk_box->getValue(); - if (delete_data) + + if (delete_data && mUserGridsCount[user_id] > 1) { - // 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. + // more than 1 grid uses this id + LLNotificationsUtil::add("LoginRemoveMultiGridUserData", LLSD(), LLSD(), boost::bind(&LLFloaterForgetUser::onConfirmForget, this, _1, _2)); + return; } + processForgetUser(); +} + +bool LLFloaterForgetUser::onConfirmForget(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + processForgetUser(); + } + return false; +} + +// static +bool LLFloaterForgetUser::onConfirmLogout(const LLSD& notification, const LLSD& response, const std::string &fav_id, const std::string &grid) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + // Remove creds + gSecAPIHandler->removeFromCredentialMap("login_list", grid, LLStartUp::getUserId()); + + LLPointer cred = gSecAPIHandler->loadCredential(grid); + if (cred.notNull() && cred->userID() == LLStartUp::getUserId()) + { + gSecAPIHandler->deleteCredential(cred); + } + + // Clean favorites + LLFavoritesOrderStorage::removeFavoritesRecordOfUser(fav_id, grid); + + // mark data for removal + LLAppViewer::instance()->purgeUserDataOnExit(); + LLAppViewer::instance()->requestQuit(); + } + return false; +} + +void LLFloaterForgetUser::processForgetUser() +{ + LLScrollListCtrl *scroll_list = getChild("user_list"); + LLCheckBoxCtrl *chk_box = getChild("delete_data"); + BOOL delete_data = chk_box->getValue(); + LLSD user_data = scroll_list->getSelectedValue(); + const std::string user_id = user_data["user_id"]; + const std::string grid = user_data["grid"]; + const std::string user_name = user_data["label"]; // for favorites + + if (delete_data && user_id == LLStartUp::getUserId() && LLStartUp::getStartupState() > STATE_LOGIN_WAIT) + { + // we can't delete data for user that is currently logged in + // we need to pass grid because we are deleting data universal to grids, but specific grid's user + LLNotificationsUtil::add("LoginCantRemoveCurUsername", LLSD(), LLSD(), boost::bind(onConfirmLogout, _1, _2, user_name, grid)); + return; + } + + // key is used for name of user's folder and in credencials + // user_name is edentical to favorite's username + forgetUser(user_id, user_name, grid, delete_data); + mLoginPanelDirty = true; + if (delete_data) + { + mUserGridsCount[user_id] = 0; //no data left to care about + } + else + { + mUserGridsCount[user_id]--; + } // Update UI scroll_list->deleteSelectedItems(); @@ -156,5 +223,126 @@ void LLFloaterForgetUser::onForgetClicked() chk_box->setEnabled(false); } } + +//static +void LLFloaterForgetUser::forgetUser(const std::string &userid, const std::string &fav_id, const std::string &grid, bool delete_data) +{ + // Remove creds + gSecAPIHandler->removeFromCredentialMap("login_list", grid, userid); + + LLPointer cred = gSecAPIHandler->loadCredential(grid); + if (cred.notNull() && cred->userID() == userid) + { + gSecAPIHandler->deleteCredential(cred); + } + + // Clean data + if (delete_data) + { + std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + userid; + gDirUtilp->deleteDirAndContents(user_path); + + // Clean favorites + LLFavoritesOrderStorage::removeFavoritesRecordOfUser(fav_id, grid); + + // 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. + } +} + +void LLFloaterForgetUser::loadGridToList(const std::string &grid, bool show_grid_name) +{ + std::string grid_label; + if (show_grid_name) + { + grid_label = LLGridManager::getInstance()->getGridId(grid); //login id (shortened label) + } + if (gSecAPIHandler->hasCredentialMap("login_list", grid)) + { + LLSecAPIHandler::credential_map_t credencials; + gSecAPIHandler->loadCredentialMap("login_list", grid, 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 + { + std::string user_label = LLPanelLogin::getUserName(cr_iter->second); + LLSD user_data; + user_data["user_id"] = cr_iter->first; + user_data["label"] = user_label; + user_data["grid"] = grid; + + if (show_grid_name) + { + user_label += " (" + grid_label + ")"; + } + + LLScrollListItem::Params item_params; + item_params.value(user_data); + item_params.columns.add() + .value(user_label) + .column("user") + .font(LLFontGL::getFontSansSerifSmall()); + mScrollList->addRow(item_params, ADD_BOTTOM); + + // Add one to grid count + std::map::iterator found = mUserGridsCount.find(cr_iter->first); + if (found != mUserGridsCount.end()) + { + found->second++; + } + else + { + mUserGridsCount[cr_iter->first] = 1; + } + } + cr_iter++; + } + } + else + { + // "Legacy" viewer support + LLPointer cred = gSecAPIHandler->loadCredential(grid); + if (cred.notNull()) + { + const LLSD &ident = cred->getIdentifier(); + if (ident.isMap() && ident.has("type")) + { + std::string user_label = LLPanelLogin::getUserName(cred); + LLSD user_data; + user_data["user_id"] = cred->userID(); + user_data["label"] = user_label; + user_data["grid"] = grid; + + if (show_grid_name) + { + user_label += " (" + grid_label + ")"; + } + + LLScrollListItem::Params item_params; + item_params.value(user_data); + item_params.columns.add() + .value(user_label) + .column("user") + .font(LLFontGL::getFontSansSerifSmall()); + mScrollList->addRow(item_params, ADD_BOTTOM); + + // Add one to grid count + std::map::iterator found = mUserGridsCount.find(cred->userID()); + if (found != mUserGridsCount.end()) + { + found->second++; + } + else + { + mUserGridsCount[cred->userID()] = 1; + } + } + } + } +} #endif diff --git a/indra/newview/llfloaterforgetuser.h b/indra/newview/llfloaterforgetuser.h index 30bb33b1f5..fb892fd5cc 100644 --- a/indra/newview/llfloaterforgetuser.h +++ b/indra/newview/llfloaterforgetuser.h @@ -29,6 +29,8 @@ #include "llfloater.h" +class LLScrollListCtrl; + class LLFloaterForgetUser : public LLFloater { public: @@ -39,8 +41,16 @@ public: void onForgetClicked(); private: + bool onConfirmForget(const LLSD& notification, const LLSD& response); + static bool onConfirmLogout(const LLSD& notification, const LLSD& response, const std::string &favorites_id, const std::string &grid); + void processForgetUser(); + static void forgetUser(const std::string &userid, const std::string &fav_id, const std::string &grid, bool delete_data); + void loadGridToList(const std::string &grid, bool show_grid_name); + + LLScrollListCtrl *mScrollList; + bool mLoginPanelDirty; - std::string mGrid; + std::map mUserGridsCount; }; #endif diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 58304174c0..ccb47f8221 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -562,7 +562,6 @@ void LLPanelLogin::populateFields(LLPointer credential, bool remem { sInstance->getChild("remember_name")->setValue(remember_user); sInstance->populateUserList(credential); - remember_check->setEnabled(remember_user); } } @@ -765,11 +764,8 @@ BOOL LLPanelLogin::areCredentialFieldsDirty() } else { - std::string username = sInstance->getChild("username_combo")->getValue().asString(); - LLStringUtil::trim(username); - std::string password = sInstance->getChild("password_edit")->getValue().asString(); LLComboBox* combo = sInstance->getChild("username_combo"); - if(combo && combo->isDirty()) + if (combo && combo->getCurrentIndex() == -1 && !combo->getValue().asString().empty()) { return true; } @@ -1114,14 +1110,22 @@ void LLPanelLogin::onUserListCommit(void*) } // static +// At the moment only happens if !mFirstLoginThisInstall void LLPanelLogin::onRememberUserCheck(void*) { - if (sInstance) + if (sInstance && !sInstance->mFirstLoginThisInstall) { LLCheckBoxCtrl* remember_name(sInstance->getChild("remember_name")); LLCheckBoxCtrl* remember_psswrd(sInstance->getChild("remember_check")); + LLComboBox* user_combo(sInstance->getChild("username_combo")); bool remember = remember_name->getValue().asBoolean(); + if (user_combo->getCurrentIndex() != -1 && !remember) + { + remember = true; + remember_name->setValue(true); + LLNotificationsUtil::add("LoginCantRemoveUsername"); + } remember_psswrd->setEnabled(remember); } } @@ -1150,8 +1154,30 @@ void LLPanelLogin::updateServer() try { // if they've selected another grid, we should load the credentials - // for that grid and set them to the UI. - if(!sInstance->areCredentialFieldsDirty()) + // for that grid and set them to the UI. But if there were any modifications to + // fields, modifications should carry over. + // Not sure if it should carry over password but it worked like this before login changes + // Example: you started typing in and found that your are under wrong grid, + // you switch yet don't lose anything + if (sInstance->areCredentialFieldsDirty()) + { + // save modified creds + LLComboBox* user_combo = sInstance->getChild("username_combo"); + LLLineEditor* pswd_edit = sInstance->getChild("password_edit"); + std::string username = user_combo->getSimple(); + LLStringUtil::trim(username); + std::string password = pswd_edit->getValue().asString(); + + // populate dropbox and setFields + // Note: following call is related to initializeLoginInfo() + LLPointer credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid()); + sInstance->populateUserList(credential); + + // restore creds + user_combo->setTextEntry(username); + pswd_edit->setValue(password); + } + else { // populate dropbox and setFields // Note: following call is related to initializeLoginInfo() @@ -1187,12 +1213,15 @@ void LLPanelLogin::updateLoginButtons() login_btn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0); - if (!mFirstLoginThisInstall) - { - LLComboBox* user_combo = getChild("username_combo"); - LLCheckBoxCtrl* remember_name = getChild("remember_name"); - remember_name->setEnabled(user_combo->getCurrentIndex() == -1); - } + if (!mFirstLoginThisInstall) + { + LLComboBox* user_combo = getChild("username_combo"); + LLCheckBoxCtrl* remember_name = getChild("remember_name"); + if (user_combo->getCurrentIndex() != -1) + { + remember_name->setValue(true); + } // Note: might be good idea to do "else remember_name->setValue(mRememberedState)" but it might behave 'weird' to user + } } void LLPanelLogin::populateUserList(LLPointer credential) @@ -1222,6 +1251,7 @@ void LLPanelLogin::populateUserList(LLPointer credential) { // selection failed, just deselect whatever might be selected user_combo->setValue(std::string()); + getChild("password_edit")->setValue(std::string()); } else { diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 1809c57968..dfd7aeb9e9 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -493,6 +493,10 @@ public: virtual bool hasCredentialMap(const std::string& storage, const std::string& grid)=0; + // returns true if map is empty or does not exist + virtual bool emptyCredentialMap(const std::string& storage, + const std::string& grid)=0; + // load map of credentials from specific storage typedef std::map > credential_map_t; virtual void loadCredentialMap(const std::string& storage, diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index dca4748115..7d13644ef0 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1676,6 +1676,19 @@ bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const st return credential.isMap(); } +// returns true if map is empty or does not exist +bool LLSecAPIBasicHandler::emptyCredentialMap(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() || credential.size() == 0; +} + // 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) { diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h index c3e338c9c2..59dc6f803a 100644 --- a/indra/newview/llsechandler_basic.h +++ b/indra/newview/llsechandler_basic.h @@ -295,6 +295,10 @@ public: virtual bool hasCredentialMap(const std::string& storage, const std::string& grid); + // returns true if map is empty or does not exist + virtual bool emptyCredentialMap(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, diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0154871f81..8c508405f2 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3640,6 +3640,15 @@ std::string& LLStartUp::getInitialOutfitName() return sInitialOutfit; } +std::string LLStartUp::getUserId() +{ + if (gUserCredential.isNull()) + { + return ""; + } + return gUserCredential->userID(); +} + // Loads a bitmap to display during load void init_start_screen(S32 location_id) { diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 981adc00a1..0de28c0f5d 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -125,6 +125,7 @@ public: static void saveInitialOutfit(); static std::string& getInitialOutfitName(); + static std::string getUserId(); static bool dispatchURL(); // if we have a SLURL or sim string ("Ahern/123/45") that started diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index aae8332235..e64ef4f056 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8876,10 +8876,24 @@ void LLPipeline::renderDeferredLighting() } const LLViewerObject *vobj = drawablep->getVObj(); - if((vobj && vobj->getAvatar() && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList())) - || (vobj && dist_vec(vobj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip)) + if (vobj) { - continue; + LLVOAvatar *av = vobj->getAvatar(); + if (av) + { + if (av->isTooComplex() || av->isInMuteList() || dist_vec(av->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip) + { + continue; + } + } + else + { + const LLViewerObject *root_obj = drawablep->getParent() ? drawablep->getParent()->getVObj() : vobj; + if (root_obj && dist_vec(root_obj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip) + { + continue; + } + } } LLVector4a center; diff --git a/indra/newview/skins/default/xui/en/floater_forget_user.xml b/indra/newview/skins/default/xui/en/floater_forget_user.xml index 86228d49ee..a9ec1b74a3 100644 --- a/indra/newview/skins/default/xui/en/floater_forget_user.xml +++ b/indra/newview/skins/default/xui/en/floater_forget_user.xml @@ -35,5 +35,5 @@ name="delete_data" top_pad="5" width="260" - tool_tip="Deletes local files: chat history, last session screenshot, browser cookies, teleport history, toolbar settings, e t c"/> + tool_tip="Deletes local files: chat history, last session screenshot, browser cookies, teleport history, toolbar settings, e t c. Some of local files are shared between grids."/> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 8f9d06e031..cc9842c201 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3659,6 +3659,26 @@ If this is your first time using [CURRENT_GRID], you will need to create an acco yestext="Create Account..."/> + + fail +Already remembered user can be forgotten from Me > Preferences > Advanced > Remembered Usernames. + + + + confirm +Forgetting the logged-in user requires you to log out. + + + + + confirm +Local Data you are deleting is shared between multiple grids, are you sure you want to delete it? + + + @@ -148,9 +148,11 @@ left="408" bottom_delta="0" label="Remember password" + label_text.word_wrap="true" + label_text.width="150" check_button.bottom="3" name="remember_check" - width="145" /> + width="170" /> - + Ponto de Aterrissagem: [LANDING]