Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Content/Defaults/WBP_Thirdweb_OAuthOverlay.uasset
Binary file not shown.
Binary file modified Content/Examples/Widgets/WBP_Thirdweb_InApp.uasset
Binary file not shown.
Binary file modified Content/Level_Thirdweb.umap
Binary file not shown.
4 changes: 2 additions & 2 deletions Source/ThirdParty/Android/libthirdweb.a
Git LFS file not shown
4 changes: 2 additions & 2 deletions Source/ThirdParty/IOS/libthirdweb.a
Git LFS file not shown
4 changes: 2 additions & 2 deletions Source/ThirdParty/IOS/libthirdweb.sim.a
Git LFS file not shown
4 changes: 2 additions & 2 deletions Source/ThirdParty/Linux/libthirdweb.a
Git LFS file not shown
4 changes: 2 additions & 2 deletions Source/ThirdParty/LinuxArm64/libthirdweb.a
Git LFS file not shown
4 changes: 2 additions & 2 deletions Source/ThirdParty/Mac/libthirdweb.a
Git LFS file not shown
4 changes: 2 additions & 2 deletions Source/ThirdParty/Win64/libthirdweb.lib
Git LFS file not shown
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
#include "AsyncTasks/AsyncTaskThirdwebLoginWithOAuth.h"

#include "ThirdwebLog.h"
#include "ThirdwebOAuthBrowserUserWidget.h"
#include "TimerManager.h"

#include "Blueprint/UserWidget.h"

#include "Browser/ThirdwebOAuthBrowserUserWidget.h"

#include "Engine/World.h"

#include "Kismet/GameplayStatics.h"
Expand All @@ -16,7 +17,7 @@

void UAsyncTaskThirdwebLoginWithOAuth::Activate()
{
Browser->OnSuccess.AddDynamic(this, &ThisClass::HandleSuccess);
Browser->OnAuthenticated.AddDynamic(this, &ThisClass::HandleAuthenticated);
Browser->OnError.AddDynamic(this, &ThisClass::HandleFailed);
Browser->AddToViewport(10000);
Browser->Authenticate(Wallet);
Expand All @@ -42,9 +43,14 @@ void UAsyncTaskThirdwebLoginWithOAuth::HandleFailed(const FString& Error)
SetReadyToDestroy();
}

void UAsyncTaskThirdwebLoginWithOAuth::HandleSuccess()
void UAsyncTaskThirdwebLoginWithOAuth::HandleAuthenticated(const FString& AuthResult)
{
if (FString Error; !Wallet.SignInWithOAuth(AuthResult, Error))
{
return HandleFailed(Error);
}
Success.Broadcast(TEXT(""));
Browser->RemoveFromParent();
SetReadyToDestroy();
}

Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Copyright (c) 2024 Thirdweb. All Rights Reserved.

#include "ThirdwebOAuthBrowserUserWidget.h"
#include "Browser/ThirdwebOAuthBrowserUserWidget.h"

#include "ThirdwebLog.h"
#include "ThirdwebOAuthBrowserWidget.h"

#include "Blueprint/WidgetTree.h"

#include "Browser/ThirdwebOAuthBrowserWidget.h"

#include "Components/Button.h"
#include "Components/Overlay.h"
#include "Components/OverlaySlot.h"
#include "Components/PanelWidget.h"
Expand All @@ -20,23 +22,25 @@ TSharedRef<SWidget> UThirdwebOAuthBrowserUserWidget::RebuildWidget()

UPanelWidget* RootWidget = Cast<UPanelWidget>(GetRootWidget());

// Construct root widget if needed
if (!RootWidget)
{
RootWidget = WidgetTree->ConstructWidget<UOverlay>(UOverlay::StaticClass(), TEXT("RootWidget"));
WidgetTree->RootWidget = RootWidget;
}

