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/startup/module as startup_module
|
||||
import app/modules/onboarding/module as onboarding_module
|
||||
import app/modules/main/module as main_module
|
||||
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/core/[main]
|
||||
|
||||
|
@ -105,6 +106,7 @@ type
|
|||
|
||||
# Modules
|
||||
startupModule: startup_module.AccessInterface
|
||||
onboardingModule: onboarding_module.AccessInterface
|
||||
mainModule: main_module.AccessInterface
|
||||
|
||||
#################################################
|
||||
|
@ -116,6 +118,7 @@ proc applyNecessaryActionsAfterLoggingIn(self: AppController)
|
|||
|
||||
# Startup Module Delegate Interface
|
||||
proc startupDidLoad*(self: AppController)
|
||||
proc onboardingDidLoad*(self: AppController)
|
||||
proc userLoggedIn*(self: AppController): string
|
||||
proc appReady*(self: AppController)
|
||||
proc logout*(self: AppController)
|
||||
|
@ -248,6 +251,11 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||
result.keycardService,
|
||||
result.devicesService
|
||||
)
|
||||
if singletonInstance.featureFlags().getOnboardingV2Enabled():
|
||||
result.onboardingModule = onboarding_module.newModule[AppController](
|
||||
result,
|
||||
statusFoundation.events,
|
||||
)
|
||||
result.mainModule = main_module.newModule[AppController](
|
||||
result,
|
||||
statusFoundation.events,
|
||||
|
@ -304,6 +312,9 @@ proc delete*(self: AppController) =
|
|||
if not self.startupModule.isNil:
|
||||
self.startupModule.delete
|
||||
self.startupModule = nil
|
||||
if not self.onboardingModule.isNil:
|
||||
self.onboardingModule.delete
|
||||
self.onboardingModule = nil
|
||||
self.mainModule.delete
|
||||
self.languageService.delete
|
||||
|
||||
|
@ -387,6 +398,7 @@ proc checkForStoringPasswordToKeychain(self: AppController) =
|
|||
self.keychainService.storeData(account.keyUid, self.startupModule.getPin())
|
||||
|
||||
proc startupDidLoad*(self: AppController) =
|
||||
# TODO move these functions to onboardingDidLoad
|
||||
singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant)
|
||||
singletonInstance.engine.setRootContextProperty("localAccountSettings", self.localAccountSettingsVariant)
|
||||
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.
|
||||
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) =
|
||||
self.applyNecessaryActionsAfterLoggingIn()
|
||||
self.startupModule.moveToAppState()
|
||||
|
@ -411,6 +427,8 @@ proc start*(self: AppController) =
|
|||
self.devicesService.init()
|
||||
|
||||
self.startupModule.load()
|
||||
if singletonInstance.featureFlags().getOnboardingV2Enabled():
|
||||
self.onboardingModule.load()
|
||||
|
||||
proc load(self: AppController) =
|
||||
self.settingsService.init()
|
||||
|
@ -484,6 +502,10 @@ proc finishAppLoading*(self: AppController) =
|
|||
self.startupModule.onAppLoaded()
|
||||
self.startupModule = nil
|
||||
|
||||
if not self.onboardingModule.isNil:
|
||||
self.onboardingModule.onAppLoaded()
|
||||
self.onboardingModule = nil
|
||||
|
||||
self.mainModule.checkAndPerformProfileMigrationIfNeeded()
|
||||
|
||||
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_PAYMENT_REQUEST_ENABLED = true
|
||||
const DEFAULT_FLAG_SIMPLE_SEND_ENABLED = false
|
||||
const DEFAULT_FLAG_ONBOARDING_V2_ENABLED = false
|
||||
|
||||
proc boolToEnv*(defaultValue: bool): string =
|
||||
return if defaultValue: "1" else: "0"
|
||||
|
@ -19,6 +20,7 @@ QtObject:
|
|||
sendViaPersonalChatEnabled: bool
|
||||
paymentRequestEnabled: bool
|
||||
simpleSendEnabled: bool
|
||||
onboardingV2Enabled: bool
|
||||
|
||||
proc setup(self: FeatureFlags) =
|
||||
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.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.onboardingV2Enabled = getEnv("FLAG_ONBOARDING_V2_ENABLED", boolToEnv(DEFAULT_FLAG_ONBOARDING_V2_ENABLED)) != "0"
|
||||
|
||||
proc delete*(self: FeatureFlags) =
|
||||
self.QObject.delete()
|
||||
|
@ -71,3 +74,9 @@ QtObject:
|
|||
|
||||
QtProperty[bool] simpleSendEnabled:
|
||||
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