diff --git a/indra/llinventory/lleconomy.cpp b/indra/llinventory/lleconomy.cpp
index c6eaa6d3e14b606728b142a7008fde154a4cc98f..d643ea6ed9077f118d9ced6a43bf0c441f91c021 100644
--- a/indra/llinventory/lleconomy.cpp
+++ b/indra/llinventory/lleconomy.cpp
@@ -48,6 +48,31 @@ LLGlobalEconomy::LLGlobalEconomy()
 LLGlobalEconomy::~LLGlobalEconomy()
 { }
 
+void LLGlobalEconomy::addObserver(LLEconomyObserver* observer)
+{
+	mObservers.push_back(observer);
+}
+
+void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer)
+{
+	std::list<LLEconomyObserver*>::iterator it =
+		std::find(mObservers.begin(), mObservers.end(), observer);
+	if (it != mObservers.end())
+	{
+		mObservers.erase(it);
+	}
+}
+
+void LLGlobalEconomy::notifyObservers()
+{
+	for (std::list<LLEconomyObserver*>::iterator it = mObservers.begin();
+		it != mObservers.end();
+		++it)
+	{
+		(*it)->onEconomyDataChange();
+	}
+}
+
 // static
 void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data)
 {
@@ -88,6 +113,8 @@ void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy*
 	econ_data->setTeleportPriceExponent(f);
 	msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceGroupCreate, i);
 	econ_data->setPriceGroupCreate(i);
+
+	econ_data->notifyObservers();
 }
 
 S32	LLGlobalEconomy::calculateTeleportCost(F32 distance) const
diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h
index cc6643f955e468c18c3db456c6c7c18d949cf343..eb2ecf71ba41b70aaa905cbe7e99138688dbf869 100644
--- a/indra/llinventory/lleconomy.h
+++ b/indra/llinventory/lleconomy.h
@@ -31,6 +31,16 @@
 class LLMessageSystem;
 class LLVector3;
 
+/**
+ * Register an observer to be notified of economy data updates coming from server.
+ */
+class LLEconomyObserver
+{
+public:
+	virtual ~LLEconomyObserver() {}
+	virtual void onEconomyDataChange() = 0;
+};
+
 class LLGlobalEconomy
 {
 public:
@@ -46,6 +56,10 @@ public:
 
 	virtual void print();
 
+	void	addObserver(LLEconomyObserver* observer);
+	void	removeObserver(LLEconomyObserver* observer);
+	void	notifyObservers();
+
 	static void processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data);
 
 	S32		calculateTeleportCost(F32 distance) const;
@@ -89,6 +103,8 @@ private:
 	S32		mTeleportMinPrice;
 	F32		mTeleportPriceExponent;
 	S32     mPriceGroupCreate;
+
+	std::list<LLEconomyObserver*> mObservers;
 };
 
 
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index 40a4d665f8e6fff60cab8d4ba618f541eb14463b..65bfc990d1eab087d5adb102024eccc089b52454 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -295,6 +295,11 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content)
 {
 	// remove the "Uploading..." message
 	LLUploadDialog::modalUploadFinished();
+	LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
+	if (floater_snapshot)
+	{
+		floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
+	}
 	
 	std::string reason = content["state"];
 	// deal with L$ errors
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 48e6cca6236f88fe62bee74d4af030e64c0efea7..ad571451f329828201282de93bb03c145cb3600d 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -380,7 +380,6 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 	{
 		mThumbnailUpToDate = FALSE ;
 	}
-	setThumbnailImageSize();
 }
 
 void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
@@ -723,25 +722,19 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
 		resetThumbnailImage() ;
 	}		
 
-	LLPointer<LLImageRaw> raw = NULL ;
-	S32 w , h ;
-	w = get_lower_power_two(mThumbnailWidth, 512) * 2 ;
-	h = get_lower_power_two(mThumbnailHeight, 512) * 2 ;
-
+	LLPointer<LLImageRaw> raw = new LLImageRaw;
+	if(!gViewerWindow->thumbnailSnapshot(raw,
+							mThumbnailWidth, mThumbnailHeight,
+							gSavedSettings.getBOOL("RenderUIInSnapshot"),
+							FALSE,
+							mSnapshotBufferType) )								
 	{
-		raw = new LLImageRaw ;
-		if(!gViewerWindow->thumbnailSnapshot(raw,
-								w, h,
-								gSavedSettings.getBOOL("RenderUIInSnapshot"),
-								FALSE,
-								mSnapshotBufferType) )								
-		{
-			raw = NULL ;
-		}
+		raw = NULL ;
 	}
 
 	if(raw)
 	{
+		raw->expandToPowerOfTwo();
 		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		
 		mThumbnailUpToDate = TRUE ;
 	}
