Skip to content

Commit

Permalink
Merge pull request #1027 from novasamatech/develop
Browse files Browse the repository at this point in the history
7.10.0 Push Notifications
  • Loading branch information
ERussel committed Apr 2, 2024
2 parents 0893b81 + ef7caf6 commit 17dcd4a
Show file tree
Hide file tree
Showing 257 changed files with 12,988 additions and 870 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/deploy_staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ jobs:
echo "BUILD_PROVISION_PROFILE_BASE64=${{ secrets.STAGING_PROVISIONING_PROFILE_BASE64 }}" >> "$GITHUB_ENV"
else
echo "BUILD_PROVISION_PROFILE_BASE64=${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}" >> "$GITHUB_ENV"
echo "PUSH_NOTIFICATIONS_EXT_PROFILE_BASE64=${{ secrets.PUSH_NOTIFICATIONS_EXT_PROFILE_BASE64 }}" >> "$GITHUB_ENV"
fi
# Source https://docs.github.com/en/actions/deployment/installing-an-apple-certificate-on-macos-runners-for-xcode-development#add-a-step-to-your-workflow
Expand All @@ -64,11 +65,13 @@ jobs:
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
PUSH_NOTIFICATIONS_PP_PATH=$RUNNER_TEMP/push_notifications_build_pp.mobileprovision
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH
echo -n "$PUSH_NOTIFICATIONS_EXT_PROFILE_BASE64" | base64 --decode --output $PUSH_NOTIFICATIONS_PP_PATH
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
Expand All @@ -82,6 +85,7 @@ jobs:
# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
cp $PUSH_NOTIFICATIONS_PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
- name: Bump version
uses: damienaicheh/update-ios-version-info-plist-action@v1.0.0
Expand All @@ -91,6 +95,14 @@ jobs:
bundle-version: ${{github.run_number}}
print-file: true

