From 37c902d1a5d4f505ac5d4d23a793564215744946 Mon Sep 17 00:00:00 2001 From: cat Date: Wed, 28 Jan 2026 20:42:48 +0800 Subject: [PATCH 1/3] feat: earn button on home --- FRW.xcodeproj/project.pbxproj | 6 +++ FRW/Foundation/Define/AppUrl.swift | 1 + FRW/Modules/Wallet/View/EarnButton.swift | 37 +++++++++++++++++++ FRW/Modules/Wallet/WalletHomeView.swift | 6 ++- FRW/Modules/Wallet/WalletViewModel.swift | 5 ++- .../wallet/earn_icon.imageset/Contents.json | 12 ++++++ .../wallet/earn_icon.imageset/earn_icon.svg | 5 +++ 7 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 FRW/Modules/Wallet/View/EarnButton.swift create mode 100644 FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/Contents.json create mode 100644 FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/earn_icon.svg diff --git a/FRW.xcodeproj/project.pbxproj b/FRW.xcodeproj/project.pbxproj index cf6a01ddc..314bd720d 100644 --- a/FRW.xcodeproj/project.pbxproj +++ b/FRW.xcodeproj/project.pbxproj @@ -1543,6 +1543,8 @@ 4E722F362ED9A96600627AAD /* EOAPrivateKeyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E722F342ED9A96600627AAD /* EOAPrivateKeyView.swift */; }; 4E722F382ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E722F372ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift */; }; 4E722F392ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E722F372ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift */; }; + 4E73FAC12F2A378200AF2711 /* EarnButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E73FAC02F2A378200AF2711 /* EarnButton.swift */; }; + 4E73FAC22F2A378200AF2711 /* EarnButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E73FAC02F2A378200AF2711 /* EarnButton.swift */; }; 4E7712E12E3B2AD70011C1DA /* RNBridgeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7712E02E3B2AD70011C1DA /* RNBridgeError.swift */; }; 4E7712E22E3B2AD70011C1DA /* RNBridgeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7712E02E3B2AD70011C1DA /* RNBridgeError.swift */; }; 4E777CAE2B1ECF8900300A3E /* SyncInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E777CAD2B1ECF8900300A3E /* SyncInfo.swift */; }; @@ -3226,6 +3228,7 @@ 4E7153232E97564D00C5D0BA /* RouteMap+Dev.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RouteMap+Dev.swift"; sourceTree = ""; }; 4E722F342ED9A96600627AAD /* EOAPrivateKeyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EOAPrivateKeyView.swift; sourceTree = ""; }; 4E722F372ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedAccountDetailViewModel.swift; sourceTree = ""; }; + 4E73FAC02F2A378200AF2711 /* EarnButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EarnButton.swift; sourceTree = ""; }; 4E7712E02E3B2AD70011C1DA /* RNBridgeError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNBridgeError.swift; sourceTree = ""; }; 4E777CAD2B1ECF8900300A3E /* SyncInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncInfo.swift; sourceTree = ""; }; 4E777CB02B1EE69E00300A3E /* WalletConnect+SyncDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WalletConnect+SyncDevice.swift"; sourceTree = ""; }; @@ -4185,6 +4188,7 @@ 15362A172DA02BA1008F4E51 /* VisualEffectView.swift */, 15362A1A2DA02BCD008F4E51 /* CoinCell.swift */, 4EB2C3092DC0E2F900E79FC5 /* FilterButton.swift */, + 4E73FAC02F2A378200AF2711 /* EarnButton.swift */, ); path = View; sourceTree = ""; @@ -9273,6 +9277,7 @@ 4ED4831B2DA515FC00AA23E6 /* BlocklistHandler.swift in Sources */, 6A06CB1128AA54A600C81BE1 /* NFTUIKitGridStyleHandler.swift in Sources */, 1586370D2D6BF1EC0083A068 /* TokenBalanceListView.swift in Sources */, + 4E73FAC22F2A378200AF2711 /* EarnButton.swift in Sources */, 6AC476ED28F40E50008503E6 /* BrowserBookmarkView.swift in Sources */, 4E1A8B702B71A7FA00485EDE /* MultiBackupConfirmPinViewModel.swift in Sources */, 6A8FA4B4285B192900EE5BE3 /* ScrollView+SnappableModifier.swift in Sources */, @@ -10374,6 +10379,7 @@ 15C58BAD2868A4EE00BD4FC6 /* ScrollView+SnappableModifier.swift in Sources */, 4ED4831A2DA515FC00AA23E6 /* BlocklistHandler.swift in Sources */, 6AC476EC28F40E50008503E6 /* BrowserBookmarkView.swift in Sources */, + 4E73FAC12F2A378200AF2711 /* EarnButton.swift in Sources */, 1586370C2D6BF1EC0083A068 /* TokenBalanceListView.swift in Sources */, 15C58BAE2868A4EE00BD4FC6 /* VNavigationViewNavigationBar.swift in Sources */, 4E1A8B6F2B71A7FA00485EDE /* MultiBackupConfirmPinViewModel.swift in Sources */, diff --git a/FRW/Foundation/Define/AppUrl.swift b/FRW/Foundation/Define/AppUrl.swift index b1af6609e..36512b757 100644 --- a/FRW/Foundation/Define/AppUrl.swift +++ b/FRW/Foundation/Define/AppUrl.swift @@ -10,4 +10,5 @@ import Foundation enum AppUrl { static let cadenceSwapUrl = "https://app.increment.fi" static let evmSwapUrl = "https://swap.flow.com" + static let earnUrl = "" //TODO: #six 3.1.1 } diff --git a/FRW/Modules/Wallet/View/EarnButton.swift b/FRW/Modules/Wallet/View/EarnButton.swift new file mode 100644 index 000000000..e16a9b2aa --- /dev/null +++ b/FRW/Modules/Wallet/View/EarnButton.swift @@ -0,0 +1,37 @@ +// +// EarnButton.swift +// FRW +// +// Created by cat on 28/1/26. +// + +import SwiftUI + +struct EarnButton: View { + var body: some View { + Button { + if let url = URL(string: AppUrl.earnUrl) { + Router.route(to: RouteMap.Explore.browser(url)) + } else { + HUD.error(title: "don't have earn url") + } + } label: { + HStack(spacing: 10) { + Text("earn".localized) + .font(.inter(size: 16, weight: .medium)) + .foregroundStyle(Color.Brain.Core.icons) + Image("earn_icon") + .resizable() + .frame(width: 20, height: 20) + } + .frame(height: 40) + .padding(.horizontal, 12) + .background(Color.Brain.Light.lines10) + .cornerRadius(20) + } + } +} + +#Preview { + EarnButton() +} diff --git a/FRW/Modules/Wallet/WalletHomeView.swift b/FRW/Modules/Wallet/WalletHomeView.swift index 389db5f82..07d088f32 100644 --- a/FRW/Modules/Wallet/WalletHomeView.swift +++ b/FRW/Modules/Wallet/WalletHomeView.swift @@ -451,7 +451,11 @@ struct WalletHomeView: View { .font(.inter(size: 18, weight: .bold)) .foregroundStyle(Color.Theme.Text.black3) Spacer() - + + if vm.showEarnButton { + EarnButton() + } + CircleButton(image: .menu) { vm.onClickManagerToken() } diff --git a/FRW/Modules/Wallet/WalletViewModel.swift b/FRW/Modules/Wallet/WalletViewModel.swift index c45837512..2a0f13574 100644 --- a/FRW/Modules/Wallet/WalletViewModel.swift +++ b/FRW/Modules/Wallet/WalletViewModel.swift @@ -184,7 +184,10 @@ final class WalletViewModel: ObservableObject { @Published var walletAccount: WalletAccount? = nil - + + @Published + var showEarnButton: Bool = true + var needShowPlaceholder: Bool { isMock || walletState == .noAddress } diff --git a/FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/Contents.json b/FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/Contents.json new file mode 100644 index 000000000..b66e4fc72 --- /dev/null +++ b/FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "earn_icon.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/earn_icon.svg b/FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/earn_icon.svg new file mode 100644 index 000000000..5e9f88687 --- /dev/null +++ b/FRW/Resource/Assets.xcassets/wallet/earn_icon.imageset/earn_icon.svg @@ -0,0 +1,5 @@ + + + + + From 999a1f1b43fbf798df8ba7310e4c1a4cd0b03008 Mon Sep 17 00:00:00 2001 From: cat Date: Wed, 28 Jan 2026 21:35:36 +0800 Subject: [PATCH 2/3] feat: add earn banner to token detail --- FRW.xcodeproj/project.pbxproj | 6 ++ .../Wallet/TokenDetail/TokenDetailView.swift | 4 ++ .../TokenDetail/TokenDetailViewModel.swift | 4 +- FRW/Modules/Wallet/View/EarnBanner.swift | 63 ++++++++++++++++++ .../earn_icon_36.imageset/Contents.json | 12 ++++ .../earn_icon_36.imageset/earn_icon_36.pdf | Bin 0 -> 5905 bytes 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 FRW/Modules/Wallet/View/EarnBanner.swift create mode 100644 FRW/Resource/Assets.xcassets/wallet/earn_icon_36.imageset/Contents.json create mode 100644 FRW/Resource/Assets.xcassets/wallet/earn_icon_36.imageset/earn_icon_36.pdf diff --git a/FRW.xcodeproj/project.pbxproj b/FRW.xcodeproj/project.pbxproj index 314bd720d..d5f551e68 100644 --- a/FRW.xcodeproj/project.pbxproj +++ b/FRW.xcodeproj/project.pbxproj @@ -1545,6 +1545,8 @@ 4E722F392ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E722F372ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift */; }; 4E73FAC12F2A378200AF2711 /* EarnButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E73FAC02F2A378200AF2711 /* EarnButton.swift */; }; 4E73FAC22F2A378200AF2711 /* EarnButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E73FAC02F2A378200AF2711 /* EarnButton.swift */; }; + 4E73FAC42F2A3C1200AF2711 /* EarnBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E73FAC32F2A3C1200AF2711 /* EarnBanner.swift */; }; + 4E73FAC52F2A3C1200AF2711 /* EarnBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E73FAC32F2A3C1200AF2711 /* EarnBanner.swift */; }; 4E7712E12E3B2AD70011C1DA /* RNBridgeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7712E02E3B2AD70011C1DA /* RNBridgeError.swift */; }; 4E7712E22E3B2AD70011C1DA /* RNBridgeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7712E02E3B2AD70011C1DA /* RNBridgeError.swift */; }; 4E777CAE2B1ECF8900300A3E /* SyncInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E777CAD2B1ECF8900300A3E /* SyncInfo.swift */; }; @@ -3229,6 +3231,7 @@ 4E722F342ED9A96600627AAD /* EOAPrivateKeyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EOAPrivateKeyView.swift; sourceTree = ""; }; 4E722F372ED9AF8B00627AAD /* LinkedAccountDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedAccountDetailViewModel.swift; sourceTree = ""; }; 4E73FAC02F2A378200AF2711 /* EarnButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EarnButton.swift; sourceTree = ""; }; + 4E73FAC32F2A3C1200AF2711 /* EarnBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EarnBanner.swift; sourceTree = ""; }; 4E7712E02E3B2AD70011C1DA /* RNBridgeError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNBridgeError.swift; sourceTree = ""; }; 4E777CAD2B1ECF8900300A3E /* SyncInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncInfo.swift; sourceTree = ""; }; 4E777CB02B1EE69E00300A3E /* WalletConnect+SyncDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WalletConnect+SyncDevice.swift"; sourceTree = ""; }; @@ -4189,6 +4192,7 @@ 15362A1A2DA02BCD008F4E51 /* CoinCell.swift */, 4EB2C3092DC0E2F900E79FC5 /* FilterButton.swift */, 4E73FAC02F2A378200AF2711 /* EarnButton.swift */, + 4E73FAC32F2A3C1200AF2711 /* EarnBanner.swift */, ); path = View; sourceTree = ""; @@ -8679,6 +8683,7 @@ 153749082E26FDD60040E3F8 /* SPPopoverController.swift in Sources */, 153749092E26FDD60040E3F8 /* SPDimmedButton+Colorise.swift in Sources */, 1537490A2E26FDD60040E3F8 /* UISwitchExtension.swift in Sources */, + 4E73FAC52F2A3C1200AF2711 /* EarnBanner.swift in Sources */, 1537490B2E26FDD60040E3F8 /* UIFontExtension.swift in Sources */, 1537490C2E26FDD60040E3F8 /* SPCollectionViewController.swift in Sources */, 1537490D2E26FDD60040E3F8 /* CollectionExtension.swift in Sources */, @@ -9781,6 +9786,7 @@ 153749602E26FDD60040E3F8 /* SPPopoverController.swift in Sources */, 153749612E26FDD60040E3F8 /* SPDimmedButton+Colorise.swift in Sources */, 153749622E26FDD60040E3F8 /* UISwitchExtension.swift in Sources */, + 4E73FAC42F2A3C1200AF2711 /* EarnBanner.swift in Sources */, 153749632E26FDD60040E3F8 /* UIFontExtension.swift in Sources */, 153749642E26FDD60040E3F8 /* SPCollectionViewController.swift in Sources */, 153749652E26FDD60040E3F8 /* CollectionExtension.swift in Sources */, diff --git a/FRW/Modules/Wallet/TokenDetail/TokenDetailView.swift b/FRW/Modules/Wallet/TokenDetail/TokenDetailView.swift index a713fcdc9..c2723a369 100644 --- a/FRW/Modules/Wallet/TokenDetail/TokenDetailView.swift +++ b/FRW/Modules/Wallet/TokenDetail/TokenDetailView.swift @@ -42,6 +42,10 @@ struct TokenDetailView: RouteableView { .visibility(showAccessibleWarning() ? .visible : .gone) summaryView + if vm.showEarnBanner { + EarnBanner() + } + unverifiedTokenView .visibility(vm.token.isVerifiedValue ? .gone : .visible) diff --git a/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift b/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift index 45e44c0ff..e8c74924c 100644 --- a/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift +++ b/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift @@ -184,7 +184,9 @@ class TokenDetailViewModel: ObservableObject { var showStorageView: Bool { token.isFlowCoin && wallet.selectedAccount?.type == .main } var isTokenDetailsButtonEnabled: Bool { token.website.isNotNullNorEmpty } - + + @Published + var showEarnBanner: Bool = true // MARK: Private private var cancelSets = Set() diff --git a/FRW/Modules/Wallet/View/EarnBanner.swift b/FRW/Modules/Wallet/View/EarnBanner.swift new file mode 100644 index 000000000..2c9a06de7 --- /dev/null +++ b/FRW/Modules/Wallet/View/EarnBanner.swift @@ -0,0 +1,63 @@ +// +// EarnBanner.swift +// FRW +// +// Created by cat on 28/1/26. +// + +import SwiftUI + +struct EarnBanner: View { + var body: some View { + Button{ + if let url = URL(string: AppUrl.earnUrl) { + Router.route(to: RouteMap.Explore.browser(url)) + } else { + HUD.error(title: "don't have earn url") + } + } label: { + HStack(alignment: .center, spacing: 0) { + VStack(alignment: .leading, spacing: 4) { + Text("Don’t miss out on $1,203 this year") + .font(.inter(size: 14)) + .lineLimit(1) + .foregroundStyle(Color.white) + + Text("Earn 15% APY on Flow Vaults") + .font(.inter(size: 16, weight: .semibold)) + .lineLimit(1) + .foregroundStyle(Color.Brain.Primary.main) + } + Spacer() + Image("earn_icon_36") + .resizable() + .frame(width: 20, height: 20) + .padding(8) + .background(Color.Brain.Primary.main) + .clipShape(Circle()) + } + .padding(18) + .frame(width: .infinity, alignment: .leading) + .background( + LinearGradient( + stops: [ + Gradient.Stop(color: Color(red: 0.1, green: 0.1, blue: 0.1), location: 0.00), + Gradient.Stop(color: Color(red: 0, green: 0.94, blue: 0.55), location: 1.00), + ], + startPoint: UnitPoint(x: 0.75, y: 1), + endPoint: UnitPoint(x: 0.75, y: -5) + ) + ) + .cornerRadius(16) + .overlay( + RoundedRectangle(cornerRadius: 16) + .inset(by: 0.25) + .stroke(Color(red: 0.09, green: 1, blue: 0.6), lineWidth: 0.5) + ) + } + } +} + +#Preview { + EarnBanner() +} diff --git a/FRW/Resource/Assets.xcassets/wallet/earn_icon_36.imageset/Contents.json b/FRW/Resource/Assets.xcassets/wallet/earn_icon_36.imageset/Contents.json new file mode 100644 index 000000000..7a045a698 --- /dev/null +++ b/FRW/Resource/Assets.xcassets/wallet/earn_icon_36.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "earn_icon_36.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FRW/Resource/Assets.xcassets/wallet/earn_icon_36.imageset/earn_icon_36.pdf b/FRW/Resource/Assets.xcassets/wallet/earn_icon_36.imageset/earn_icon_36.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b1b91651bb6e703e7d60d52cb8f7b7407cc4ea72 GIT binary patch literal 5905 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 e%!Uwv2OR= Date: Thu, 29 Jan 2026 08:51:20 +0800 Subject: [PATCH 3/3] feat: add flag to earn --- FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift | 2 +- FRW/Modules/Wallet/WalletViewModel.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift b/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift index e8c74924c..c56eaf42f 100644 --- a/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift +++ b/FRW/Modules/Wallet/TokenDetail/TokenDetailViewModel.swift @@ -186,7 +186,7 @@ class TokenDetailViewModel: ObservableObject { var isTokenDetailsButtonEnabled: Bool { token.website.isNotNullNorEmpty } @Published - var showEarnBanner: Bool = true + var showEarnBanner: Bool = !AppUrl.earnUrl.isEmpty // MARK: Private private var cancelSets = Set() diff --git a/FRW/Modules/Wallet/WalletViewModel.swift b/FRW/Modules/Wallet/WalletViewModel.swift index 2a0f13574..8b4fa7db3 100644 --- a/FRW/Modules/Wallet/WalletViewModel.swift +++ b/FRW/Modules/Wallet/WalletViewModel.swift @@ -186,7 +186,7 @@ final class WalletViewModel: ObservableObject { var walletAccount: WalletAccount? = nil @Published - var showEarnButton: Bool = true + var showEarnButton: Bool = !AppUrl.earnUrl.isEmpty var needShowPlaceholder: Bool { isMock || walletState == .noAddress