@@ -791,6 +784,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	}
 
 	// time to produce a snapshot
+	previewp->setThumbnailImageSize();
 
 	lldebugs << "producing snapshot" << llendl;
 	if (!previewp->mPreviewImage)
@@ -1003,13 +997,7 @@ void LLSnapshotLivePreview::saveTexture()
 
 BOOL LLSnapshotLivePreview::saveLocal()
 {
-	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage, true);
-
-	// Relinquish image memory. Save button will be disabled as a side-effect.
-	lldebugs << "resetting formatted image after saving to disk" << llendl;
-	mFormattedImage = NULL;
-	mDataSize = 0;
-	updateSnapshot(FALSE, FALSE);
+	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
 
 	if(success)
 	{
@@ -1064,6 +1052,7 @@ public:
 	:	mAvatarPauseHandles(),
 		mLastToolset(NULL),
 		mAspectRatioCheckOff(false),
+		mNeedRefresh(false),
 		mStatus(STATUS_READY)
 	{
 	}
@@ -1083,7 +1072,6 @@ public:
 	static void onClickKeepAspectCheck(LLUICtrl *ctrl, void* data);
 #endif
 	static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked);
-	static void onCommitResolution(LLUICtrl* ctrl, void* data) { updateResolution(ctrl, data); }
 	static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);
 	static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
 	static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
@@ -1113,6 +1101,7 @@ public:
 	static void updateLayout(LLFloaterSnapshot* floater);
 	static void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null);
 	EStatus getStatus() const { return mStatus; }
+	static void setNeedRefresh(LLFloaterSnapshot* floater, bool need);
 
 private:
 	static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);
@@ -1129,6 +1118,7 @@ public:
 	LLToolset*	mLastToolset;
 	LLHandle<LLView> mPreviewHandle;
 	bool mAspectRatioCheckOff ;
+	bool mNeedRefresh;
 	EStatus mStatus;
 };
 
@@ -1251,7 +1241,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
 
 	// Show/hide advanced options.
 	LLPanel* advanced_options_panel = floaterp->getChild<LLPanel>("advanced_options_panel");
-	floaterp->getChild<LLButton>("advanced_options_btn")->setToggleState(advanced);
+	floaterp->getChild<LLButton>("advanced_options_btn")->setImageOverlay(advanced ? "TabIcon_Open_Off" : "TabIcon_Close_Off");
 	if (advanced != advanced_options_panel->getVisible())
 	{
 		S32 panel_width = advanced_options_panel->getRect().getWidth();
@@ -1347,6 +1337,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
 // No other methods should be changing any of the controls directly except for helpers called by this method.
 // The basic pattern for programmatically changing the GUI settings is to first set the
 // appropriate saved settings and then call this method to sync the GUI with them.
+// FIXME: The above comment seems obsolete now.
 // static
 void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
 {
@@ -1514,6 +1505,15 @@ void LLFloaterSnapshot::Impl::setStatus(EStatus status, bool ok, const std::stri
 	floater->impl.mStatus = status;
 }
 
+// static
+void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool need)
+{
+	if (!floater) return;
+
+	floater->mRefreshLabel->setVisible(need);
+	floater->impl.mNeedRefresh = need;
+}
+
 // static
 void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
 {
@@ -1531,6 +1531,7 @@ void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data)
 	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
 	if (previewp && view)
 	{
+		view->impl.setStatus(Impl::STATUS_READY);
 		previewp->updateSnapshot(TRUE);
 	}
 }
@@ -1556,6 +1557,7 @@ void LLFloaterSnapshot::Impl::onClickMore(void* data)
 	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
 	if (view)
 	{
+		view->impl.setStatus(Impl::STATUS_READY);
 		gSavedSettings.setBOOL("AdvanceSnapshot", !visible);
 #if 0
 		view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() );
@@ -1697,6 +1699,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
 	return ;
 }
 
+// Show/hide upload progress indicators.
 // static
 void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working)
 {
@@ -1712,20 +1715,21 @@ void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool workin
 		working_lbl->setValue(progress_text);
 	}
 
