diff options
| author | Cho <cho@lindenlab.com> | 2013-11-04 23:42:21 +0000 | 
|---|---|---|
| committer | Cho <cho@lindenlab.com> | 2013-11-04 23:42:21 +0000 | 
| commit | cea9ffe89ce98f04e311aa989cce5955e77a15ff (patch) | |
| tree | a39aba4b740cd90afa649fd5fd08176bbf3e5af6 /indra/newview | |
| parent | 7c46eb17f24e30fe83469a297086aa93f100e5ed (diff) | |
added Twitter floater for ACME-1146, ACME-1147, ACME-1148, ACME-1149, and ACME-1150
Diffstat (limited to 'indra/newview')
| -rwxr-xr-x | indra/newview/CMakeLists.txt | 2 | ||||
| -rwxr-xr-x | indra/newview/llfloatersnapshot.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llfloatertwitter.cpp | 669 | ||||
| -rw-r--r-- | indra/newview/llfloatertwitter.h | 122 | ||||
| -rw-r--r-- | indra/newview/llsnapshotlivepreview.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/lltwitterconnect.cpp | 3 | ||||
| -rwxr-xr-x | indra/newview/llviewerfloaterreg.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_twitter.xml | 89 | ||||
| -rwxr-xr-x | indra/newview/skins/default/xui/en/menu_viewer.xml | 11 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_twitter_account.xml | 75 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_twitter_photo.xml | 152 | ||||
| -rwxr-xr-x | indra/newview/skins/default/xui/en/strings.xml | 8 | 
12 files changed, 1137 insertions, 7 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 226c739e48..746991a6f0 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -288,6 +288,7 @@ set(viewer_SOURCE_FILES      llfloatertos.cpp      llfloatertoybox.cpp      llfloatertranslationsettings.cpp +    llfloatertwitter.cpp      llfloateruipreview.cpp      llfloaterurlentry.cpp      llfloatervoiceeffect.cpp @@ -879,6 +880,7 @@ set(viewer_HEADER_FILES      llfloatertos.h      llfloatertoybox.h      llfloatertranslationsettings.h +    llfloatertwitter.h      llfloateruipreview.h      llfloaterurlentry.h      llfloatervoiceeffect.h diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index fa92ed094b..4701e128d3 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -33,6 +33,7 @@  #include "llfloaterreg.h"  #include "llfloatersocial.h"  #include "llfloaterflickr.h" +#include "llfloatertwitter.h"  #include "llcheckboxctrl.h"  #include "llcombobox.h"  #include "llpostcard.h" @@ -1265,10 +1266,11 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)  void LLFloaterSnapshot::update()  {  	LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); -	LLFloaterSocial* floater_social  = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");  -	LLFloaterFlickr* floater_flickr  = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");  +	LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");  +	LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");  +	LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");  -	if (!inst && !floater_social && !floater_flickr) +	if (!inst && !floater_social && !floater_flickr && !floater_twitter)  		return;  	BOOL changed = FALSE; diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp new file mode 100644 index 0000000000..b45cf32945 --- /dev/null +++ b/indra/newview/llfloatertwitter.cpp @@ -0,0 +1,669 @@ +/**  +* @file llfloatertwitter.cpp +* @brief Implementation of llfloatertwitter +* @author cho@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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 "llfloatertwitter.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lltwitterconnect.h" +#include "llfloaterreg.h" +#include "lliconctrl.h" +#include "llresmgr.h"		// LLLocale +#include "llsdserialize.h" +#include "llloadingindicator.h" +#include "llplugincookiestore.h" +#include "llslurl.h" +#include "lltrans.h" +#include "llsnapshotlivepreview.h" +#include "llviewerregion.h" +#include "llviewercontrol.h" +#include "llviewermedia.h" + +static LLRegisterPanelClassWrapper<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel"); +static LLRegisterPanelClassWrapper<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel"); + +const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte +const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare"; + +/////////////////////////// +//LLTwitterPhotoPanel/////// +/////////////////////////// + +LLTwitterPhotoPanel::LLTwitterPhotoPanel() : +mSnapshotPanel(NULL), +mResolutionComboBox(NULL), +mRefreshBtn(NULL), +mWorkingLabel(NULL), +mThumbnailPlaceholder(NULL), +mCaptionTextBox(NULL), +mLocationCheckbox(NULL), +mPostButton(NULL) +{ +	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this)); +	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLTwitterPhotoPanel::onClickNewSnapshot, this)); +} + +LLTwitterPhotoPanel::~LLTwitterPhotoPanel() +{ +	if(mPreviewHandle.get()) +	{ +		mPreviewHandle.get()->die(); +	} +} + +BOOL LLTwitterPhotoPanel::postBuild() +{ +	setVisibleCallback(boost::bind(&LLTwitterPhotoPanel::onVisibilityChange, this, _2)); +	 +	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel"); +	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox"); +	mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE)); +	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); +    mWorkingLabel = getChild<LLUICtrl>("working_lbl"); +	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); +	mCaptionTextBox = getChild<LLUICtrl>("photo_caption"); +	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb"); +	mPostButton = getChild<LLUICtrl>("post_photo_btn"); +	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn"); + +	return LLPanel::postBuild(); +} + +void LLTwitterPhotoPanel::draw() +{  +	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); + +    // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) +    bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing()); +    mCancelButton->setEnabled(no_ongoing_connection); +    mCaptionTextBox->setEnabled(no_ongoing_connection); +    mResolutionComboBox->setEnabled(no_ongoing_connection); +    mRefreshBtn->setEnabled(no_ongoing_connection); +    mLocationCheckbox->setEnabled(no_ongoing_connection); +     +    // Display the preview if one is available +	if (previewp && previewp->getThumbnailImage()) +	{ +		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect(); +		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 ; + +		// calc preview offset within the floater rect +        // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. +        // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. +        // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. +		S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; +		S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; +         +		mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>()); +         +		gGL.matrixMode(LLRender::MM_MODELVIEW); +		// Apply floater transparency to the texture unless the floater is focused. +		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); +		LLColor4 color = LLColor4::white; +		gl_draw_scaled_image(offset_x, offset_y,  +			thumbnail_w, thumbnail_h, +			previewp->getThumbnailImage(), color % alpha); + +		previewp->drawPreviewRect(offset_x, offset_y) ; +	} + +    // Update the visibility of the working (computing preview) label +    mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate())); +     +    // Enable Post if we have a preview to send and no on going connection being processed +    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate())); +     +    // Draw the rest of the panel on top of it +	LLPanel::draw(); +} + +LLSnapshotLivePreview* LLTwitterPhotoPanel::getPreviewView() +{ +	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); +	return previewp; +} + +void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility) +{ +	bool visible = new_visibility.asBoolean(); +	if (visible) +	{ +		if (mPreviewHandle.get()) +		{ +			LLSnapshotLivePreview* preview = getPreviewView(); +			if(preview) +			{ +				lldebugs << "opened, updating snapshot" << llendl; +				preview->updateSnapshot(TRUE); +			} +		} +		else +		{ +			LLRect full_screen_rect = getRootView()->getRect(); +			LLSnapshotLivePreview::Params p; +			p.rect(full_screen_rect); +			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); +			mPreviewHandle = previewp->getHandle();	 + +			previewp->setSnapshotType(previewp->SNAPSHOT_WEB); +			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); +			//previewp->setSnapshotQuality(98); +			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); + +			updateControls(); +		} +	} +} + +void LLTwitterPhotoPanel::onClickNewSnapshot() +{ +	LLSnapshotLivePreview* previewp = getPreviewView(); +	if (previewp) +	{ +		//setStatus(Impl::STATUS_READY); +		lldebugs << "updating snapshot" << llendl; +		previewp->updateSnapshot(TRUE); +	} +} + +void LLTwitterPhotoPanel::onSend() +{ +	LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); // just in case it is already listening +	LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterPhotoPanel", boost::bind(&LLTwitterPhotoPanel::onTwitterConnectStateChange, this, _1)); +	 +	// Connect to Twitter if necessary and then post +	if (LLTwitterConnect::instance().isConnected()) +	{ +		sendPhoto(); +	} +	else +	{ +		LLTwitterConnect::instance().checkConnectionToTwitter(true); +	} +} + +bool LLTwitterPhotoPanel::onTwitterConnectStateChange(const LLSD& data) +{ +	switch (data.get("enum").asInteger()) +	{ +		case LLTwitterConnect::TWITTER_CONNECTED: +			sendPhoto(); +			break; + +		case LLTwitterConnect::TWITTER_POSTED: +			LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); +			clearAndClose(); +			break; +	} + +	return false; +} + +void LLTwitterPhotoPanel::sendPhoto() +{ +	// Get the caption +	std::string caption = mCaptionTextBox->getValue().asString(); + +	// Add the location if required +	bool add_location = mLocationCheckbox->getValue().asBoolean(); +	if (add_location) +	{ +		// Get the SLURL for the location +		LLSLURL slurl; +		LLAgentUI::buildSLURL(slurl); +		std::string slurl_string = slurl.getSLURLString(); + +		// Add query parameters so Google Analytics can track incoming clicks! +		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; + +		// Add it to the caption (pretty crude, but we don't have a better option with photos) +		if (caption.empty()) +			caption = slurl_string; +		else +			caption = caption + " " + slurl_string; +	} + +	// Get the image +	LLSnapshotLivePreview* previewp = getPreviewView(); +	 +	// Post to Twitter +	LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), caption); + +	updateControls(); +} + +void LLTwitterPhotoPanel::clearAndClose() +{ +	mCaptionTextBox->setValue(""); + +	LLFloater* floater = getParentByType<LLFloater>(); +	if (floater) +	{ +		floater->closeFloater(); +	} +} + +void LLTwitterPhotoPanel::updateControls() +{ +	LLSnapshotLivePreview* previewp = getPreviewView(); +	BOOL got_bytes = previewp && previewp->getDataSize() > 0; +	BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); +	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + +	// *TODO: Separate maximum size for Web images from postcards +	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; + +	LLLocale locale(LLLocale::USER_LOCALE); +	std::string bytes_string; +	if (got_snap) +	{ +		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); +	} + +	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string +	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown"); +	getChild<LLUICtrl>("file_size_label")->setColor( +		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD  +		&& got_bytes +		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); + +	updateResolution(FALSE); +} + +void LLTwitterPhotoPanel::updateResolution(BOOL do_update) +{ +	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox); + +	std::string sdstring = combobox->getSelectedValue(); +	LLSD sdres; +	std::stringstream sstream(sdstring); +	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); + +	S32 width = sdres[0]; +	S32 height = sdres[1]; + +	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); +	if (previewp && combobox->getCurrentIndex() >= 0) +	{ +		S32 original_width = 0 , original_height = 0 ; +		previewp->getSize(original_width, original_height) ; + +		if (width == 0 || height == 0) +		{ +			// take resolution from current window size +			lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; +			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); +		} +		else +		{ +			// use the resolution from the selected pre-canned drop-down choice +			lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; +			previewp->setSize(width, height); +		} + +		checkAspectRatio(width); + +		previewp->getSize(width, height); +		 +		if(original_width != width || original_height != height) +		{ +			previewp->setSize(width, height); + +			// hide old preview as the aspect ratio could be wrong +			lldebugs << "updating thumbnail" << llendl; +			 +			previewp->updateSnapshot(FALSE, TRUE); +			if(do_update) +			{ +				lldebugs << "Will update controls" << llendl; +				updateControls(); +                LLTwitterPhotoPanel::onClickNewSnapshot(); +			} +		} +		 +	} +} + +void LLTwitterPhotoPanel::checkAspectRatio(S32 index) +{ +	LLSnapshotLivePreview *previewp = getPreviewView() ; + +	BOOL keep_aspect = FALSE; + +	if (0 == index) // current window size +	{ +		keep_aspect = TRUE; +	} +	else // predefined resolution +	{ +		keep_aspect = FALSE; +	} + +	if (previewp) +	{ +		previewp->mKeepAspectRatio = keep_aspect; +	} +} + +LLUICtrl* LLTwitterPhotoPanel::getRefreshBtn() +{ +	return mRefreshBtn; +} + +/////////////////////////// +//LLTwitterAccountPanel////// +/////////////////////////// + +LLTwitterAccountPanel::LLTwitterAccountPanel() :  +mAccountCaptionLabel(NULL), +mAccountNameLabel(NULL), +mPanelButtons(NULL), +mConnectButton(NULL), +mDisconnectButton(NULL) +{ +	mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLTwitterAccountPanel::onConnect, this)); +	mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLTwitterAccountPanel::onDisconnect, this)); + +	setVisibleCallback(boost::bind(&LLTwitterAccountPanel::onVisibilityChange, this, _2)); +} + +BOOL LLTwitterAccountPanel::postBuild() +{ +	mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label"); +	mAccountNameLabel = getChild<LLTextBox>("account_name_label"); +	mPanelButtons = getChild<LLUICtrl>("panel_buttons"); +	mConnectButton = getChild<LLUICtrl>("connect_btn"); +	mDisconnectButton = getChild<LLUICtrl>("disconnect_btn"); + +	return LLPanel::postBuild(); +} + +void LLTwitterAccountPanel::draw() +{ +	LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState(); + +	//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress +	bool disconnecting = connection_state == LLTwitterConnect::TWITTER_DISCONNECTING; +	mDisconnectButton->setEnabled(!disconnecting); + +	//Disable the 'connect' button when a connection is in progress +	bool connecting = connection_state == LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS; +	mConnectButton->setEnabled(!connecting); + +	LLPanel::draw(); +} + +void LLTwitterAccountPanel::onVisibilityChange(const LLSD& new_visibility) +{ +	bool visible = new_visibility.asBoolean(); + +	if(visible) +	{ +		LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel"); +		LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectStateChange, this, _1)); + +		LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel"); +		LLEventPumps::instance().obtain("TwitterConnectInfo").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectInfoChange, this)); + +		//Connected +		if(LLTwitterConnect::instance().isConnected()) +		{ +			showConnectedLayout(); +		} +		//Check if connected (show disconnected layout in meantime) +		else +		{ +			showDisconnectedLayout(); +		} +        if ((LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_NOT_CONNECTED) || +            (LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_CONNECTION_FAILED)) +        { +            LLTwitterConnect::instance().checkConnectionToTwitter(); +        } +	} +	else +	{ +		LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel"); +		LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel"); +	} +} + +bool LLTwitterAccountPanel::onTwitterConnectStateChange(const LLSD& data) +{ +	if(LLTwitterConnect::instance().isConnected()) +	{ +		//In process of disconnecting so leave the layout as is +		if(data.get("enum").asInteger() != LLTwitterConnect::TWITTER_DISCONNECTING) +		{ +			showConnectedLayout(); +		} +	} +	else +	{ +		showDisconnectedLayout(); +	} + +	return false; +} + +bool LLTwitterAccountPanel::onTwitterConnectInfoChange() +{ +	LLSD info = LLTwitterConnect::instance().getInfo(); +	std::string clickable_name; + +	//Strings of format [http://www.somewebsite.com Click Me] become clickable text +	if(info.has("link") && info.has("name")) +	{ +		clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; +	} + +	mAccountNameLabel->setText(clickable_name); + +	return false; +} + +void LLTwitterAccountPanel::showConnectButton() +{ +	if(!mConnectButton->getVisible()) +	{ +		mConnectButton->setVisible(TRUE); +		mDisconnectButton->setVisible(FALSE); +	} +} + +void LLTwitterAccountPanel::hideConnectButton() +{ +	if(mConnectButton->getVisible()) +	{ +		mConnectButton->setVisible(FALSE); +		mDisconnectButton->setVisible(TRUE); +	} +} + +void LLTwitterAccountPanel::showDisconnectedLayout() +{ +	mAccountCaptionLabel->setText(getString("twitter_disconnected")); +	mAccountNameLabel->setText(std::string("")); +	showConnectButton(); +} + +void LLTwitterAccountPanel::showConnectedLayout() +{ +	LLTwitterConnect::instance().loadTwitterInfo(); + +	mAccountCaptionLabel->setText(getString("twitter_connected")); +	hideConnectButton(); +} + +void LLTwitterAccountPanel::onConnect() +{ +	LLTwitterConnect::instance().checkConnectionToTwitter(true); + +	//Clear only the twitter browser cookies so that the twitter login screen appears +	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com");  +} + +void LLTwitterAccountPanel::onDisconnect() +{ +	LLTwitterConnect::instance().disconnectFromTwitter(); + +	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com");  +} + +//////////////////////// +//LLFloaterTwitter/////// +//////////////////////// + +LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key), +    mSocialPhotoPanel(NULL), +    mStatusErrorText(NULL), +    mStatusLoadingText(NULL), +    mStatusLoadingIndicator(NULL) +{ +	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterTwitter::onCancel, this)); +} + +void LLFloaterTwitter::onCancel() +{ +    closeFloater(); +} + +BOOL LLFloaterTwitter::postBuild() +{ +    // Keep tab of the Photo Panel +	mSocialPhotoPanel = static_cast<LLTwitterPhotoPanel*>(getChild<LLUICtrl>("panel_twitter_photo")); +    // Connection status widgets +    mStatusErrorText = getChild<LLTextBox>("connection_error_text"); +    mStatusLoadingText = getChild<LLTextBox>("connection_loading_text"); +    mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator"); +	return LLFloater::postBuild(); +} + +// static +void LLFloaterTwitter::preUpdate() +{ +	LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter"); +	if (instance) +	{ +		//Will set file size text to 'unknown' +		instance->mSocialPhotoPanel->updateControls(); +	} +} + +// static +void LLFloaterTwitter::postUpdate() +{ +	LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter"); +	if (instance) +	{ +		//Will set the file size text +		instance->mSocialPhotoPanel->updateControls(); + +		// The refresh button is initially hidden. We show it after the first update, +		// i.e. after snapshot is taken +		LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn(); + +		if (!refresh_button->getVisible()) +		{ +			refresh_button->setVisible(true); +		} +		 +	} +} + +void LLFloaterTwitter::draw() +{ +    if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) +    { +        mStatusErrorText->setVisible(false); +        mStatusLoadingText->setVisible(false); +        mStatusLoadingIndicator->setVisible(false); +        LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState(); +        std::string status_text; +         +        switch (connection_state) +        { +        case LLTwitterConnect::TWITTER_NOT_CONNECTED: +            // No status displayed when first opening the panel and no connection done +        case LLTwitterConnect::TWITTER_CONNECTED: +            // When successfully connected, no message is displayed +        case LLTwitterConnect::TWITTER_POSTED: +            // No success message to show since we actually close the floater after successful posting completion +            break; +        case LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS: +            // Connection loading indicator +            mStatusLoadingText->setVisible(true); +            status_text = LLTrans::getString("SocialTwitterConnecting"); +            mStatusLoadingText->setValue(status_text); +            mStatusLoadingIndicator->setVisible(true); +            break; +        case LLTwitterConnect::TWITTER_POSTING: +            // Posting indicator +            mStatusLoadingText->setVisible(true); +            status_text = LLTrans::getString("SocialTwitterPosting"); +            mStatusLoadingText->setValue(status_text); +            mStatusLoadingIndicator->setVisible(true); +			break; +        case LLTwitterConnect::TWITTER_CONNECTION_FAILED: +            // Error connecting to the service +            mStatusErrorText->setVisible(true); +            status_text = LLTrans::getString("SocialTwitterErrorConnecting"); +            mStatusErrorText->setValue(status_text); +            break; +        case LLTwitterConnect::TWITTER_POST_FAILED: +            // Error posting to the service +            mStatusErrorText->setVisible(true); +            status_text = LLTrans::getString("SocialTwitterErrorPosting"); +            mStatusErrorText->setValue(status_text); +            break; +		case LLTwitterConnect::TWITTER_DISCONNECTING: +			// Disconnecting loading indicator +			mStatusLoadingText->setVisible(true); +			status_text = LLTrans::getString("SocialTwitterDisconnecting"); +			mStatusLoadingText->setValue(status_text); +			mStatusLoadingIndicator->setVisible(true); +			break; +		case LLTwitterConnect::TWITTER_DISCONNECT_FAILED: +			// Error disconnecting from the service +			mStatusErrorText->setVisible(true); +			status_text = LLTrans::getString("SocialTwitterErrorDisconnecting"); +			mStatusErrorText->setValue(status_text); +			break; +        } +    } +	LLFloater::draw(); +} + diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h new file mode 100644 index 0000000000..d0c7b57eef --- /dev/null +++ b/indra/newview/llfloatertwitter.h @@ -0,0 +1,122 @@ +/**  +* @file   llfloatertwitter.h +* @brief  Header file for llfloatertwitter +* @author cho@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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_LLFLOATERTWITTER_H +#define LL_LLFLOATERTWITTER_H + +#include "llfloater.h" +#include "lltextbox.h" +#include "llviewertexture.h" + +class LLIconCtrl; +class LLCheckBoxCtrl; +class LLSnapshotLivePreview; + +class LLTwitterPhotoPanel : public LLPanel +{ +public: +	LLTwitterPhotoPanel(); +	~LLTwitterPhotoPanel(); + +	BOOL postBuild(); +	void draw(); + +	LLSnapshotLivePreview* getPreviewView(); +	void onVisibilityChange(const LLSD& new_visibility); +	void onClickNewSnapshot(); +	void onSend(); +	bool onTwitterConnectStateChange(const LLSD& data); + +	void sendPhoto(); +	void clearAndClose(); + +	void updateControls(); +	void updateResolution(BOOL do_update); +	void checkAspectRatio(S32 index); +	LLUICtrl* getRefreshBtn(); + +private: +	LLHandle<LLView> mPreviewHandle; + +	LLUICtrl * mSnapshotPanel; +	LLUICtrl * mResolutionComboBox; +	LLUICtrl * mRefreshBtn; +	LLUICtrl * mWorkingLabel; +	LLUICtrl * mThumbnailPlaceholder; +	LLUICtrl * mCaptionTextBox; +	LLUICtrl * mLocationCheckbox; +	LLUICtrl * mPostButton; +	LLUICtrl* mCancelButton; +}; + +class LLTwitterAccountPanel : public LLPanel +{ +public: +	LLTwitterAccountPanel(); +	BOOL postBuild(); +	void draw(); + +private: +	void onVisibilityChange(const LLSD& new_visibility); +	bool onTwitterConnectStateChange(const LLSD& data); +	bool onTwitterConnectInfoChange(); +	void onConnect(); +	void onUseAnotherAccount(); +	void onDisconnect(); + +	void showConnectButton(); +	void hideConnectButton(); +	void showDisconnectedLayout(); +	void showConnectedLayout(); + +	LLTextBox * mAccountCaptionLabel; +	LLTextBox * mAccountNameLabel; +	LLUICtrl * mPanelButtons; +	LLUICtrl * mConnectButton; +	LLUICtrl * mDisconnectButton; +}; + + +class LLFloaterTwitter : public LLFloater +{ +public: +	LLFloaterTwitter(const LLSD& key); +	BOOL postBuild(); +	void draw(); +	void onCancel(); + +	static void preUpdate(); +	static void postUpdate(); + +private: +	LLTwitterPhotoPanel* mSocialPhotoPanel; +    LLTextBox* mStatusErrorText; +    LLTextBox* mStatusLoadingText; +    LLUICtrl*  mStatusLoadingIndicator; +}; + +#endif // LL_LLFLOATERTWITTER_H + diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index afd9942e77..67952f83c7 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -36,6 +36,7 @@  #include "llfloaterreg.h"  #include "llfloatersocial.h"  #include "llfloaterflickr.h" +#include "llfloatertwitter.h"  #include "llimagebmp.h"  #include "llimagej2c.h"  #include "llimagejpeg.h" @@ -211,6 +212,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail  		LLFloaterSnapshot::preUpdate();  		LLFloaterSocial::preUpdate();  		LLFloaterFlickr::preUpdate(); +		LLFloaterTwitter::preUpdate();  	}  	// Update thumbnail if requested. @@ -769,6 +771,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  	LLFloaterSnapshot::postUpdate();  	LLFloaterSocial::postUpdate();  	LLFloaterFlickr::postUpdate(); +	LLFloaterTwitter::postUpdate();  	return TRUE;  } diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 80142e7073..5abd654d0c 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -296,7 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo      LLViewerRegion *regionp = gAgent.getRegion();      if (regionp)      { -        url = regionp->getCapability("TwitterConnect"); +		url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO +        //url = regionp->getCapability("TwitterConnect");          url += route;          if (include_read_from_master && mReadFromMaster) diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 0541da95fc..e74e6fef3d 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -116,6 +116,7 @@  #include "llfloatertopobjects.h"  #include "llfloatertoybox.h"  #include "llfloatertranslationsettings.h" +#include "llfloatertwitter.h"  #include "llfloateruipreview.h"  #include "llfloatervoiceeffect.h"  #include "llfloatervoicevolume.h" @@ -307,6 +308,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);  	LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSocial>);  	LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>); +	LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTwitter>);  	LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);  	LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);  	LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>); diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml new file mode 100644 index 0000000000..7007a14cdb --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_twitter.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<floater +  positioning="cascading" +  can_close="true" +  can_resize="false" +  help_topic="floater_twitter" +  layout="topleft" +  name="floater_twitter" +  save_rect="true" +  single_instance="true" +  reuse_instance="true" +  title="TWITTER" +  height="482" +  width="304"> +  <panel +   height="482" +   width="304" +   visible="true" +   name="background" +   follows="all" +   top="0" +   left="0"> +   <tab_container +     name="tabs" +     tab_group="1" +     tab_min_width="70" +     tab_height="30" +     tab_position="top" +     top="7" +     height="437" +     halign="center"> +     <panel +       filename="panel_twitter_photo.xml" +       class="lltwitterphotopanel" +       follows="all" +       label="COMPOSE" +       name="panel_twitter_photo"/> +     <panel +       filename="panel_twitter_account.xml" +       class="lltwitteraccountpanel" +       follows="all" +       label="ACCOUNT" +       name="panel_twitter_account"/>      +    </tab_container> +    <panel +     name="connection_status_panel" +     follows="left|bottom|right" +     height="24"> +     <text +      name="connection_error_text" +      type="string" +      follows="left|bottom|right" +      top="5" +      left="9" +      width="250" +      height="20" +      wrap="true" +      halign="left" +      valign="center" +      text_color="DrYellow" +      font="SansSerif"> +      Error +     </text> +     <loading_indicator +      follows="left|bottom|right" +      height="24" +      width="24" +      name="connection_loading_indicator" +      top="2" +      left="9" +      visible="true"/> +     <text +      name="connection_loading_text" +      type="string" +      follows="left|bottom|right" +      top="5" +      left_pad="5" +      width="250" +      height="20" +      wrap="true" +      halign="left" +      valign="center" +      text_color="EmphasisColor" +      font="SansSerif"> +      Loading... +    </text> +  </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index bbd6e94579..79adb4e8bb 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -282,14 +282,21 @@          <menu_item_separator/>        <menu_item_call          label="Facebook..." -        name="PostToFacebook"> +        name="Facebook">          <menu_item_call.on_click            function="Floater.Toggle"            parameter="social"/>        </menu_item_call>        <menu_item_call +        label="Twitter..." +        name="Twitter"> +        <menu_item_call.on_click +          function="Floater.Toggle" +          parameter="twitter"/> +      </menu_item_call> +      <menu_item_call          label="Flickr..." -        name="UploadToFacebook"> +        name="Flickr">          <menu_item_call.on_click            function="Floater.Toggle"            parameter="flickr"/> diff --git a/indra/newview/skins/default/xui/en/panel_twitter_account.xml b/indra/newview/skins/default/xui/en/panel_twitter_account.xml new file mode 100644 index 0000000000..4a413bd711 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_twitter_account.xml @@ -0,0 +1,75 @@ +<panel +	 height="400" +	 width="304" +	 layout="topleft" +   name="panel_twitter_account"> +  <string +      name="twitter_connected" +      value="You are connected to Twitter as:" /> +  <string +      name="twitter_disconnected" +      value="Not connected to Twitter" /> +  <text +   layout="topleft" +   length="1" +   follows="top|left" +   font="SansSerif" +   height="16" +   left="9" +   name="account_caption_label" +   top="21" +   type="string"> +    Not connected to Twitter. +  </text> +  <text +   layout="topleft" +   top_pad="2" +   length="1" +   follows="top|left" +   font="SansSerif" +   height="16" +   left="9" +   name="account_name_label" +   parse_urls="true" +   type="string"/> +  <panel +    layout="topleft" +    name="panel_buttons" +    height="345" +    left="9"> +    <button +     layout="topleft" +     follows="left|top" +     top_pad="9" +     visible="true" +     height="23" +     label="Connect..." +     name="connect_btn" +     width="210"> +      <commit_callback function="SocialSharing.Connect"/> +    </button> + +    <button +     layout="topleft" +     follows="left|top" +     top_delta="0" +     height="23" +     label="Disconnect" +     name="disconnect_btn" +     width="210" +     visible="false"> +      <commit_callback function="SocialSharing.Disconnect"/> +    </button> +    <text +      layout="topleft" +      length="1" +      follows="top|left" +      height="16" +      left="0" +      name="account_learn_more_label" +      top_pad="20" +      type="string"> +      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Twitter] +    </text> +  </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml new file mode 100644 index 0000000000..058c65402a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml @@ -0,0 +1,152 @@ +    <panel +      height="400" +      width="304" +      layout="topleft" +      name="panel_twitter_photo"> +      <layout_stack +	   layout="topleft" +       border_size="0" +       height="392" +       follows="all" +       orientation="vertical" +       name="stack_photo" +       top="8"> +        <layout_panel	 +         name="snapshot_panel" +         height="367"> +            <combo_box +             control_name="SocialPhotoResolution" +             follows="left|top" +             top="6" +             left="9" +             name="resolution_combobox" +             tool_tip="Image resolution" +             height="21" +             width="135"> +              <combo_box.item +               label="Current Window" +               name="CurrentWindow" +               value="[i0,i0]" /> +              <combo_box.item +               label="640x480" +               name="640x480" +               value="[i640,i480]" /> +              <combo_box.item +               label="800x600" +               name="800x600" +               value="[i800,i600]" /> +              <combo_box.item +               label="1024x768" +               name="1024x768" +               value="[i1024,i768]" /> +            </combo_box> +            <text +             follows="left|top" +             font="SansSerifSmall" +             height="14" +             left="208" +             length="1" +             halign="right" +             name="file_size_label" +             top="9" +             type="string" +             width="50"> +              [SIZE] KB +            </text> +            <panel +                height="150" +                width="250" +                visible="true" +                name="thumbnail_placeholder" +                top="33" +                follows="left|top" +                left="9"> +            </panel> +            <button +             follows="left|top" +             height="23" +             label="Refresh" +             left="9" +             top_pad="5" +             name="new_snapshot_btn" +             tool_tip="Click to refresh" +             visible="true" +             width="100" > +             <button.commit_callback +               function="SocialSharing.RefreshPhoto" /> +            </button> +            <text +                follows="left|top" +                font="SansSerif" +                text_color="EmphasisColor" +                height="14" +                top_pad="-19" +                left_pad="-20" +                length="1" +                halign="center" +                name="working_lbl" +                translate="false" +                type="string" +                visible="true" +                width="150"> +                Refreshing... +            </text> +            <text +             length="1" +             follows="top|left|right" +             font="SansSerif" +             height="16" +             left="9" +             name="caption_label" +             top_pad="20" +             type="string"> +              Comment (optional): +            </text> +            <text_editor +             follows="left|top" +             height="87" +             width="250" +             left="9" +             length="1" +             max_length="700" +             name="photo_caption" +             type="string" +             word_wrap="true"> +            </text_editor> +            <check_box +             follows="left|top" +             initial_value="true" +             label="Include location in posting" +             name="add_location_cb" +              left="9" +              height="16" +             top_pad="8"/> +        </layout_panel> +        <layout_panel +          name="photo_button_panel" +          height="25"> +          <button +           follows="left|top" +           top="0" +           left="9" +           height="23" +           label="Post" +           name="post_photo_btn" +           width="100"> +            <button.commit_callback +             function="SocialSharing.SendPhoto" /> +          </button> +          <button +               follows="left|top" +               height="23" +               label="Cancel" +               name="cancel_photo_btn" +               left_pad="15" +               top_delta="0" +               width="100"> +            <button.commit_callback +             function="SocialSharing.Cancel" /> +          </button>           +        </layout_panel>         +      </layout_stack> +    </panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ce09faeac0..2b707ed84b 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -148,7 +148,7 @@ Please try logging in again in a minute.</string>  	<string name="SentToInvalidRegion">You were sent to an invalid region.</string>  	<string name="TestingDisconnect">Testing viewer disconnect</string> -	<!-- SLShare: Facebook, Flickr, and so on... --> +	<!-- SLShare: Facebook, Flickr, and Twitter -->    <string name="SocialFacebookConnecting">Connecting to Facebook...</string>    <string name="SocialFacebookPosting">Posting...</string>    <string name="SocialFacebookDisconnecting">Disconnecting from Facebook...</string> @@ -161,6 +161,12 @@ Please try logging in again in a minute.</string>    <string name="SocialFlickrErrorConnecting">Problem connecting to Flickr</string>    <string name="SocialFlickrErrorPosting">Problem posting to Flickr</string>    <string name="SocialFlickrErrorDisconnecting">Problem disconnecting from Flickr</string> +  <string name="SocialTwitterConnecting">Connecting to Twitter...</string> +  <string name="SocialTwitterPosting">Posting...</string> +  <string name="SocialTwitterDisconnecting">Disconnecting from Twitter...</string> +  <string name="SocialTwitterErrorConnecting">Problem connecting to Twitter</string> +  <string name="SocialTwitterErrorPosting">Problem posting to Twitter</string> +  <string name="SocialTwitterErrorDisconnecting">Problem disconnecting from Twitter</string>  	<!-- Tooltip -->  	<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar --> | 
