chore(onboarding): add scaffolding for the new onboarding (#16980)
Part of #16832 Adds the basic files needed for the new onboarding, aka onboarding V2. It does not do anything yet, but it's ready to be implemented. It is locked behind a feature flag. To enable it, run the app with `export FLAG_ONBOARDING_V2_ENABLED=1`
This commit is contained in:
parent
8aebb81137
commit
3dd5fa9443
|
@ -37,9 +37,10 @@ import app_service/service/metrics/service as metrics_service
|
||||||
|
|
||||||
import app/modules/shared_modules/keycard_popup/module as keycard_shared_module
|
import app/modules/shared_modules/keycard_popup/module as keycard_shared_module
|
||||||
import app/modules/startup/module as startup_module
|
import app/modules/startup/module as startup_module
|
||||||
|
import app/modules/onboarding/module as onboarding_module
|
||||||
import app/modules/main/module as main_module
|
import app/modules/main/module as main_module
|
||||||
import app/core/notifications/notifications_manager
|
import app/core/notifications/notifications_manager
|
||||||
import app/global/global_singleton
|
import app/global/[global_singleton, feature_flags]
|
||||||
import app/global/app_signals
|
import app/global/app_signals
|
||||||
import app/core/[main]
|
import app/core/[main]
|
||||||
|
|
||||||
|
@ -105,6 +106,7 @@ type
|
||||||
|
|
||||||
# Modules
|
# Modules
|
||||||
startupModule: startup_module.AccessInterface
|
startupModule: startup_module.AccessInterface
|
||||||
|
onboardingModule: onboarding_module.AccessInterface
|
||||||
mainModule: main_module.AccessInterface
|
mainModule: main_module.AccessInterface
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
|
@ -116,6 +118,7 @@ proc applyNecessaryActionsAfterLoggingIn(self: AppController)
|
||||||
|
|
||||||
# Startup Module Delegate Interface
|
# Startup Module Delegate Interface
|
||||||
proc startupDidLoad*(self: AppController)
|
proc startupDidLoad*(self: AppController)
|
||||||
|
proc onboardingDidLoad*(self: AppController)
|
||||||
proc userLoggedIn*(self: AppController): string
|
proc userLoggedIn*(self: AppController): string
|
||||||
proc appReady*(self: AppController)
|
proc appReady*(self: AppController)
|
||||||
proc logout*(self: AppController)
|
proc logout*(self: AppController)
|
||||||
|
@ -248,6 +251,11 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||||
result.keycardService,
|
result.keycardService,
|
||||||
result.devicesService
|
result.devicesService
|
||||||
)
|
)
|
||||||
|
if singletonInstance.featureFlags().getOnboardingV2Enabled():
|
||||||
|
result.onboardingModule = onboarding_module.newModule[AppController](
|
||||||
|
result,
|
||||||
|
statusFoundation.events,
|
||||||
|
)
|
||||||
result.mainModule = main_module.newModule[AppController](
|
result.mainModule = main_module.newModule[AppController](
|
||||||
result,
|
result,
|
||||||
statusFoundation.events,
|
statusFoundation.events,
|
||||||
|
@ -304,6 +312,9 @@ proc delete*(self: AppController) =
|
||||||
if not self.startupModule.isNil:
|
if not self.startupModule.isNil:
|
||||||
self.startupModule.delete
|
self.startupModule.delete
|
||||||
self.startupModule = nil
|
self.startupModule = nil
|
||||||
|
if not self.onboardingModule.isNil:
|
||||||
|
self.onboardingModule.delete
|
||||||
|
self.onboardingModule = nil
|
||||||
self.mainModule.delete
|
self.mainModule.delete
|
||||||
self.languageService.delete
|
self.languageService.delete
|
||||||
|
|
||||||
|
@ -387,6 +398,7 @@ proc checkForStoringPasswordToKeychain(self: AppController) =
|
||||||
self.keychainService.storeData(account.keyUid, self.startupModule.getPin())
|
self.keychainService.storeData(account.keyUid, self.startupModule.getPin())
|
||||||
|
|
||||||
proc startupDidLoad*(self: AppController) =
|
proc startupDidLoad*(self: AppController) =
|
||||||
|
# TODO move these functions to onboardingDidLoad
|
||||||
singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant)
|
singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant)
|
||||||
singletonInstance.engine.setRootContextProperty("localAccountSettings", self.localAccountSettingsVariant)
|
singletonInstance.engine.setRootContextProperty("localAccountSettings", self.localAccountSettingsVariant)
|
||||||
singletonInstance.engine.setRootContextProperty("globalUtils", self.globalUtilsVariant)
|
singletonInstance.engine.setRootContextProperty("globalUtils", self.globalUtilsVariant)
|
||||||
|
@ -398,6 +410,10 @@ proc startupDidLoad*(self: AppController) =
|
||||||
# We need this to set app width/height appropriatelly on the app start.
|
# We need this to set app width/height appropriatelly on the app start.
|
||||||
self.startupModule.startUpUIRaised()
|
self.startupModule.startUpUIRaised()
|
||||||
|
|
||||||
|
proc onboardingDidLoad*(self: AppController) =
|
||||||
|
debug "NEW ONBOARDING LOADED"
|
||||||
|
# TODO when removing the old startup module, we should move the functions above here
|
||||||
|
|
||||||
proc mainDidLoad*(self: AppController) =
|
proc mainDidLoad*(self: AppController) =
|
||||||
self.applyNecessaryActionsAfterLoggingIn()
|
self.applyNecessaryActionsAfterLoggingIn()
|
||||||
self.startupModule.moveToAppState()
|
self.startupModule.moveToAppState()
|
||||||
|
@ -411,6 +427,8 @@ proc start*(self: AppController) =
|
||||||
self.devicesService.init()
|
self.devicesService.init()
|
||||||
|
|
||||||
self.startupModule.load()
|
self.startupModule.load()
|
||||||
|
if singletonInstance.featureFlags().getOnboardingV2Enabled():
|
||||||
|
self.onboardingModule.load()
|
||||||
|
|
||||||
proc load(self: AppController) =
|
proc load(self: AppController) =
|
||||||
self.settingsService.init()
|
self.settingsService.init()
|
||||||
|
@ -484,6 +502,10 @@ proc finishAppLoading*(self: AppController) =
|
||||||
self.startupModule.onAppLoaded()
|
self.startupModule.onAppLoaded()
|
||||||
self.startupModule = nil
|
self.startupModule = nil
|
||||||
|
|
||||||
|
if not self.onboardingModule.isNil:
|
||||||
|
self.onboardingModule.onAppLoaded()
|
||||||
|
self.onboardingModule = nil
|
||||||
|
|
||||||
self.mainModule.checkAndPerformProfileMigrationIfNeeded()
|
self.mainModule.checkAndPerformProfileMigrationIfNeeded()
|
||||||
|
|
||||||
proc logout*(self: AppController) =
|
proc logout*(self: AppController) =
|
||||||
|
|
|
@ -7,6 +7,7 @@ const DEFAULT_FLAG_CONNECTOR_ENABLED* = true
|
||||||
const DEFAULT_FLAG_SEND_VIA_PERSONAL_CHAT_ENABLED = true
|
const DEFAULT_FLAG_SEND_VIA_PERSONAL_CHAT_ENABLED = true
|
||||||
const DEFAULT_FLAG_PAYMENT_REQUEST_ENABLED = true
|
const DEFAULT_FLAG_PAYMENT_REQUEST_ENABLED = true
|
||||||
const DEFAULT_FLAG_SIMPLE_SEND_ENABLED = false
|
const DEFAULT_FLAG_SIMPLE_SEND_ENABLED = false
|
||||||
|
const DEFAULT_FLAG_ONBOARDING_V2_ENABLED = false
|
||||||
|
|
||||||
proc boolToEnv*(defaultValue: bool): string =
|
proc boolToEnv*(defaultValue: bool): string =
|
||||||
return if defaultValue: "1" else: "0"
|
return if defaultValue: "1" else: "0"
|
||||||
|
@ -19,6 +20,7 @@ QtObject:
|
||||||
sendViaPersonalChatEnabled: bool
|
sendViaPersonalChatEnabled: bool
|
||||||
paymentRequestEnabled: bool
|
paymentRequestEnabled: bool
|
||||||
simpleSendEnabled: bool
|
simpleSendEnabled: bool
|
||||||
|
onboardingV2Enabled: bool
|
||||||
|
|
||||||
proc setup(self: FeatureFlags) =
|
proc setup(self: FeatureFlags) =
|
||||||
self.QObject.setup()
|
self.QObject.setup()
|
||||||
|
@ -28,6 +30,7 @@ QtObject:
|
||||||
self.sendViaPersonalChatEnabled = getEnv("FLAG_SEND_VIA_PERSONAL_CHAT_ENABLED", boolToEnv(DEFAULT_FLAG_SEND_VIA_PERSONAL_CHAT_ENABLED)) != "0"
|
self.sendViaPersonalChatEnabled = getEnv("FLAG_SEND_VIA_PERSONAL_CHAT_ENABLED", boolToEnv(DEFAULT_FLAG_SEND_VIA_PERSONAL_CHAT_ENABLED)) != "0"
|
||||||
self.paymentRequestEnabled = getEnv("FLAG_PAYMENT_REQUEST_ENABLED", boolToEnv(DEFAULT_FLAG_PAYMENT_REQUEST_ENABLED)) != "0"
|
self.paymentRequestEnabled = getEnv("FLAG_PAYMENT_REQUEST_ENABLED", boolToEnv(DEFAULT_FLAG_PAYMENT_REQUEST_ENABLED)) != "0"
|
||||||
self.simpleSendEnabled = getEnv("FLAG_SIMPLE_SEND_ENABLED", boolToEnv(DEFAULT_FLAG_SIMPLE_SEND_ENABLED)) != "0"
|
self.simpleSendEnabled = getEnv("FLAG_SIMPLE_SEND_ENABLED", boolToEnv(DEFAULT_FLAG_SIMPLE_SEND_ENABLED)) != "0"
|
||||||
|
self.onboardingV2Enabled = getEnv("FLAG_ONBOARDING_V2_ENABLED", boolToEnv(DEFAULT_FLAG_ONBOARDING_V2_ENABLED)) != "0"
|
||||||
|
|
||||||
proc delete*(self: FeatureFlags) =
|
proc delete*(self: FeatureFlags) =
|
||||||
self.QObject.delete()
|
self.QObject.delete()
|
||||||
|
@ -71,3 +74,9 @@ QtObject:
|
||||||
|
|
||||||
QtProperty[bool] simpleSendEnabled:
|
QtProperty[bool] simpleSendEnabled:
|
||||||
read = getSimpleSendEnabled
|
read = getSimpleSendEnabled
|
||||||
|
|
||||||
|
proc getOnboardingV2Enabled*(self: FeatureFlags): bool {.slot.} =
|
||||||
|
return self.onboardingV2Enabled
|
||||||
|
|
||||||
|
QtProperty[bool] onboardingV2Enabled:
|
||||||
|
read = getOnboardingV2Enabled
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import chronicles
|
||||||
|
import io_interface
|
||||||
|
|
||||||
|
import app/core/eventemitter
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "onboarding-controller"
|
||||||
|
|
||||||
|
type
|
||||||
|
Controller* = ref object of RootObj
|
||||||
|
delegate: io_interface.AccessInterface
|
||||||
|
events: EventEmitter
|
||||||
|
|
||||||
|
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter):
|
||||||
|
Controller =
|
||||||
|
result = Controller()
|
||||||
|
result.delegate = delegate
|
||||||
|
result.events = events
|
||||||
|
|
||||||
|
proc delete*(self: Controller) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc init*(self: Controller) =
|
||||||
|
discard
|
|
@ -0,0 +1,16 @@
|
||||||
|
type
|
||||||
|
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||||
|
|
||||||
|
method delete*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onAppLoaded*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method load*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
# This way (using concepts) is used only for the modules managed by AppController
|
||||||
|
type
|
||||||
|
DelegateInterface* = concept c
|
||||||
|
c.onboardingDidLoad()
|
|
@ -0,0 +1,49 @@
|
||||||
|
import NimQml, chronicles, json
|
||||||
|
|
||||||
|
import io_interface
|
||||||
|
import view, controller
|
||||||
|
|
||||||
|
import app/global/global_singleton
|
||||||
|
import app/core/eventemitter
|
||||||
|
|
||||||
|
export io_interface
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "onboarding-module"
|
||||||
|
|
||||||
|
type
|
||||||
|
Module*[T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface
|
||||||
|
delegate: T
|
||||||
|
view: View
|
||||||
|
viewVariant: QVariant
|
||||||
|
controller: Controller
|
||||||
|
|
||||||
|
proc newModule*[T](delegate: T, events: EventEmitter): Module[T] =
|
||||||
|
result = Module[T]()
|
||||||
|
result.delegate = delegate
|
||||||
|
result.view = view.newView(result)
|
||||||
|
result.viewVariant = newQVariant(result.view)
|
||||||
|
result.controller = controller.newController(result, events)
|
||||||
|
|
||||||
|
{.push warning[Deprecated]: off.}
|
||||||
|
|
||||||
|
method delete*[T](self: Module[T]) =
|
||||||
|
self.view.delete
|
||||||
|
self.viewVariant.delete
|
||||||
|
self.controller.delete
|
||||||
|
|
||||||
|
method onAppLoaded*[T](self: Module[T]) =
|
||||||
|
singletonInstance.engine.setRootContextProperty("onboardingModule", newQVariant())
|
||||||
|
self.view.delete
|
||||||
|
self.view = nil
|
||||||
|
self.viewVariant.delete
|
||||||
|
self.viewVariant = nil
|
||||||
|
self.controller.delete
|
||||||
|
self.controller = nil
|
||||||
|
|
||||||
|
method load*[T](self: Module[T]) =
|
||||||
|
singletonInstance.engine.setRootContextProperty("onboardingModule", self.viewVariant)
|
||||||
|
self.controller.init()
|
||||||
|
self.delegate.onboardingDidLoad()
|
||||||
|
|
||||||
|
{.pop.}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import NimQml, json
|
||||||
|
import io_interface
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type
|
||||||
|
View* = ref object of QObject
|
||||||
|
delegate: io_interface.AccessInterface
|
||||||
|
|
||||||
|
proc delete*(self: View) =
|
||||||
|
self.QObject.delete
|
||||||
|
|
||||||
|
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||||
|
new(result, delete)
|
||||||
|
result.QObject.setup
|
||||||
|
result.delegate = delegate
|
Loading…
Reference in New Issue