-	// All controls should be disable while posting.
+	// All controls should be disabled while posting.
 	floater->setCtrlsEnabled(!working);
 	LLPanelSnapshot* active_panel = getActivePanel(floater);
 	if (active_panel)
 	{
-		active_panel->setCtrlsEnabled(!working);
+		active_panel->enableControls(!working);
 	}
 }
 
+// Show/hide upload status message.
 // static
 void LLFloaterSnapshot::Impl::setFinished(LLFloaterSnapshot* floater, bool finished, bool ok, const std::string& msg)
 {
-	floater->getChild<LLUICtrl>("succeeded_panel")->setVisible(finished && ok);
-	floater->getChild<LLUICtrl>("failed_panel")->setVisible(finished && !ok);
+	floater->mSucceessLblPanel->setVisible(finished && ok);
+	floater->mFailureLblPanel->setVisible(finished && !ok);
 
 	if (finished)
 	{
@@ -1869,6 +1873,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
 			if(do_update)
 			{
 				updateControls(view);
+				setNeedRefresh(view, true);
 			}
 		}
 	}
@@ -1911,6 +1916,7 @@ void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view)
 		gSavedSettings.setS32("SnapshotFormat", getImageFormat(view));
 		getPreviewView(view)->updateSnapshot(TRUE);
 		updateControls(view);
+		setNeedRefresh(view, false); // we're refreshing
 	}
 }
 
@@ -2060,6 +2066,8 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat
 // static
 void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h)
 {
+	bool need_refresh = false;
+
 	lldebugs << "applyCustomResolution(" << w << ", " << h << ")" << llendl;
 	if (view)
 	{
@@ -2110,6 +2118,7 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32
 				comboSetCustom(view, "postcard_size_combo");
 				comboSetCustom(view, "texture_size_combo");
 				comboSetCustom(view, "local_size_combo");
+				need_refresh = true;
 			}
 		}
 
@@ -2117,6 +2126,10 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32
 		gSavedSettings.setS32(lastSnapshotHeightName(getActiveSnapshotType(view)), h);
 
 		updateControls(view);
+		if (need_refresh)
+		{
+			setNeedRefresh(view, true); // need to do this after updateControls()
+		}
 	}
 }
 
@@ -2140,6 +2153,10 @@ void LLFloaterSnapshot::Impl::onSendingPostcardFinished(bool status)
 // Default constructor
 LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
 	: LLFloater(key),
+	  mRefreshBtn(NULL),
+	  mRefreshLabel(NULL),
+	  mSucceessLblPanel(NULL),
+	  mFailureLblPanel(NULL),
 	  impl (*(new Impl))
 {
 }
@@ -2173,7 +2190,11 @@ BOOL LLFloaterSnapshot::postBuild()
 	childSetCommitCallback("snapshot_type_radio", Impl::onCommitSnapshotType, this);
 #endif
 	
+	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
 	childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this);
+	mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
+	mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
+	mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
 
 	childSetAction("advanced_options_btn", Impl::onClickMore, this);
 
@@ -2208,11 +2229,6 @@ BOOL LLFloaterSnapshot::postBuild()
 	getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
 	childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
 
-	childSetCommitCallback("profile_size_combo", Impl::onCommitResolution, this);
-	childSetCommitCallback("postcard_size_combo", Impl::onCommitResolution, this);
-	childSetCommitCallback("texture_size_combo", Impl::onCommitResolution, this);
-	childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this);
-
 	LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));
 	LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1));
 