// Construct children
if (RootWidget)
{
// Construct browser widget
Browser = WidgetTree->ConstructWidget<UThirdwebOAuthBrowserWidget>(UThirdwebOAuthBrowserWidget::StaticClass(), TEXT("ThirdwebOauthBrowser"));
Browser->OnUrlChanged.AddUniqueDynamic(this, &ThisClass::HandleUrlChanged);
Browser->OnUrlChanged.AddUObject(this, &ThisClass::HandleUrlChanged);
Browser->OnPageLoaded.AddUObject(this, &ThisClass::HandlePageLoaded);
UPanelSlot* PanelSlot = RootWidget->AddChild(Browser);
if (UOverlaySlot* RootWidgetSlot = Cast<UOverlaySlot>(PanelSlot))
{
TW_LOG(Warning, TEXT("ThirdwebOAuthBrowserUserWidget::RebuildWidget()"));
RootWidgetSlot->SetHorizontalAlignment(HAlign_Fill);
RootWidgetSlot->SetVerticalAlignment(VAlign_Fill);

}
}

Expand All @@ -60,11 +64,11 @@ void UThirdwebOAuthBrowserUserWidget::Authenticate(const FWalletHandle& InAppWal
{
if (!InAppWallet.IsValid())
{
TW_LOG(Error, TEXT("OAuthBrowserUserWidget::Authenticate::Wallet invalid"));\
TW_LOG(Error, TEXT("OAuthBrowserUserWidget::Authenticate::Wallet invalid"));
return OnError.Broadcast(TEXT("Invalid Wallet"));
}
Wallet = InAppWallet;

if (Browser)
{
FString Error;
Expand All @@ -77,8 +81,15 @@ void UThirdwebOAuthBrowserUserWidget::Authenticate(const FWalletHandle& InAppWal
}
}

// ReSharper disable once CppPassValueParameterByConstReference
void UThirdwebOAuthBrowserUserWidget::HandleUrlChanged(FString Url)

bool UThirdwebOAuthBrowserUserWidget::IsBlank() const
{
FString Url = Browser->GetUrl();

return Url.IsEmpty() || Url.StartsWith(BackendUrlPrefix);
}

void UThirdwebOAuthBrowserUserWidget::HandleUrlChanged(const FString& Url)
{
TW_LOG(Verbose, TEXT("OAuthBrowserUserWidget::HandleUrlChanged::%s"), *Url);
if (Url.IsEmpty() || Url.StartsWith(BackendUrlPrefix))
Expand All @@ -91,36 +102,45 @@ void UThirdwebOAuthBrowserUserWidget::HandleUrlChanged(FString Url)
FString Left, Right;
if (Url.Split(TEXT("authResult="), &Left, &Right, ESearchCase::IgnoreCase))
{
FString Error;
if (Wallet.SignInWithOAuth(Right, Error))
{
return OnSuccess.Broadcast();
}
return OnError.Broadcast(Error);
return OnAuthenticated.Broadcast(Right);
}
return OnError.Broadcast(TEXT("Failed to match AuthResult in url"));

}
SetVisible(true);
bShouldBeVisible = true;
}

void UThirdwebOAuthBrowserUserWidget::HandlePageLoaded(const FString& Url)
{
if (bShouldBeVisible)
{
SetVisible(true);
}
}

void UThirdwebOAuthBrowserUserWidget::SetVisible(const bool bVisible)
{
// Mobile webview needs to be visible to work
if (bVisible)
{
if (bCollapseWhenBlank)
{
#if PLATFORM_IOS | PLATFORM_ANDROID
SetRenderOpacity(1.0f);
SetRenderOpacity(1.0f);
#else
SetVisibility(ESlateVisibility::Visible);
SetVisibility(ESlateVisibility::Visible);
#endif
}
}
else
{
bShouldBeVisible = false;
if (bCollapseWhenBlank)
{
#if PLATFORM_IOS | PLATFORM_ANDROID
SetRenderOpacity(0.01f);
SetRenderOpacity(0.01f);
#else
SetVisibility(ESlateVisibility::Hidden);
SetVisibility(ESlateVisibility::Collapsed);
#endif
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) 2024 Thirdweb. All Rights Reserved.

#include "ThirdwebOAuthBrowserWidget.h"
#include "Browser/ThirdwebOAuthBrowserWidget.h"

#include "ThirdwebLog.h"

#include "Async//Async.h"
#include "Async/Async.h"

#include "GenericPlatform/GenericPlatformHttp.h"

Expand All @@ -14,6 +14,13 @@
#include "SWebBrowser.h"
#endif

#define ENSURE_VALID_BROWSER(FunctionName) \
if (!Browser.IsValid()) \
{ \
TW_LOG(Error, TEXT("OAuthBrowserWidget::%s::Web browser invalid"), TEXT(FunctionName)); \
return; \
}

const FString UThirdwebOAuthBrowserWidget::DummyUrl = TEXT("about:blank");

bool UThirdwebOAuthBrowserWidget::IsPageLoaded() const
Expand All @@ -25,6 +32,20 @@ bool UThirdwebOAuthBrowserWidget::IsPageLoaded() const
#endif
}

FString UThirdwebOAuthBrowserWidget::GetUrl() const
{
#if WITH_CEF
if (Browser.IsValid())
{
if (FString Url = Browser->GetUrl(); !Url.IsEmpty())
{
return FGenericPlatformHttp::UrlDecode(Url);
}
}
#endif
return TEXT("");
}

void UThirdwebOAuthBrowserWidget::ReleaseSlateResources(const bool bReleaseChildren)
{
Super::ReleaseSlateResources(bReleaseChildren);
Expand All @@ -44,34 +65,34 @@ const FText UThirdwebOAuthBrowserWidget::GetPaletteCategory()
void UThirdwebOAuthBrowserWidget::Authenticate(const FString& OAuthLoginUrl)
{
#if WITH_CEF
if (!Browser.IsValid())
{
TW_LOG(Error, TEXT("OAuthBrowserWidget::Authenticate::Web browser invalid"));
return;
}
TW_LOG(Log, TEXT("OAuthBrowserWidget::Authenticate::Loading %s"), *OAuthLoginUrl);
ENSURE_VALID_BROWSER("Authenticate")
TW_LOG(Verbose, TEXT("OAuthBrowserWidget::Authenticate::Loading %s"), *OAuthLoginUrl);
Browser->LoadURL(OAuthLoginUrl);
#endif
}

void UThirdwebOAuthBrowserWidget::HandleUrlChanged(const FText& InUrl)
{
#if WITH_CEF
ENSURE_VALID_BROWSER("HandleUrlChanged")
FString Url = InUrl.ToString();
TW_LOG(Log, TEXT("UThirdwebOAuthBrowserWidget::HandleUrlChanged:%s"), *Url);
TW_LOG(Verbose, TEXT("UThirdwebOAuthBrowserWidget::HandleUrlChanged:%s"), *Url);
if (Url.IsEmpty())
{
Url = Browser->GetUrl();
}
TW_LOG(Log, TEXT("UThirdwebOAuthBrowserWidget::HandleUrlChanged:%s"), *Url);
TW_LOG(Verbose, TEXT("UThirdwebOAuthBrowserWidget::HandleUrlChanged:%s"), *Url);
// Ensure this code runs on the game thread
AsyncTask(ENamedThreads::GameThread, [&, Url]()
{
if (IsInGameThread())
{
OnUrlChanged.Broadcast(FGenericPlatformHttp::UrlDecode(Url));
}
});
AsyncTask(ENamedThreads::GameThread, [&, Url]() { if (IsInGameThread()) OnUrlChanged.Broadcast(FGenericPlatformHttp::UrlDecode(Url)); });
#endif
}

void UThirdwebOAuthBrowserWidget::HandleOnLoadComplete()
{
#if WITH_CEF
ENSURE_VALID_BROWSER("HandleOnLoadComplete")
FString Url = Browser->GetUrl();
AsyncTask(ENamedThreads::GameThread, [&, Url]() { if (IsInGameThread()) OnPageLoaded.Broadcast(FGenericPlatformHttp::UrlDecode(Url)); });
#endif
}

Expand All @@ -85,6 +106,7 @@ TSharedRef<SWidget> UThirdwebOAuthBrowserWidget::RebuildWidget()
.ShowControls(false)
.SupportsTransparency(bSupportsTransparency)
.ShowInitialThrobber(bShowInitialThrobber)
.OnLoadCompleted(BIND_UOBJECT_DELEGATE(FSimpleDelegate, HandleOnLoadComplete))
.OnUrlChanged(BIND_UOBJECT_DELEGATE(FOnTextChanged, HandleUrlChanged));

return Browser.ToSharedRef();
Expand Down
68 changes: 68 additions & 0 deletions Source/Thirdweb/Private/ThirdwebInternal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "ThirdwebInternal.h"

#include "HttpModule.h"
#include "ThirdwebRuntimeSettings.h"
#include "ThirdwebUtils.h"

#include "Dom/JsonObject.h"

#include "Interfaces/IPluginManager.h"

#include "Kismet/GameplayStatics.h"

#include "Policies/CondensedJsonPrintPolicy.h"

#include "Serialization/JsonSerializer.h"
#include "Serialization/JsonWriter.h"

FString FThirdwebAnalytics::JsonObjectToString(const TSharedPtr<FJsonObject>& JsonObject)
{
FString Out;
const TSharedRef<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> Writer = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&Out);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
return Out;
}

FString FThirdwebAnalytics::GetPluginVersion()
{
if (const TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(TEXT("Thirdweb")); Plugin.IsValid())
{
return Plugin->GetDescriptor().VersionName;
}
return "0.0.0";
}

void FThirdwebAnalytics::SendConnectEvent(const FString& Wallet, const FString& Type)
{
const UThirdwebRuntimeSettings* Settings = UThirdwebRuntimeSettings::Get();
if (!Settings->bSendAnalytics || (Settings->BundleID.IsEmpty() && Settings->ClientID.IsEmpty() && Settings->SecretKey.IsEmpty()))
{
return;
}
FHttpModule& HttpModule = FHttpModule::Get();
const TSharedRef<IHttpRequest> Request = HttpModule.CreateRequest();
Request->SetVerb("POST");
Request->SetURL("https://c.thirdweb.com/event");
Request->SetHeader("Content-Type", "application/json");
Request->SetHeader("x-sdk-name", "UnrealEngineSDK");
Request->SetHeader("x-sdk-os", UGameplayStatics::GetPlatformName());
Request->SetHeader("x-sdk-platform", "unreal-engine");
Request->SetHeader("x-sdk-version", GetPluginVersion());
if (!Settings->SecretKey.IsEmpty())
{
Request->SetHeader("x-client-id", ThirdwebUtils::GetClientIdFromSecretKey(Settings->SecretKey));
} else
{
Request->SetHeader("x-client-id", Settings->ClientID);
Request->SetHeader("x-bundle-id", Settings->BundleID);
}
Request->SetTimeout(5.0f);

TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
JsonObject->SetStringField(TEXT("source"), TEXT("connectWallet"));
JsonObject->SetStringField(TEXT("action"), TEXT("connect"));
JsonObject->SetStringField(TEXT("walletAddress"), Wallet);
JsonObject->SetStringField(TEXT("walletType"), Type);
Request->SetContentAsString(JsonObjectToString(JsonObject));
Request->ProcessRequest();
}
1 change: 1 addition & 0 deletions Source/Thirdweb/Private/ThirdwebRuntimeSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
UThirdwebRuntimeSettings::UThirdwebRuntimeSettings()
{
AuthenticationMethod = EThirdwebAuthenticationMethod::ClientID;
bSendAnalytics = true;
}
Loading