bool FCrashReportClient::Tick(float UnusedDeltaTime)
{
	// We are waiting for diagnose report task to complete.
	if( IsProcessingCallstack() )
	{
		return true;
	}
	
	if( bSendData )
	{
		if( !bBeginUploadCalled )
		{
			// Can be called only when we have all files.
			Uploader.BeginUpload( ErrorReport );
			bBeginUploadCalled = true;
		}

		// IsWorkDone will always return true here (since uploader can't finish until the diagnosis has been sent), but it
		//  has the side effect of joining the worker thread.
		if( !Uploader.IsFinished() )
		{
			// More ticks, please
			return true;
		}
	}

	FPlatformMisc::RequestExit(false);
	return false;
}
bool FCrashReportClient::Tick(float UnusedDeltaTime)
{
	// We are waiting for diagnose report task to complete.
	if( IsProcessingCallstack() )
	{
		return true;
	}
	
	if( bSendData )
	{
		if (!FCrashUploadBase::IsInitialized())
		{
			FCrashUploadBase::StaticInitialize( ErrorReport );
		}

		if (ReceiverUploader.IsEnabled())
		{
			if (!ReceiverUploader.IsUploadCalled())
			{
				// Can be called only when we have all files.
				ReceiverUploader.BeginUpload(ErrorReport);
			}

			// IsWorkDone will always return true here (since ReceiverUploader can't finish until the diagnosis has been sent), but it
			//  has the side effect of joining the worker thread.
			if (!ReceiverUploader.IsFinished())
			{
				// More ticks, please
				return true;
			}
		}

		if (DataRouterUploader.IsEnabled())
		{
			if (!DataRouterUploader.IsUploadCalled())
			{
				// Can be called only when we have all files.
				DataRouterUploader.BeginUpload(ErrorReport);
			}

			// IsWorkDone will always return true here (since DataRouterUploader can't finish until the diagnosis has been sent), but it
			//  has the side effect of joining the worker thread.
			if (!DataRouterUploader.IsFinished())
			{
				// More ticks, please
				return true;
			}
		}
	}

	if (FCrashUploadBase::IsInitialized())
	{
		FCrashUploadBase::StaticShutdown();
	}

	FPlatformMisc::RequestExit(false);
	return false;
}
EVisibility FCrashReportClient::IsThrobberVisible() const
{
	return IsProcessingCallstack() ? EVisibility::Visible : EVisibility::Hidden;
}
bool FCrashReportClient::AreCallstackWidgetsEnabled() const
{
	return !IsProcessingCallstack();
}