@@ -2259,28 +2275,63 @@ void LLFloaterSnapshot::draw()
 		{
 			bool working = impl.getStatus() == Impl::STATUS_WORKING;
 			const LLRect& thumbnail_rect = getThumbnailPlaceholderRect();
-			S32 offset_x = thumbnail_rect.mLeft + (thumbnail_rect.getWidth() - previewp->getThumbnailWidth()) / 2 ;
-			S32 offset_y = thumbnail_rect.mBottom + (thumbnail_rect.getHeight() - previewp->getThumbnailHeight()) / 2 ;
+			const S32 thumbnail_w = previewp->getThumbnailWidth();
+			const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+			// calc preview offset within the preview rect
+			const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
+			const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; // preview y pos within the preview rect
+
+			// calc preview offset within the floater rect
+			S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
+			S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
 
 			glMatrixMode(GL_MODELVIEW);
 			// Apply floater transparency to the texture unless the floater is focused.
 			F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
 			LLColor4 color = working ? LLColor4::grey4 : LLColor4::white;
 			gl_draw_scaled_image(offset_x, offset_y, 
-					previewp->getThumbnailWidth(), previewp->getThumbnailHeight(), 
+					thumbnail_w, thumbnail_h,
 					previewp->getThumbnailImage(), color % alpha);
 
 			previewp->drawPreviewRect(offset_x, offset_y) ;
 
-			// Draw progress indicators on top of the preview.
-			if (working)
+			// Draw some controls on top of the preview thumbnail.
+			static const S32 PADDING = 5;
+			static const S32 REFRESH_LBL_BG_HEIGHT = 32;
+
+			// Reshape and position the posting result message panels at the top of the thumbnail.
+			// Do this regardless of current posting status (finished or not) to avoid flicker
+			// when the result message is displayed for the first time.
+			// if (impl.getStatus() == Impl::STATUS_FINISHED)
 			{
-				gGL.pushUIMatrix();
-				const LLRect& r = getThumbnailPlaceholderRect();
-				LLUI::translate((F32) r.mLeft, (F32) r.mBottom);
-				sThumbnailPlaceholder->draw();
-				gGL.popUIMatrix();
+				LLRect result_lbl_rect = mSucceessLblPanel->getRect();
+				const S32 result_lbl_h = result_lbl_rect.getHeight();
+				result_lbl_rect.setLeftTopAndSize(local_offset_x, local_offset_y + thumbnail_h, thumbnail_w - 1, result_lbl_h);
+				mSucceessLblPanel->reshape(result_lbl_rect.getWidth(), result_lbl_h);
+				mSucceessLblPanel->setRect(result_lbl_rect);
+				mFailureLblPanel->reshape(result_lbl_rect.getWidth(), result_lbl_h);
+				mFailureLblPanel->setRect(result_lbl_rect);
 			}
+
+			// Position the refresh button in the bottom left corner of the thumbnail.
+			mRefreshBtn->setOrigin(local_offset_x + PADDING, local_offset_y + PADDING);
+
+			if (impl.mNeedRefresh)
+			{
+				// Place the refresh hint text to the right of the refresh button.
+				const LLRect& refresh_btn_rect = mRefreshBtn->getRect();
+				mRefreshLabel->setOrigin(refresh_btn_rect.mLeft + refresh_btn_rect.getWidth() + PADDING, refresh_btn_rect.mBottom);
+
+				// Draw the refresh hint background.
+				LLRect refresh_label_bg_rect(offset_x, offset_y + REFRESH_LBL_BG_HEIGHT, offset_x + thumbnail_w - 1, offset_y);
+				gl_rect_2d(refresh_label_bg_rect, LLColor4::white % 0.9f, TRUE);
+			}
+
+			gGL.pushUIMatrix();
+			LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom);
+			sThumbnailPlaceholder->draw();
+			gGL.popUIMatrix();
 		}
 	}
 }
@@ -2411,7 +2462,7 @@ void LLFloaterSnapshot::saveTexture()
 }
 
 // static
-void LLFloaterSnapshot::saveLocal()
+BOOL LLFloaterSnapshot::saveLocal()
 {
 	lldebugs << "saveLocal" << llendl;
 	// FIXME: duplicated code
@@ -2419,16 +2470,16 @@ void LLFloaterSnapshot::saveLocal()
 	if (!instance)
 	{
 		llassert(instance != NULL);
-		return;
+		return FALSE;
 	}
 	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
 	if (!previewp)
 	{
 		llassert(previewp != NULL);
-		return;
+		return FALSE;
 	}
 
-	previewp->saveLocal();
+	return previewp->saveLocal();
 }
 
 // static
@@ -2440,6 +2491,9 @@ void LLFloaterSnapshot::preUpdate()
 	{
 		// Disable the send/post/save buttons until snapshot is ready.
 		Impl::updateControls(instance);
+
+		// Force hiding the "Refresh to save" hint because we know we've just started refresh.
+		Impl::setNeedRefresh(instance, false);
 	}
 }
 
@@ -2452,6 +2506,16 @@ void LLFloaterSnapshot::postUpdate()
 	{
 		// Enable the send/post/save buttons.
 		Impl::updateControls(instance);
+
+		// We've just done refresh.
+		Impl::setNeedRefresh(instance, false);
+
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. when preview appears.
+		if (!instance->mRefreshBtn->getVisible())
+		{
+			instance->mRefreshBtn->setVisible(true);
+		}
 	}
 }
 