- name: Push Notifications Setup
env:
GOOGLE_SERVICE_INFO: ${{ secrets.GOOGLE_SERVICE_FILE_CONTENT }}
run: |
GOOGLE_SERVICE_PATH=./novawallet/GoogleService-Info-Dev.plist
echo "$GOOGLE_SERVICE_INFO" > $GOOGLE_SERVICE_PATH
- name: Archive
env:
MERCURYO_PRODUCTION_SECRET: ${{ secrets.MERCURYO_PRODUCTION_SECRET }}
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ jobs:
echo $default | cat >default
echo Using default scheme: $default
- name: Push Notifications Setup
env:
GOOGLE_SERVICE_INFO: ${{ secrets.GOOGLE_SERVICE_FILE_CONTENT }}
run: |
GOOGLE_SERVICE_PATH=./novawallet/GoogleService-Info-Dev.plist
echo "$GOOGLE_SERVICE_INFO" > $GOOGLE_SERVICE_PATH
- name: Build
env:
scheme: ${{ 'default' }}
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/push_develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,19 @@ jobs:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ""
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
PUSH_NOTIFICATIONS_EXT_PROFILE_BASE64: ${{ secrets.PUSH_NOTIFICATIONS_EXT_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
PUSH_NOTIFICATIONS_PP_PATH=$RUNNER_TEMP/push_notifications_build_pp.mobileprovision
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH
echo -n "$PUSH_NOTIFICATIONS_EXT_PROFILE_BASE64" | base64 --decode --output $PUSH_NOTIFICATIONS_PP_PATH
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
Expand All @@ -58,6 +61,15 @@ jobs:
# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
cp $PUSH_NOTIFICATIONS_PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
- name: Push Notifications Setup
env:
GOOGLE_SERVICE_INFO: ${{ secrets.GOOGLE_SERVICE_FILE_CONTENT }}
run: |
GOOGLE_SERVICE_PATH=./novawallet/GoogleService-Info-Dev.plist
echo "$GOOGLE_SERVICE_INFO" > $GOOGLE_SERVICE_PATH
- name: Bump version
uses: damienaicheh/update-ios-version-info-plist-action@v1.0.0
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ Tests/Mocks/ModuleMocks.swift
Templates/
# Misc
**/.DS_Store
GoogleService-Info-*.plist
GoogleService-Info.plist
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ excluded:
- R.generated.swift
- novawalletTests
- novawalletIntegrationTests
- NovaPushNotificationServiceExtension/R.generated.swift
identifier_name:
excluded:
- id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "../../Pods/Target Support Files/Pods-NovaPushNotificationServiceExtension/Pods-NovaPushNotificationServiceExtension.debug.xcconfig"

OTHER_SWIFT_FLAGS = $(inherited) "-DF_DEV"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "../../Pods/Target Support Files/Pods-NovaPushNotificationServiceExtension/Pods-NovaPushNotificationServiceExtension.dev.xcconfig"

OTHER_SWIFT_FLAGS = $(inherited) "-DF_DEV"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "../../Pods/Target Support Files/Pods-NovaPushNotificationServiceExtension/Pods-NovaPushNotificationServiceExtension.release.xcconfig"

OTHER_SWIFT_FLAGS = $(inherited) "-DF_RELEASE"
142 changes: 142 additions & 0 deletions NovaPushNotificationServiceExtension/Handlers/CommonHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import RobinHood
import SoraFoundation
import SoraKeystore
import BigInt

class CommonHandler {
let userStorageFacade: StorageFacadeProtocol
let substrateStorageFacade: StorageFacadeProtocol
var locale: Locale {
LocalizationManager.shared.selectedLocale
}

lazy var settingsRepository: AnyDataProviderRepository<Web3Alert.LocalSettings> = createSettingsRepository()
lazy var chainsRepository: AnyDataProviderRepository<ChainModel> = createChainsRepository()
let settingsManager: SettingsManagerProtocol

init(
userStorageFacade: StorageFacadeProtocol = UserDataStorageFacade.shared,
substrateStorageFacade: StorageFacadeProtocol = SubstrateDataStorageFacade.shared,
settingsManager: SettingsManagerProtocol = SharedSettingsManager() ?? SettingsManager.shared
) {
self.userStorageFacade = userStorageFacade
self.substrateStorageFacade = substrateStorageFacade
self.settingsManager = settingsManager
}

func createSettingsRepository() -> AnyDataProviderRepository<Web3Alert.LocalSettings> {
let pushSettings = NSPredicate(
format: "%K == %@",
#keyPath(CDUserSingleValue.identifier),
Web3Alert.LocalSettings.getIdentifier()
)

let repository: CoreDataRepository<Web3Alert.LocalSettings, CDUserSingleValue> =
userStorageFacade.createRepository(
filter: pushSettings,
sortDescriptors: [],
mapper: AnyCoreDataMapper(Web3AlertSettingsMapper())
)

return AnyDataProviderRepository(repository)
}

func createChainsRepository() -> AnyDataProviderRepository<ChainModel> {
let mapper = ChainModelMapper()
let repository = substrateStorageFacade.createRepository(
filter: nil,
sortDescriptors: [],
mapper: AnyCoreDataMapper(mapper)
)

return AnyDataProviderRepository(repository)
}

func search(chainId: ChainModel.Id, in chains: [ChainModel]) -> ChainModel? {
chains.first(where: { chain in
let remoteChainId = Web3Alert.createRemoteChainId(from: chain.chainId)
return remoteChainId == chainId
})
}
}

extension CommonHandler {
func balanceViewModel(
asset: AssetModel,
amount: String,
priceData: PriceData?,
workingQueue: OperationQueue
) -> BalanceViewModelProtocol? {
guard
let currencyManager = currencyManager(operationQueue: workingQueue),
let amountInPlank = BigUInt(amount) else {
return nil
}
let decimalAmount = amountInPlank.decimal(precision: asset.precision)
let priceAssetInfoFactory = PriceAssetInfoFactory(currencyManager: currencyManager)
let factory = PrimitiveBalanceViewModelFactory(
targetAssetInfo: asset.displayInfo,
priceAssetInfoFactory: priceAssetInfoFactory,
formatterFactory: AssetBalanceFormatterFactory()
)
return factory.balanceFromPrice(decimalAmount, priceData: priceData).value(for: locale)
}

func priceRepository(for priceId: String, currencyId: Int) -> CoreDataRepository<PriceData, CDPrice> {
let mapper = PriceDataMapper()
let identifier = PriceData.createIdentifier(for: priceId, currencyId: currencyId)
let filter = NSPredicate(format: "%K == %@", #keyPath(CDPrice.identifier), identifier)

let repository: CoreDataRepository<PriceData, CDPrice> = substrateStorageFacade.createRepository(
filter: filter,
sortDescriptors: [],
mapper: AnyCoreDataMapper(mapper)
)

return repository
}

func currencyManager(operationQueue: OperationQueue) -> CurrencyManagerProtocol? {
try? CurrencyManager(
currencyRepository: CurrencyRepository(),
settingsManager: SharedSettingsManager() ?? SettingsManager.shared,
queue: operationQueue
)
}

func targetWalletName(
for address: AccountAddress?,
chainId: ChainModel.Id,
wallets: [Web3Alert.LocalWallet],
metaAccounts: [MetaAccountModel]
) -> String? {
guard let address = address, wallets.count > 1 else {
return nil
}

guard let targetWallet = wallets.first(where: {
if let specificAddress = $0.model.chainSpecific[chainId] {
return specificAddress == address
} else {
return $0.model.baseSubstrate == address ||
$0.model.baseEthereum == address
}
}) else {
return nil
}

return metaAccounts.first(where: { $0.metaId == targetWallet.metaId })?.name
}

func walletsRepository() -> AnyDataProviderRepository<MetaAccountModel> {
let mapper = MetaAccountMapper()

let repository = userStorageFacade.createRepository(
filter: nil,
sortDescriptors: [],
mapper: AnyCoreDataMapper(mapper)
)

return AnyDataProviderRepository(repository)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import SoraFoundation

extension LocalizationManager {
func refreshLocale() {
if let settingsKey = settingsKey,
let localization = settings?.string(for: settingsKey) {
selectedLocalization = localization
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation

extension ReferendumStateUpdatePayload.Status {
func description(for locale: Locale?) -> String {
switch self {
case .created:
return R.string.localizable.pushNotificationReferendumCreated(preferredLanguages: locale?.rLanguages)
case .deciding:
return R.string.localizable.pushNotificationReferendumDeciding(preferredLanguages: locale?.rLanguages)
case .confirming:
return R.string.localizable.pushNotificationReferendumConfirming(preferredLanguages: locale?.rLanguages)
case .approved:
return R.string.localizable.pushNotificationReferendumApproved(preferredLanguages: locale?.rLanguages)
case .rejected:
return R.string.localizable.pushNotificationReferendumRejected(preferredLanguages: locale?.rLanguages)
case .cancelled:
return R.string.localizable.pushNotificationReferendumCancelled(preferredLanguages: locale?.rLanguages)
case .timedOut:
return R.string.localizable.pushNotificationReferendumTimedOut(preferredLanguages: locale?.rLanguages)
case .killed:
return R.string.localizable.pushNotificationReferendumKilled(preferredLanguages: locale?.rLanguages)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Foundation

extension PushNotification.TransferType {
func title(locale: Locale, walletName: String?) -> String {
let walletString = walletName.flatMap { "[\($0)]" } ?? ""
let title: String
switch self {
case .income:
title = R.string.localizable.pushNotificationReceiveTokensTitle(preferredLanguages: locale.rLanguages)
case .outcome:
title = R.string.localizable.pushNotificationSentTokensTitle(preferredLanguages: locale.rLanguages)
}

return [title, walletString].joined(with: .space)
}

func subtitle(
amount: String,
price: String?,
chainName: String,
address: AccountAddress?,
locale: Locale
) -> String {
let priceString = price.map { "(\($0))" } ?? ""
switch self {
case .income:
return R.string.localizable.pushNotificationReceiveTokensSubtitle(
amount,
priceString,
chainName,
preferredLanguages: locale.rLanguages
)
case .outcome:
if let address = address {
return R.string.localizable.pushNotificationSentTokensSubtitle(
amount,
priceString,
address,
chainName,
preferredLanguages: locale.rLanguages
)
} else {
return R.string.localizable.pushNotificationSentTokensNoAddressSubtitle(
amount,
priceString,
chainName,
preferredLanguages: locale.rLanguages
)
}
}
}

func address(from payload: NotificationTransferPayload) -> AccountAddress? {
switch self {
case .income:
return nil
case .outcome:
return payload.recipient
}
}
}

0 comments on commit 17dcd4a

Please sign in to comment.