diff options
author | Andrey Lihatskiy <andreylproductengine@lindenlab.com> | 2015-12-11 17:41:41 +0200 |
---|---|---|
committer | Andrey Lihatskiy <andreylproductengine@lindenlab.com> | 2015-12-11 17:41:41 +0200 |
commit | aa42870d5ad1edc9ea33c62c5bf66e84375c3b0e (patch) | |
tree | 5bbd74f0b89fed271fc9ca8eb01ddd5954a26f94 | |
parent | dca797c3db34d119ccdc2d6f24c7742df75ff9c6 (diff) | |
parent | a53caef1e8314f9cf2af3c0081bf57d5f20db560 (diff) |
Merged lindenlab/viewer-lion into default
-rwxr-xr-x | indra/llui/lliconctrl.cpp | 14 | ||||
-rwxr-xr-x | indra/llui/lliconctrl.h | 4 | ||||
-rwxr-xr-x | indra/newview/llaisapi.cpp | 18 | ||||
-rwxr-xr-x | indra/newview/llavatariconctrl.cpp | 36 | ||||
-rwxr-xr-x | indra/newview/llgroupiconctrl.cpp | 11 | ||||
-rwxr-xr-x | indra/newview/llinspectgroup.cpp | 98 | ||||
-rwxr-xr-x | indra/newview/llinventorymodel.cpp | 2 | ||||
-rwxr-xr-x | indra/newview/llnamelistctrl.cpp | 8 | ||||
-rwxr-xr-x | indra/newview/llnamelistctrl.h | 2 | ||||
-rwxr-xr-x | indra/newview/llselectmgr.cpp | 6 | ||||
-rwxr-xr-x | indra/newview/llviewertexture.cpp | 76 | ||||
-rwxr-xr-x | indra/newview/skins/default/xui/es/floater_about_land.xml | 4 |
12 files changed, 171 insertions, 108 deletions
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 58b66f60ca..f841901801 100755 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -54,7 +54,9 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) mUseDrawContextAlpha(p.use_draw_context_alpha), mPriority(0), mMinWidth(p.min_width), - mMinHeight(p.min_height) + mMinHeight(p.min_height), + mMaxWidth(0), + mMaxHeight(0) { if (mImagep.notNull()) { @@ -104,7 +106,15 @@ void LLIconCtrl::setValue(const LLSD& value ) && mMinWidth && mMinHeight) { - mImagep->getImage()->setKnownDrawSize(llmax(mMinWidth, mImagep->getWidth()), llmax(mMinHeight, mImagep->getHeight())); + S32 desired_draw_width = llmax(mMinWidth, mImagep->getWidth()); + S32 desired_draw_height = llmax(mMinHeight, mImagep->getHeight()); + if (mMaxWidth && mMaxHeight) + { + desired_draw_width = llmin(desired_draw_width, mMaxWidth); + desired_draw_height = llmin(desired_draw_height, mMaxHeight); + } + + mImagep->getImage()->setKnownDrawSize(desired_draw_width, desired_draw_height); } } diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index 8b1092df46..7971cd44d3 100755 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -79,7 +79,9 @@ protected: //the output size of the icon image if set. S32 mMinWidth, - mMinHeight; + mMinHeight, + mMaxWidth, + mMaxHeight; // If set to true (default), use the draw context transparency. // If false, will use transparency returned by getCurrentTransparency(). See STORM-698. diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 714b456ae7..d8b6cc729d 100755 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -567,13 +567,25 @@ void AISUpdate::parseCategory(const LLSD& category_map) parseDescendentCount(category_id, category_map["_embedded"]); } - LLPointer<LLViewerInventoryCategory> new_cat(new LLViewerInventoryCategory(category_id)); + LLPointer<LLViewerInventoryCategory> new_cat; LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id); if (curr_cat) { // Default to current values where not provided. - new_cat->copyViewerCategory(curr_cat); - } + new_cat = new LLViewerInventoryCategory(curr_cat); + } + else + { + if (category_map.has("agent_id")) + { + new_cat = new LLViewerInventoryCategory(category_map["agent_id"].asUUID()); + } + else + { + LL_DEBUGS() << "No owner provided, folder might be assigned wrong owner" << LL_ENDL; + new_cat = new LLViewerInventoryCategory(LLUUID::null); + } + } BOOL rv = new_cat->unpackMessage(category_map); // *NOTE: unpackMessage does not unpack version or descendent count. //if (category_map.has("version")) diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 25a5df9781..932326acae 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -182,38 +182,12 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) mSymbolPos(p.symbol_pos) { mPriority = LLViewerFetchedTexture::BOOST_ICON; - - LLRect rect = p.rect; - - // BottomRight is the default position - S32 left = rect.getWidth() - mSymbolSize - mSymbolHpad; - S32 bottom = mSymbolVpad; - switch(mSymbolPos) - { - case LLAvatarIconCtrlEnums::BOTTOM_LEFT: - { - left = mSymbolHpad; - bottom = mSymbolVpad; - } - - case LLAvatarIconCtrlEnums::TOP_LEFT: - { - left = mSymbolHpad; - bottom = rect.getHeight() - mSymbolSize - mSymbolVpad; - } - - case LLAvatarIconCtrlEnums::TOP_RIGHT: - { - left = rect.getWidth() - mSymbolSize - mSymbolHpad; - bottom = rect.getHeight() - mSymbolSize - mSymbolVpad; - } - - case LLAvatarIconCtrlEnums::BOTTOM_RIGHT: - // fallthrough, is default - default: - rect.setOriginAndSize(left, bottom, mSymbolSize, mSymbolSize); - } + // don't request larger image then necessary to save gl memory, + // but ensure that quality is sufficient + LLRect rect = p.rect; + mMaxHeight = llmax((S32)p.min_height, rect.getHeight()); + mMaxWidth = llmax((S32)p.min_width, rect.getWidth()); if (p.avatar_id.isProvided()) { diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp index 6abf9ea637..1974a073dd 100755 --- a/indra/newview/llgroupiconctrl.cpp +++ b/indra/newview/llgroupiconctrl.cpp @@ -37,7 +37,10 @@ LLGroupIconCtrl::Params::Params() : group_id("group_id"), draw_tooltip("draw_tooltip", true), default_icon_name("default_icon_name") -{} +{ + changeDefault(min_width, 32); + changeDefault(min_height, 32); +} LLGroupIconCtrl::LLGroupIconCtrl(const LLGroupIconCtrl::Params& p) @@ -48,6 +51,12 @@ LLGroupIconCtrl::LLGroupIconCtrl(const LLGroupIconCtrl::Params& p) { mPriority = LLViewerFetchedTexture::BOOST_ICON; + // don't request larger image then necessary to save gl memory, + // but ensure that quality is sufficient + LLRect rect = p.rect; + mMaxHeight = llmax((S32)p.min_height, rect.getHeight()); + mMaxWidth = llmax((S32)p.min_width, rect.getWidth()); + if (p.group_id.isProvided()) { LLSD value(p.group_id); diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp index 76617b55bf..8e91af321e 100755 --- a/indra/newview/llinspectgroup.cpp +++ b/indra/newview/llinspectgroup.cpp @@ -42,16 +42,13 @@ #include "lltrans.h" #include "lluictrl.h" -class LLFetchGroupData; - - ////////////////////////////////////////////////////////////////////////////// // LLInspectGroup ////////////////////////////////////////////////////////////////////////////// /// Group Inspector, a small information window used when clicking /// on group names in the 2D UI -class LLInspectGroup : public LLInspect +class LLInspectGroup : public LLInspect, public LLGroupMgrObserver { friend class LLFloaterReg; @@ -65,12 +62,16 @@ public: // (for example, inspector about same group but in different position) /*virtual*/ void onOpen(const LLSD& group_id); + void setGroupID(const LLUUID& group_id); + // When closing they should close their gear menu /*virtual*/ void onClose(bool app_quitting); // Update view based on information from group manager void processGroupData(); - + + virtual void changed(LLGroupChange gc); + // Make network requests for all the data to display in this view. // Used on construction and if avatar id changes. void requestUpdate(); @@ -88,53 +89,12 @@ public: private: LLUUID mGroupID; - // an in-flight network request for group properties - // is represented by this object - LLFetchGroupData* mPropertiesRequest; }; -////////////////////////////////////////////////////////////////////////////// -// LLFetchGroupData -////////////////////////////////////////////////////////////////////////////// - -// This object represents a pending request for avatar properties information -class LLFetchGroupData : public LLGroupMgrObserver -{ -public: - // If the inspector closes it will delete the pending request object, so the - // inspector pointer will be valid for the lifetime of this object - LLFetchGroupData(const LLUUID& group_id, LLInspectGroup* inspector) - : LLGroupMgrObserver(group_id), - mInspector(inspector) - { - LLGroupMgr* mgr = LLGroupMgr::getInstance(); - // register ourselves as an observer - mgr->addObserver(this); - // send a request - mgr->sendGroupPropertiesRequest(group_id); - } - - ~LLFetchGroupData() - { - // remove ourselves as an observer - LLGroupMgr::getInstance()->removeObserver(this); - } - - void changed(LLGroupChange gc) - { - if (gc == GC_PROPERTIES) - { - mInspector->processGroupData(); - } - } - - LLInspectGroup* mInspector; -}; LLInspectGroup::LLInspectGroup(const LLSD& sd) : LLInspect( LLSD() ), // single_instance, doesn't really need key - mGroupID(), // set in onOpen() - mPropertiesRequest(NULL) + mGroupID() // set in onOpen() { mCommitCallbackRegistrar.add("InspectGroup.ViewProfile", boost::bind(&LLInspectGroup::onClickViewProfile, this)); @@ -149,10 +109,7 @@ LLInspectGroup::LLInspectGroup(const LLSD& sd) LLInspectGroup::~LLInspectGroup() { - // clean up any pending requests so they don't call back into a deleted - // view - delete mPropertiesRequest; - mPropertiesRequest = NULL; + LLGroupMgr::getInstance()->removeObserver(this); } @@ -164,7 +121,7 @@ void LLInspectGroup::onOpen(const LLSD& data) // start fade animation LLInspect::onOpen(data); - mGroupID = data["group_id"]; + setGroupID(data["group_id"]); // Position the inspector relative to the mouse cursor // Similar to how tooltips are positioned @@ -185,7 +142,8 @@ void LLInspectGroup::onOpen(const LLSD& data) // virtual void LLInspectGroup::onClose(bool app_quitting) { - // *TODO: If we add a gear menu, close it here + LLGroupMgr::getInstance()->removeObserver(this); + // *TODO: If we add a gear menu, close it here } void LLInspectGroup::requestUpdate() @@ -213,9 +171,15 @@ void LLInspectGroup::requestUpdate() getChild<LLUICtrl>("leave_btn")->setVisible(false); getChild<LLUICtrl>("join_btn")->setVisible(false); - // Make a new request for properties - delete mPropertiesRequest; - mPropertiesRequest = new LLFetchGroupData(mGroupID, this); + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + if (!gdatap || !gdatap->isGroupPropertiesDataComplete() ) + { + LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID); + } + else + { + processGroupData(); + } // Name lookup will be faster out of cache, use that gCacheName->getGroup(mGroupID, @@ -223,6 +187,16 @@ void LLInspectGroup::requestUpdate() this, _1, _2, _3)); } +void LLInspectGroup::setGroupID(const LLUUID& group_id) +{ + LLGroupMgr::getInstance()->removeObserver(this); + + mID = group_id; + mGroupID = group_id; + + LLGroupMgr::getInstance()->addObserver(this); +} + void LLInspectGroup::nameUpdatedCallback( const LLUUID& id, const std::string& name, @@ -236,6 +210,14 @@ void LLInspectGroup::nameUpdatedCallback( // Otherwise possibly a request for an older inspector, ignore it } +void LLInspectGroup::changed(LLGroupChange gc) +{ + if (gc == GC_PROPERTIES) + { + processGroupData(); + } +} + void LLInspectGroup::processGroupData() { LLGroupMgrGroupData* data = @@ -288,10 +270,6 @@ void LLInspectGroup::processGroupData() bool can_join = !is_member && data->mOpenEnrollment; getChild<LLUICtrl>("join_btn")->setEnabled(can_join); } - - // Delete the request object as it has been satisfied - delete mPropertiesRequest; - mPropertiesRequest = NULL; } void LLInspectGroup::onClickViewProfile() diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0bad4702e0..e123a3e68a 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1075,7 +1075,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 else { // add this category - LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat->getParentUUID()); + LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat->getOwnerID()); new_cat->copyViewerCategory(cat); addCategory(new_cat); diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 5510598ae7..fe75ab8e50 100755 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -345,7 +345,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( } mAvatarNameCacheConnections.erase(it); } - mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, item->getHandle())); + mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, prefix, item->getHandle())); if(mPendingLookupsRemaining <= 0) { @@ -418,6 +418,7 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id) void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, + std::string prefix, LLHandle<LLNameListItem> item) { avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id); @@ -442,6 +443,11 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, name.append(suffix); } + if (!prefix.empty()) + { + name.insert(0, prefix); + } + LLNameListItem* list_item = item.get(); if (list_item && list_item->getUUID() == agent_id) { diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 19ce3c7aed..677b49e667 100755 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -170,7 +170,7 @@ public: /*virtual*/ void mouseOverHighlightNthItem( S32 index ); private: void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false); - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle<LLNameListItem> item); + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, std::string prefix, LLHandle<LLNameListItem> item); private: S32 mNameColumnIndex; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 7620046ee3..4f63df1ea2 100755 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1628,7 +1628,11 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {} bool apply(LLViewerObject* objectp, S32 te) { - if (mItem) + if(objectp && !objectp->permModify()) + { + return false; + } + if (mItem) { if (te == -1) // all faces { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a957367f61..c8c71b74b7 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -97,6 +97,7 @@ S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez; const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128; +const S32 DEFAULT_ICON_DIMENTIONS = 32; S32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256. S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA; BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE; @@ -1178,6 +1179,17 @@ void LLViewerFetchedTexture::loadFromFastCache() } else { + if (mBoostLevel == LLGLTexture::BOOST_ICON) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + // scale oversized icon, no need to give more work to gl + mRawImage->scale(expected_width, expected_height); + } + } + mRequestedDiscardLevel = mDesiredDiscardLevel + 1; mIsRawImageValid = TRUE; addToCreateTexture(); @@ -1506,6 +1518,17 @@ void LLViewerFetchedTexture::processTextureStats() { mDesiredDiscardLevel = 0; } + else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON) + { + if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + { + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + } + else + { + mDesiredDiscardLevel = 0; + } + } else if(!mFullWidth || !mFullHeight) { mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel); @@ -1936,6 +1959,17 @@ bool LLViewerFetchedTexture::updateFetch() addToCreateTexture(); } + if (mBoostLevel == LLGLTexture::BOOST_ICON) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + // scale oversized icon, no need to give more work to gl + mRawImage->scale(expected_width, expected_height); + } + } + return TRUE; } else @@ -2670,7 +2704,7 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) { - if(mSavedRawDiscardLevel != discard_level) + if (mSavedRawDiscardLevel != discard_level && mBoostLevel != BOOST_ICON) { mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); mRawImage->copy(getSavedRawImage()); @@ -2771,8 +2805,25 @@ void LLViewerFetchedTexture::switchToCachedImage() void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) { if(imageraw != mRawImage.get()) - { - mCachedRawImage = imageraw; + { + if (mBoostLevel == LLGLTexture::BOOST_ICON) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents()); + mCachedRawImage->copyScaled(imageraw); + } + else + { + mCachedRawImage = imageraw; + } + } + else + { + mCachedRawImage = imageraw; + } mCachedRawDiscardLevel = discard_level; mCachedRawImageReady = TRUE; } @@ -2862,7 +2913,24 @@ void LLViewerFetchedTexture::saveRawImage() } mSavedRawDiscardLevel = mRawDiscardLevel; - mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()); + if (mBoostLevel == LLGLTexture::BOOST_ICON) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents()); + mSavedRawImage->copyScaled(mRawImage); + } + else + { + mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()); + } + } + else + { + mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()); + } if(mForceToSaveRawImage && mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) { 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 10907344ae..79493d3885 100755 --- a/indra/newview/skins/default/xui/es/floater_about_land.xml +++ b/indra/newview/skins/default/xui/es/floater_about_land.xml @@ -353,10 +353,10 @@ 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_label5"> + <text name="allow_label5" 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."/> + <check_box label="Ver los avatares" name="SeeAvatarsCheck" top="170" 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."/> <text name="landing_point"> Punto de llegada: [LANDING] </text> |