@@ -2474,6 +2538,9 @@ void LLFloaterSnapshot::postPanelSwitch()
 {
 	LLFloaterSnapshot* instance = getInstance();
 	instance->impl.updateControls(instance);
+
+	// Remove the success/failure indicator whenever user presses a snapshot option button.
+	instance->impl.setStatus(Impl::STATUS_READY);
 }
 
 // static
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index 2c79c749d60809311dc114e99d61d7bb3c11fbc7..afe135fa407cd009258f4c5a375e28dd96867963 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -58,7 +58,7 @@ public:
 	// TODO: create a snapshot model instead
 	static LLFloaterSnapshot* getInstance();
 	static void saveTexture();
-	static void saveLocal();
+	static BOOL saveLocal();
 	static void preUpdate();
 	static void postUpdate();
 	static void postSave();
@@ -71,6 +71,8 @@ public:
 
 private:
 	static LLUICtrl* sThumbnailPlaceholder;
+	LLUICtrl *mRefreshBtn, *mRefreshLabel;
+	LLUICtrl *mSucceessLblPanel, *mFailureLblPanel;
 
 	class Impl;
 	Impl& impl;
diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp
index fdae521ac52bc9d3388cb646dce2be7af52f81a8..90e32f973f64feb63a45b58ce39cb40a92cc3691 100644
--- a/indra/newview/llpanelsnapshot.cpp
+++ b/indra/newview/llpanelsnapshot.cpp
@@ -74,6 +74,16 @@ LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshot::getImageFormat() const
 	return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
 }
 
+void LLPanelSnapshot::enableControls(BOOL enable)
+{
+	setCtrlsEnabled(enable);
+	if (enable)
+	{
+		// Make sure only relevant controls are enabled/shown.
+		updateCustomResControls();
+	}
+}
+
 LLSpinCtrl* LLPanelSnapshot::getWidthSpinner()
 {
 	return getChild<LLSpinCtrl>(getWidthSpinnerName());
diff --git a/indra/newview/llpanelsnapshot.h b/indra/newview/llpanelsnapshot.h
index a49782a3e0404b2649ad3bc4e5107348403c4aee..7adb2fabc71ae174f1ecbf59388e5f1592020cc1 100644
--- a/indra/newview/llpanelsnapshot.h
+++ b/indra/newview/llpanelsnapshot.h
@@ -52,6 +52,7 @@ public:
 	virtual void enableAspectRatioCheckbox(BOOL enable);
 	virtual LLFloaterSnapshot::ESnapshotFormat getImageFormat() const;
 	virtual void updateControls(const LLSD& info) = 0; ///< Update controls from saved settings
+	void enableControls(BOOL enable);
 
 protected:
 	LLSideTrayPanelContainer* getParentContainer();
diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp
index 63ccbc1b029fe1f3196bd716d2af1c073ce93072..aca0ee67003d71b63f6dc9dfd8762517b34d6931 100644
--- a/indra/newview/llpanelsnapshotinventory.cpp
+++ b/indra/newview/llpanelsnapshotinventory.cpp
@@ -70,6 +70,7 @@ LLPanelSnapshotInventory::LLPanelSnapshotInventory()
 // virtual
 BOOL LLPanelSnapshotInventory::postBuild()
 {
+	getChild<LLUICtrl>(getAspectRatioCBName())->setVisible(FALSE); // we don't keep aspect ratio for inventory textures
 	return LLPanelSnapshot::postBuild();
 }
 
@@ -89,10 +90,10 @@ void LLPanelSnapshotInventory::updateCustomResControls()
 
 	getChild<LLUICtrl>(getWidthSpinnerName())->setVisible(show);
 	getChild<LLUICtrl>(getHeightSpinnerName())->setVisible(show);
-	getChild<LLUICtrl>(getAspectRatioCBName())->setVisible(show);
 
-	// enable controls if possible
-	LLPanelSnapshot::updateCustomResControls();
+	// Editing gets often enable elsewhere in common snapshot panel code. Override that.
+	getChild<LLSpinCtrl>(getWidthSpinnerName())->setAllowEdit(FALSE);
+	getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(FALSE);
 }
 
 // virtual
diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp
index eaa27b8d41065a872001d79baa36c2ffecf9bd80..4a2614fa7d72fa057e7832c43f609c6f1e8f26ec 100644
--- a/indra/newview/llpanelsnapshotlocal.cpp
+++ b/indra/newview/llpanelsnapshotlocal.cpp
@@ -34,6 +34,7 @@
 #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
 #include "llpanelsnapshot.h"
 #include "llviewercontrol.h" // gSavedSettings
+#include "llviewerwindow.h"
 
 /**
  * The panel provides UI for saving snapshot to a local folder.
@@ -58,14 +59,13 @@ private:
 
 	void onFormatComboCommit(LLUICtrl* ctrl);
 	void onQualitySliderCommit(LLUICtrl* ctrl);
-	void onSend();
+	void onSaveFlyoutCommit(LLUICtrl* ctrl);
 };
 
 static LLRegisterPanelClassWrapper<LLPanelSnapshotLocal> panel_class("llpanelsnapshotlocal");
 
 LLPanelSnapshotLocal::LLPanelSnapshotLocal()
 {
-	mCommitCallbackRegistrar.add("Local.Save",		boost::bind(&LLPanelSnapshotLocal::onSend,		this));
 	mCommitCallbackRegistrar.add("Local.Cancel",	boost::bind(&LLPanelSnapshotLocal::cancel,		this));
 }
 
@@ -74,6 +74,7 @@ BOOL LLPanelSnapshotLocal::postBuild()
 {
 	getChild<LLUICtrl>("image_quality_slider")->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onQualitySliderCommit, this, _1));
 	getChild<LLUICtrl>("local_format_combo")->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onFormatComboCommit, this, _1));
+	getChild<LLUICtrl>("save_btn")->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onSaveFlyoutCommit, this, _1));
 
 	return LLPanelSnapshot::postBuild();
 }
@@ -142,13 +143,25 @@ void LLPanelSnapshotLocal::onQualitySliderCommit(LLUICtrl* ctrl)
 	LLFloaterSnapshot::getInstance()->notify(info);
 }
 
-void LLPanelSnapshotLocal::onSend()
+void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)
 {
+	if (ctrl->getValue().asString() == "save as")
+	{
+		gViewerWindow->resetSnapshotLoc();
+	}
+
 	LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();
 
 	floater->notify(LLSD().with("set-working", true));
-	LLFloaterSnapshot::saveLocal();
-	LLFloaterSnapshot::postSave();
-	goBack();
-	floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local")));
+	BOOL saved = LLFloaterSnapshot::saveLocal();
+	if (saved)
+	{
+		LLFloaterSnapshot::postSave();
+		goBack();
+		floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local")));
+	}
+	else
+	{
+		cancel();
+	}
 }
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index df904b68365ee6f959d43a2fcdbf8cb1dc6021c5..554fabe5b3d38f0cd9dded22f1b071b327c9e7cb 100644
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -37,14 +37,18 @@
  */
 class LLPanelSnapshotOptions
 :	public LLPanel
+,	public LLEconomyObserver
 {
 	LOG_CLASS(LLPanelSnapshotOptions);
 
 public:
 	LLPanelSnapshotOptions();
+	~LLPanelSnapshotOptions();
 	/*virtual*/ void onOpen(const LLSD& key);
+	/*virtual*/ void onEconomyDataChange() { updateUploadCost(); }
 
 private:
+	void updateUploadCost();
 	void openPanel(const std::string& panel_name);
 	void onSaveToProfile();
 	void onSaveToEmail();
@@ -60,10 +64,22 @@ LLPanelSnapshotOptions::LLPanelSnapshotOptions()
 	mCommitCallbackRegistrar.add("Snapshot.SaveToEmail",		boost::bind(&LLPanelSnapshotOptions::onSaveToEmail,		this));
 	mCommitCallbackRegistrar.add("Snapshot.SaveToInventory",	boost::bind(&LLPanelSnapshotOptions::onSaveToInventory,	this));
 	mCommitCallbackRegistrar.add("Snapshot.SaveToComputer",		boost::bind(&LLPanelSnapshotOptions::onSaveToComputer,	this));
+
+	LLGlobalEconomy::Singleton::getInstance()->addObserver(this);
+}
+
+LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
+{
+	LLGlobalEconomy::Singleton::getInstance()->removeObserver(this);
 }
 
 // virtual
 void LLPanelSnapshotOptions::onOpen(const LLSD& key)
+{
+	updateUploadCost();
+}
+
+void LLPanelSnapshotOptions::updateUploadCost()
 {
 	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
 	getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d", upload_cost));
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index d7a1510c1c0c8cb5db1b1bf681cca1747f9fda30..85f65dedd38e8e77f1ac4469ce8eb54754b3af55 100644
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -5,7 +5,7 @@
  can_minimize="true"
  can_close="true"
  follows="left|top"
- height="600"
+ height="500"
  layout="topleft"
  name="Snapshot"
  help_topic="snapshot"
@@ -35,7 +35,7 @@
     </string>
  	<string
  	 name="profile_succeeded_str">
- 	    Your Profile Feed has been updated!
+ 	    Profile feed updated!
  	</string>
  	<string
  	 name="postcard_succeeded_str">
@@ -65,45 +65,15 @@
  	 name="local_failed_str">
  	    Failed to save to computer.
  	</string>
-   <view_border 
-    bevel_style="in"
-    follows="left|top" 
-    height="21"
-    left="10"
-    layout="topleft"
-    name="img_info_border"
-    top="22"
-    width="50"
-   />
-   <icon
-    follows="top|left"
-    height="18"
-    image_name="Snapshot_Off"
-    layout="topleft"
-    left_delta="-5"
-    mouse_opaque="true"
-    name="refresh_icon"
-    top_delta="3"
-    width="36" />
-   <button
-    follows="left|top"
-    height="22"
-    image_overlay="Refresh_Off"
-    layout="topleft"
-    left_delta="31"
-    name="new_snapshot_btn"
-    top_delta="-3"
-    width="23" />
     <button
      follows="left|top"
      height="23"
      image_overlay="TabIcon_Close_Off"
-     is_toggle="true"
      layout="topleft"
-     left="240"
+     left="236"
      name="advanced_options_btn"
      tool_tip="Advanced options"
-     top_delta="0"
+     top="25"
      width="23" />
   <ui_ctrl 
     height="160"
@@ -113,6 +83,70 @@
     top="50"
     follows="left|top"
     left="10">
+      <panel
+       background_visible="true"
+       bg_alpha_color="0.9 1 0.9 1"
+       follows="left|top"
+       font="SansSerifLarge"
+       halign="center"
+       height="20"
+       layout="topleft"
+       left="0"
+       length="1"
+       name="succeeded_panel"
+       right="-1"
+       top="0"
+       type="string"
+       visible="false">
+          <text
+           follows="all"
+           font="SansSerif"
+           halign="center"
+           height="18"
+           layout="topleft"
+           left="1"
+           length="1"
+           name="succeeded_lbl"
+           right="-1"
+           text_color="0.2 0.5 0.2 1"
+           top="4"
+           translate="false"
+           type="string">
+              Succeeded
+          </text>
+      </panel>
+      <panel
+       background_visible="true"
+       bg_alpha_color="1 0.9 0.9 1"
+       follows="left|top"
+       font="SansSerifLarge"
+       halign="center"
+       height="20"
+       layout="topleft"
+       left_delta="0"
+       length="1"
+       name="failed_panel"
+       right="-1"
+       top="0"
+       type="string"
+       visible="false">
+          <text
+           follows="all"
+           font="SansSerif"
+           halign="center"
+           height="18"
+           layout="topleft"
+           left="1"
+           length="1"
+           name="failed_lbl"
+           right="-1"
+           text_color="0.5 0.2 0.2 1"
+           top="4"
+           translate="false"
+           type="string">
+              Failed
+          </text>
+      </panel>
       <loading_indicator
        follows="left|top"
        height="48"
@@ -139,6 +173,34 @@
        width="130">
           Working
       </text>
+      <button
+       follows="left|top"
+       height="22"
+       image_overlay="Refresh_Off"
+       layout="topleft"
+       left="20"
+       name="new_snapshot_btn"
+       bottom="-20"
+       visible="false"
+       width="22" />
+      <text
+       follows="left|top"
+       font="SansSerifBold"
+       halign="left"
+       height="18"
+       layout="topleft"
+       left_pad="10"
+       length="1"
+       name="refresh_lbl"
+       right="-5"
+       text_color="red"
+       top_delta="0"
+       translate="false"
+       type="string"
+       visible="false"
+       width="130">
+          Refresh to save.
+      </text>
   </ui_ctrl>
   <view_border 
    bevel_style="in" 
@@ -180,7 +242,7 @@
    </text>
     <panel_container
      follows="left|top"
-     height="360"
+     height="260"
      layout="topleft"
      left="0"
      name="panel_container"
diff --git a/indra/newview/skins/default/xui/en/panel_postcard_message.xml b/indra/newview/skins/default/xui/en/panel_postcard_message.xml
index e9f322f590f14cf05596c718eb2413cb504fb787..ab2a42ea01bf1baa6be6c97a037f41d2c8da9a2d 100644
--- a/indra/newview/skins/default/xui/en/panel_postcard_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_postcard_message.xml
@@ -87,8 +87,8 @@
     <text_editor
      type="string"
      length="1"
-     follows="left|top|right|bottom"
-     height="140"
+     follows="left|top|right"
+     height="60"
      layout="topleft"
      left_delta="0"
      max_length="700"
@@ -104,7 +104,7 @@
      label="Cancel"
      layout="topleft"
      name="cancel_btn"
-     right="-10"
+     right="-32"
      top="350"
      width="100">
       <button.commit_callback
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
index 7b148fa338f084ad6f3d447f059fae4916935bb5..9057ebb65eb4d96915d6a5bc2b46e2cd75e40381 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
@@ -118,14 +118,15 @@
      label="Constrain proportions"
      layout="topleft"
      left="10"
-     name="inventory_keep_aspect_check" />
+     name="inventory_keep_aspect_check"
+     visible="false" />
     <button
      follows="right|bottom"
      height="23"
      label="Cancel"
      layout="topleft"
      name="cancel_btn"
-     right="-10"
+     right="-32"
      top="350"
      width="100">
       <button.commit_callback
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
index 4d6c4bcdfaccc741885eda31d4200a1eff51ea16..30403a21dd6c3001348e035d2648121e452da5de 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
@@ -173,22 +173,29 @@
      label="Cancel"
      layout="topleft"
      name="cancel_btn"
-     right="-10"
+     right="-32"
      top="350"
      width="100">
       <button.commit_callback
        function="Local.Cancel" />
     </button>
-    <button
+    <flyout_button
      follows="right|bottom"
      height="23"
      label="Save"
      layout="topleft"
      left_delta="-106"
      name="save_btn"
+     tool_tip="Save image to a file"
      top_delta="0"
      width="100">
-      <button.commit_callback
-       function="Local.Save" />
-    </button>
+        <flyout_button.item
+         label="Save"
+         name="save_item"
+         value="save" />
+        <flyout_button.item
+         label="Save As..."
+         name="saveas_item"
+         value="save as" />
+    </flyout_button>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
index 792f6dbec8f032cd454a481b81cb55bf97ed61af..d2f29ade44c74911b534f3ced8309a54140ee112 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
@@ -81,68 +81,4 @@
     <button.commit_callback
      function="Snapshot.SaveToComputer" />
   </button>
-  <panel
-   background_visible="true"
-   bg_alpha_color="0.9 1 0.9 1"
-   bottom="-10"
-   follows="left|bottom|right"
-   font="SansSerifLarge"
-   halign="center"
-   height="20"
-   layout="topleft"
-   left_delta="0"
-   length="1"
-   name="succeeded_panel"
-   right="-10"
-   type="string"
-   visible="false">
-      <text
-       follows="all"
-       font="SansSerif"
-       halign="center"
-       height="18"
-       layout="topleft"
-       left="1"
-       length="1"
-       name="succeeded_lbl"
-       right="-1"
-       text_color="0.2 0.5 0.2 1"
-       top="4"
-       translate="false"
-       type="string">
-          Succeeded
-      </text>
-  </panel>
-  <panel
-   background_visible="true"
-   bg_alpha_color="1 0.9 0.9 1"
-   bottom="-10"
-   follows="left|bottom|right"
-   font="SansSerifLarge"
-   halign="center"
-   height="20"
-   layout="topleft"
-   left_delta="0"
-   length="1"
-   name="failed_panel"
-   right="-10"
-   type="string"
-   visible="false">
-      <text
-       follows="all"
-       font="SansSerif"
-       halign="center"
-       height="18"
-       layout="topleft"
-       left="1"
-       length="1"
-       name="failed_lbl"
-       right="-1"
-       text_color="0.5 0.2 0.2 1"
-       top="4"
-       translate="false"
-       type="string">
-          Failed
-      </text>
-  </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml
index 0760a33f82e0a49866e556eeb8b3c02fc786273a..ee79a4b3b820cc3ab9e693710226b48afb1f80ae 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml
@@ -119,7 +119,7 @@
     </text>
     <text_editor
      follows="all"
-     height="170"
+     height="160"
      layout="topleft"
      left_delta="0"
      length="1"
@@ -144,7 +144,7 @@
      label="Cancel"
      layout="topleft"
      name="cancel_btn"
-     right="-10"
+     right="-32"
      top="350"
      width="100">
       <button.commit_callback