From 137d14928e4b873b9f4e6da29dea775b41afc6b2 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Tue, 29 Oct 2024 18:51:01 +0530 Subject: [PATCH 01/31] Attempts to load image in iOS --- bisqapps/gradle/libs.versions.toml | 2 +- bisqapps/iosClient/Podfile.lock | 2 +- bisqapps/iosClient/Pods/Manifest.lock | 2 +- .../Pods/Pods.xcodeproj/project.pbxproj | 202 +++++++++--------- .../Pods-iosClient.debug.xcconfig | 1 - .../Pods-iosClient.release.xcconfig | 1 - bisqapps/shared/presentation/build.gradle.kts | 28 ++- .../drawable/logo_with_slogan.svg | 9 + .../bisq/mobile/presentation/ui/App.kt | 39 ++-- .../presentation/ui/screens/SplashScreen.kt | 90 ++++++++ .../mobile/presentation/ui/theme/Color.kt | 33 +++ .../presentation/ui/theme/Typography.kt | 12 ++ 12 files changed, 292 insertions(+), 129 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt diff --git a/bisqapps/gradle/libs.versions.toml b/bisqapps/gradle/libs.versions.toml index 295d58d8..20bad801 100644 --- a/bisqapps/gradle/libs.versions.toml +++ b/bisqapps/gradle/libs.versions.toml @@ -2,7 +2,7 @@ agp = "8.5.0" android-compileSdk = "34" android-targetSdk = "34" -android-minSdk = "24" +android-minSdk = "28" android-node-minSdk = "31" androidx-activityCompose = "1.9.2" androidx-appcompat = "1.7.0" diff --git a/bisqapps/iosClient/Podfile.lock b/bisqapps/iosClient/Podfile.lock index 295e6bb7..1a06817f 100644 --- a/bisqapps/iosClient/Podfile.lock +++ b/bisqapps/iosClient/Podfile.lock @@ -18,4 +18,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e4e5bb187d8247572973af90a35b57b84c96b4c6 -COCOAPODS: 1.16.2 +COCOAPODS: 1.15.2 diff --git a/bisqapps/iosClient/Pods/Manifest.lock b/bisqapps/iosClient/Pods/Manifest.lock index 295e6bb7..1a06817f 100644 --- a/bisqapps/iosClient/Pods/Manifest.lock +++ b/bisqapps/iosClient/Pods/Manifest.lock @@ -18,4 +18,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e4e5bb187d8247572973af90a35b57b84c96b4c6 -COCOAPODS: 1.16.2 +COCOAPODS: 1.15.2 diff --git a/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj b/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj index 69267914..f0fd5c11 100644 --- a/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj +++ b/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj @@ -32,25 +32,25 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 348FFC44A5E9B7B78B5AFA2AFED5280D /* Pods-iosClient-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BE8A23FBC0272A84B2B6DF475B94078C /* Pods-iosClient-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 47FAAB4F7EFABDB8C6D42B0132784DF1 /* Pods-iosClient-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E481B77DFE58C61A03CF060B546D43 /* Pods-iosClient-dummy.m */; }; - 9F54DC905AC77CABA77E9F04008E9B6F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 384DDA2CB25005BD6479B5987C619DD4 /* Foundation.framework */; }; + 6D8AEE933A29DC7B08810C345CFA5E24 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + CAC030B21B2C869E7ACF12303AAC81C8 /* Pods-iosClient-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E481B77DFE58C61A03CF060B546D43 /* Pods-iosClient-dummy.m */; }; + F69108046F55BD4137DDB333E58FB806 /* Pods-iosClient-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BE8A23FBC0272A84B2B6DF475B94078C /* Pods-iosClient-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 43926A465BA48F490AAD4266561191E9 /* PBXContainerItemProxy */ = { + 6270F50CCD4DE87ED97016FF300F6833 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 9FA10608F377AE5B47F00969C58A08B0; - remoteInfo = domain; + remoteGlobalIDString = CA23A621E427291AD7AAC241FE14977E; + remoteInfo = presentation; }; - D94579C113BF9D6877F572CEBE34C518 /* PBXContainerItemProxy */ = { + ECE0965C37EE068DC96145D99562455D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = CA23A621E427291AD7AAC241FE14977E; - remoteInfo = presentation; + remoteGlobalIDString = 9FA10608F377AE5B47F00969C58A08B0; + remoteInfo = domain; }; /* End PBXContainerItemProxy section */ @@ -59,10 +59,10 @@ 08F36E9886CC49F84B0FAF507C3E9B5B /* Pods-iosClient-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosClient-acknowledgements.plist"; sourceTree = ""; }; 12A9F0027D088186CD39E0238C94B9C8 /* Pods-iosClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosClient.release.xcconfig"; sourceTree = ""; }; 204E5861AA89F6485AE0E7BE7CC61EB9 /* presentation.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = presentation.release.xcconfig; sourceTree = ""; }; - 384DDA2CB25005BD6479B5987C619DD4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 49F48C70711D582068D8EF03B5D062B2 /* Pods-iosClient */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iosClient"; path = Pods_iosClient.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4AAF1B0BB5C923912BF8947076BB504A /* presentation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = presentation.framework; path = build/cocoapods/framework/presentation.framework; sourceTree = ""; }; 703090F2823E5D42D1ED04CAF0E55193 /* Pods-iosClient.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iosClient.modulemap"; sourceTree = ""; }; + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 74ED85F89A4112470D68D97319C810B5 /* domain.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = domain.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 804065BB4F007C057F539031BA89C4D2 /* domain.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = domain.debug.xcconfig; sourceTree = ""; }; 8EA548F0CBB66C825F5F196469AE443C /* presentation.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = presentation.debug.xcconfig; sourceTree = ""; }; @@ -82,11 +82,11 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - EBBD9B769AA45797F4E13290D3F4D389 /* Frameworks */ = { + C42E73C43E7636D285E3EFB564AED2A2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9F54DC905AC77CABA77E9F04008E9B6F /* Foundation.framework in Frameworks */, + 6D8AEE933A29DC7B08810C345CFA5E24 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -141,6 +141,14 @@ path = ../../shared/domain; sourceTree = ""; }; + 578452D2E740E91742655AC8F1636D1F /* iOS */ = { + isa = PBXGroup; + children = ( + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; 6B7DEDEE95A0508984457A702CE60837 /* Targets Support Files */ = { isa = PBXGroup; children = ( @@ -219,19 +227,11 @@ D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { isa = PBXGroup; children = ( - E4801F62A6B08CD9B5410329F1A18FDE /* iOS */, + 578452D2E740E91742655AC8F1636D1F /* iOS */, ); name = Frameworks; sourceTree = ""; }; - E4801F62A6B08CD9B5410329F1A18FDE /* iOS */ = { - isa = PBXGroup; - children = ( - 384DDA2CB25005BD6479B5987C619DD4 /* Foundation.framework */, - ); - name = iOS; - sourceTree = ""; - }; E9FF437E9B7237DA2D4C60336C9890D7 /* Pod */ = { isa = PBXGroup; children = ( @@ -243,11 +243,11 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 90BC81E26DDEAC698173DBBDF44F548F /* Headers */ = { + BA415ECC9F54D30119E5CC9DD75101AE /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 348FFC44A5E9B7B78B5AFA2AFED5280D /* Pods-iosClient-umbrella.h in Headers */, + F69108046F55BD4137DDB333E58FB806 /* Pods-iosClient-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -256,18 +256,18 @@ /* Begin PBXNativeTarget section */ F3C92A200A7569173DED928345F8DF17 /* Pods-iosClient */ = { isa = PBXNativeTarget; - buildConfigurationList = BD19120D9E7ED18653B7259546989F15 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */; + buildConfigurationList = 353001358113C9F843A3BBE263DA5845 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */; buildPhases = ( - 90BC81E26DDEAC698173DBBDF44F548F /* Headers */, - A6370334C83C2D6AF3EA6C4C370A5C80 /* Sources */, - EBBD9B769AA45797F4E13290D3F4D389 /* Frameworks */, - 9F2EFCAA86FE94012544D8E099DFA032 /* Resources */, + BA415ECC9F54D30119E5CC9DD75101AE /* Headers */, + 50D8119830E647007B7C6B621F14082F /* Sources */, + C42E73C43E7636D285E3EFB564AED2A2 /* Frameworks */, + 962FF8154C877D9E2348823600E7D577 /* Resources */, ); buildRules = ( ); dependencies = ( - 7EA97463B99B732B6B24774A9B942A85 /* PBXTargetDependency */, - 631D2882C1581DA7DF2E1CC18B1B3809 /* PBXTargetDependency */, + 301E0E32512A3E0913F6AEC1A7C27833 /* PBXTargetDependency */, + BC1D990945D84666EE9129354C69E0FA /* PBXTargetDependency */, ); name = "Pods-iosClient"; productName = Pods_iosClient; @@ -280,8 +280,8 @@ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1600; - LastUpgradeCheck = 1600; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 14.0"; @@ -292,8 +292,6 @@ en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; - minimizedProjectReferenceProxies = 0; - preferredProjectObjectVersion = 77; productRefGroup = A926F4DF68FD1A33909AAB7F17266C96 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -306,7 +304,7 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 9F2EFCAA86FE94012544D8E099DFA032 /* Resources */ = { + 962FF8154C877D9E2348823600E7D577 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -373,69 +371,47 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - A6370334C83C2D6AF3EA6C4C370A5C80 /* Sources */ = { + 50D8119830E647007B7C6B621F14082F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 47FAAB4F7EFABDB8C6D42B0132784DF1 /* Pods-iosClient-dummy.m in Sources */, + CAC030B21B2C869E7ACF12303AAC81C8 /* Pods-iosClient-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 631D2882C1581DA7DF2E1CC18B1B3809 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = presentation; - target = CA23A621E427291AD7AAC241FE14977E /* presentation */; - targetProxy = D94579C113BF9D6877F572CEBE34C518 /* PBXContainerItemProxy */; - }; - 7EA97463B99B732B6B24774A9B942A85 /* PBXTargetDependency */ = { + 301E0E32512A3E0913F6AEC1A7C27833 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = domain; target = 9FA10608F377AE5B47F00969C58A08B0 /* domain */; - targetProxy = 43926A465BA48F490AAD4266561191E9 /* PBXContainerItemProxy */; + targetProxy = ECE0965C37EE068DC96145D99562455D /* PBXContainerItemProxy */; + }; + BC1D990945D84666EE9129354C69E0FA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = presentation; + target = CA23A621E427291AD7AAC241FE14977E /* presentation */; + targetProxy = 6270F50CCD4DE87ED97016FF300F6833 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 018F2F2185808E1CFC64820D5D133A46 /* Release */ = { + 2E45E8C4BD4AFB54267F590D5DE5DC7E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 12A9F0027D088186CD39E0238C94B9C8 /* Pods-iosClient.release.xcconfig */; + baseConfigurationReference = DA1AD272BC5CBE1D4ED4240B2689D453 /* domain.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - INFOPLIST_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", - "@loader_path/Frameworks", ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; - SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; }; name = Release; }; @@ -501,14 +477,13 @@ }; name = Release; }; - 437EA4C44DE0B4C7DCDF7777DED031FA /* Debug */ = { + 5073BD3B8BAE827A42C6C0745CF30855 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8EA548F0CBB66C825F5F196469AE443C /* presentation.debug.xcconfig */; + baseConfigurationReference = 204E5861AA89F6485AE0E7BE7CC61EB9 /* presentation.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; - ENABLE_USER_SCRIPT_SANDBOXING = NO; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -516,17 +491,17 @@ ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; - name = Debug; + name = Release; }; - 48F2FDB6889B575B7DB16DE30260C86D /* Release */ = { + 77458C92CF4EA7DEDC04735E8E580C2A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 204E5861AA89F6485AE0E7BE7CC61EB9 /* presentation.release.xcconfig */; + baseConfigurationReference = 804065BB4F007C057F539031BA89C4D2 /* domain.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; - ENABLE_USER_SCRIPT_SANDBOXING = NO; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -534,11 +509,10 @@ ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = Release; + name = Debug; }; - CB606ED3E79A498A37998C1B0EED7638 /* Debug */ = { + 86AF170A2B3395569AB4C66092089CF0 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A733908725930A882438524B1F97DAE3 /* Pods-iosClient.debug.xcconfig */; buildSettings = { @@ -552,8 +526,6 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - ENABLE_USER_SCRIPT_SANDBOXING = NO; INFOPLIST_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; @@ -577,14 +549,13 @@ }; name = Debug; }; - D347EF77A9147218FFD617F7E00D9870 /* Release */ = { + 9084D9814A27814E5AA332C6B109236D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DA1AD272BC5CBE1D4ED4240B2689D453 /* domain.release.xcconfig */; + baseConfigurationReference = 8EA548F0CBB66C825F5F196469AE443C /* presentation.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; - ENABLE_USER_SCRIPT_SANDBOXING = NO; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -592,9 +563,8 @@ ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = Release; + name = Debug; }; F4FF6A0D1970CA9705974E3CB2134802 /* Debug */ = { isa = XCBuildConfiguration; @@ -662,59 +632,79 @@ }; name = Debug; }; - F6743C549671A6AE48C5AF30AA7C423A /* Debug */ = { + FB7B18B0BBBBE282315F2CBBBE2B90B5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 804065BB4F007C057F539031BA89C4D2 /* domain.debug.xcconfig */; + baseConfigurationReference = 12A9F0027D088186CD39E0238C94B9C8 /* Pods-iosClient.release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; - ENABLE_USER_SCRIPT_SANDBOXING = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + "@loader_path/Frameworks", ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + 353001358113C9F843A3BBE263DA5845 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */ = { isa = XCConfigurationList; buildConfigurations = ( - F4FF6A0D1970CA9705974E3CB2134802 /* Debug */, - 30E0B9EFD9A5C45D0D351231E81B30B3 /* Release */, + 86AF170A2B3395569AB4C66092089CF0 /* Debug */, + FB7B18B0BBBBE282315F2CBBBE2B90B5 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 84A7558F1F961C4A23CF638108708641 /* Build configuration list for PBXAggregateTarget "presentation" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 437EA4C44DE0B4C7DCDF7777DED031FA /* Debug */, - 48F2FDB6889B575B7DB16DE30260C86D /* Release */, + F4FF6A0D1970CA9705974E3CB2134802 /* Debug */, + 30E0B9EFD9A5C45D0D351231E81B30B3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - B978635EC7F36DF902EF0C770E5CBB10 /* Build configuration list for PBXAggregateTarget "domain" */ = { + 84A7558F1F961C4A23CF638108708641 /* Build configuration list for PBXAggregateTarget "presentation" */ = { isa = XCConfigurationList; buildConfigurations = ( - F6743C549671A6AE48C5AF30AA7C423A /* Debug */, - D347EF77A9147218FFD617F7E00D9870 /* Release */, + 9084D9814A27814E5AA332C6B109236D /* Debug */, + 5073BD3B8BAE827A42C6C0745CF30855 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BD19120D9E7ED18653B7259546989F15 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */ = { + B978635EC7F36DF902EF0C770E5CBB10 /* Build configuration list for PBXAggregateTarget "domain" */ = { isa = XCConfigurationList; buildConfigurations = ( - CB606ED3E79A498A37998C1B0EED7638 /* Debug */, - 018F2F2185808E1CFC64820D5D133A46 /* Release */, + 77458C92CF4EA7DEDC04735E8E580C2A /* Debug */, + 2E45E8C4BD4AFB54267F590D5DE5DC7E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig index f7d607d8..b5042e50 100644 --- a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig +++ b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig @@ -4,7 +4,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/domain/build/co GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -l"c++" -framework "domain" -framework "presentation" -OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/domain" "-F${PODS_CONFIGURATION_BUILD_DIR}/presentation" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig index f7d607d8..b5042e50 100644 --- a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig +++ b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig @@ -4,7 +4,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/domain/build/co GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -l"c++" -framework "domain" -framework "presentation" -OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/domain" "-F${PODS_CONFIGURATION_BUILD_DIR}/presentation" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/bisqapps/shared/presentation/build.gradle.kts b/bisqapps/shared/presentation/build.gradle.kts index f744cba1..85e3fda4 100644 --- a/bisqapps/shared/presentation/build.gradle.kts +++ b/bisqapps/shared/presentation/build.gradle.kts @@ -79,7 +79,7 @@ kotlin { implementation(compose.runtime) implementation(compose.foundation) - implementation(compose.material) + implementation(compose.material3) implementation(compose.ui) implementation(compose.components.resources) implementation(compose.components.uiToolingPreview) @@ -90,6 +90,13 @@ kotlin { implementation(libs.koin.core) implementation(libs.koin.compose) + implementation("io.coil-kt.coil3:coil-compose:3.0.0-rc02") + implementation("io.coil-kt.coil3:coil-svg:3.0.0-rc02") + + //https://github.com/Kamel-Media/Kamel + //implementation("media.kamel:kamel-image:1.0.0") + //implementation("media.kamel:kamel-decoder-svg-std:1.0.0") + //implementation("io.ktor:ktor-server-netty:3.0.0") } val commonTest by getting { dependencies { @@ -114,3 +121,22 @@ android { targetCompatibility = JavaVersion.VERSION_1_8 } } + dependencies { + //implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.0-rc02") + //implementation("io.ktor:ktor-client-android:3.0.0") + } +// dependencies { +// implementation("media.kamel:kamel-fetcher-resources-android:1.0.0") +// } + + +//appleMain { +// dependencies { +// implementation("io.ktor:ktor-client-darwin:3.0.0") +// } +//} +//jvmMain { +// dependencies { +// implementation("io.ktor:ktor-client-java:3.0.0>") +// } +//} diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg new file mode 100644 index 00000000..239aa1bb --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index 40e2505f..e9f1b4aa 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -4,9 +4,9 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.Button -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -17,6 +17,7 @@ import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.compose_multiplatform import kotlinx.coroutines.flow.StateFlow import org.koin.compose.koinInject +import network.bisq.mobile.presentation.ui.screens.SplashScreen interface AppPresenter { // Observables for state @@ -35,19 +36,23 @@ interface AppPresenter { fun App() { val presenter: AppPresenter = koinInject() MaterialTheme { - // Collecting state from presenter - val showContent by presenter.isContentVisible.collectAsState() - val greeting by presenter.greetingText.collectAsState() - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Button(onClick = { presenter.toggleContentVisibility() }) { - Text("Click me!") - } - AnimatedVisibility(showContent) { - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Image(painterResource(Res.drawable.compose_multiplatform), null) - Text("Compose: $greeting") - } - } - } + SplashScreen() } + + // Collecting state from presenter +// val showContent by presenter.isContentVisible.collectAsState() +// val greeting by presenter.greetingText.collectAsState() +// Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { +// Button(onClick = { presenter.toggleContentVisibility() }) { +// Text("Click me!") +// } +// AnimatedVisibility(showContent) { +// Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { +// Image(painterResource(Res.drawable.compose_multiplatform), null) +// Text("Compose: $greeting") +// } +// } +// } + + } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt new file mode 100644 index 00000000..83a1b568 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -0,0 +1,90 @@ +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.theme.backgroundColor +import network.bisq.mobile.presentation.ui.theme.grey2 +import network.bisq.mobile.presentation.ui.theme.primaryStandard +import network.bisq.mobile.presentation.ui.theme.secondaryHover +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.ExperimentalResourceApi + +import coil3.compose.AsyncImage + +import bisqapps.shared.presentation.generated.resources.Res +//import bisqapps.shared.presentation.generated.resources.logo_with_slogan +//import io.kamel.image.KamelImage +//import io.kamel.image.asyncPainterResource + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun SplashScreen() { + Column( + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .background(color = backgroundColor) + .padding(top = 48.dp, bottom = 30.dp) + ) { +// 3. Having issues rendering in both iOS and Android using Kamel +// KamelImage( +// { asyncPainterResource("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg") }, contentDescription = "Hi" +// ) +// KamelImage( +// { asyncPainterResource("drawable/logo_with_slogan.svg") }, contentDescription = null +// ) + +// 2. Image not loading in iOS, though some Image placeholder is placed. +// Though it's said that with Coil3.0.0, iOS is supported + AsyncImage( + model = Res.getUri("drawable/logo_with_slogan.svg"), + contentDescription = "Bisq logo with slogan", + modifier = Modifier.height(92.dp).width(300.dp), + ) +// AsyncImage( +// model = Res.getUri("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg"), +// contentDescription = "Bisq logo with slogan", +// modifier = Modifier.height(92.dp).width(300.dp), +// ) +// +// 1. Loading images from resources, doesn't work with SVG. +// Solution is to convert the SVG to VectorDrawable. +// But doing that makes it work only in Android, not with iOS +// Image(painterResource(Res.drawable.logo_with_slogan), null) + LoadingProgress() + } +} + +@Composable +fun LoadingProgress() { + + Column { + + LinearProgressIndicator( + trackColor = grey2, + color = primaryStandard, + gapSize = 0.dp, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 100.dp) + .padding(bottom = 20.dp) + .height(2.dp), + ) + Text( + text = "Connecting to Tor Network...", + color = secondaryHover, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt new file mode 100644 index 00000000..397cd628 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt @@ -0,0 +1,33 @@ +package network.bisq.mobile.presentation.ui.theme + +import androidx.compose.ui.graphics.Color + +//Branding +val backgroundColor = Color(0xFF1C1C1C) +val primaryStandard = Color(0xFF25B135) +val primaryHover = Color(0x56C262) +val primaryDisabled = Color(0x6425B135) +val secondaryStandard = Color(0xFF2F2F2F) +val secondaryHover = Color(0xFF525252) +val secondaryDisabled = Color(0x642F2F2F) +val grey1 = Color(0xFF999999) +val grey2 = Color(0xFF747474) +val White2 = Color(0xFFF8F8F8) +val Black5 = Color(0xFF333333) +val Black3 = Color(0xFF282828) +val Danger1 = Color(0xFFDB0000) + + + + +val primaryColor = Color(0xFF262626) +val primaryTextColor = Color(0xFFF4F4F4) +val secondaryTextColor = Color(0xFF474747) +val progressColor = Color(0xFF707070) +val primaryGreenColor = Color(0xFF25B135) +val paragraphColor = Color(0xFF777777) +val secondaryColor = Color(0xFF2B2B2B) +val indicatorTrackColor = Color(0xFF2F2F2F) +val nextStepColor = Color(0xFF767676) +val smallTextColor = Color(0xFFCBCBCB) +val progressSecondaryColor = Color(0xFF303030) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt new file mode 100644 index 00000000..1d6fcb25 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt @@ -0,0 +1,12 @@ +package network.bisq.mobile.presentation.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.font.FontFamily + +val ibmPlexSansFontFamily = FontFamily( + +) + +val Typography = Typography( + +) \ No newline at end of file From 2accb8f39803fad6748535e8f3120851da1996d1 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Tue, 29 Oct 2024 20:03:14 +0530 Subject: [PATCH 02/31] [Splash] Animation --- .../presentation/ui/screens/SplashScreen.kt | 121 +++++++++++++----- 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 83a1b568..293bf5e6 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -4,8 +4,17 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.ProgressIndicatorDefaults +import androidx.compose.material3.ProgressIndicatorDefaults.drawStopIndicator import androidx.compose.material3.Text +import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign @@ -18,8 +27,13 @@ import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.ExperimentalResourceApi import coil3.compose.AsyncImage +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.LocalPlatformContext +import coil3.request.ImageRequest + //import bisqapps.shared.presentation.generated.resources.logo_with_slogan //import io.kamel.image.KamelImage //import io.kamel.image.asyncPainterResource @@ -27,57 +41,91 @@ import bisqapps.shared.presentation.generated.resources.Res @OptIn(ExperimentalResourceApi::class) @Composable fun SplashScreen() { - Column( - verticalArrangement = Arrangement.SpaceBetween, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxSize() - .background(color = backgroundColor) - .padding(top = 48.dp, bottom = 30.dp) - ) { -// 3. Having issues rendering in both iOS and Android using Kamel -// KamelImage( -// { asyncPainterResource("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg") }, contentDescription = "Hi" -// ) -// KamelImage( -// { asyncPainterResource("drawable/logo_with_slogan.svg") }, contentDescription = null -// ) + Scaffold( + containerColor = backgroundColor, + ) { + Column( + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .background(color = backgroundColor) + .padding(top = 48.dp, bottom = 30.dp) + ) { + // 3. Having issues rendering in both iOS and Android using Kamel (TODO: Yet to understand how ktor integration works with the lib, to properly try) + // KamelImage( + // { asyncPainterResource("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg") }, contentDescription = "Hi" + // ) + // KamelImage( + // { asyncPainterResource("drawable/logo_with_slogan.svg") }, contentDescription = null + // ) -// 2. Image not loading in iOS, though some Image placeholder is placed. -// Though it's said that with Coil3.0.0, iOS is supported - AsyncImage( - model = Res.getUri("drawable/logo_with_slogan.svg"), - contentDescription = "Bisq logo with slogan", - modifier = Modifier.height(92.dp).width(300.dp), - ) -// AsyncImage( -// model = Res.getUri("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg"), -// contentDescription = "Bisq logo with slogan", -// modifier = Modifier.height(92.dp).width(300.dp), -// ) -// -// 1. Loading images from resources, doesn't work with SVG. -// Solution is to convert the SVG to VectorDrawable. -// But doing that makes it work only in Android, not with iOS -// Image(painterResource(Res.drawable.logo_with_slogan), null) - LoadingProgress() + // 2. Image not loading in iOS, though some Image placeholder is placed. + // Though it's said that with Coil3.0.0, iOS is supported + AsyncImage( + model = Res.getUri("drawable/logo_with_slogan.svg"), + contentDescription = "Bisq logo with slogan", + modifier = Modifier.height(92.dp).width(300.dp), + ) + // TODO: Have to try this sample setup using 'viewModel' + // https://github.com/coil-kt/coil/blob/main/samples/compose/src/commonMain/kotlin/sample/compose/App.kt + // AsyncImage( + // model = ImageRequest.Builder(LocalPlatformContext.current) + // .data(screen.image.uri) + // .placeholderMemoryCacheKey(screen.placeholder) + // .extras(screen.image.extras) + // .build(), + // contentDescription = null, + // modifier = Modifier.fillMaxSize(), + // ) + // AsyncImage( + // model = Res.getUri("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg"), + // contentDescription = "Bisq logo with slogan", + // modifier = Modifier.height(92.dp).width(300.dp), + // ) + // + // 1. Loading images from resources, doesn't work with SVG. + // Solution is to convert the SVG to VectorDrawable. + // But doing that makes it work only in Android, not with iOS + // Image(painterResource(Res.drawable.logo_with_slogan), null) + LoadingProgress() + } } } + @Composable fun LoadingProgress() { + var currentProgress by remember { mutableFloatStateOf(0f) } + val scope = rememberCoroutineScope() Column { + LaunchedEffect(true) { + scope.launch { + loadProgress { progress -> + currentProgress = progress + } + } + } LinearProgressIndicator( trackColor = grey2, color = primaryStandard, + progress = { currentProgress }, gapSize = 0.dp, modifier = Modifier .fillMaxWidth() .padding(horizontal = 100.dp) .padding(bottom = 20.dp) .height(2.dp), + drawStopIndicator = { + drawStopIndicator( + drawScope = this, + stopSize = 0.dp, + color = grey2, + strokeCap = ProgressIndicatorDefaults.LinearStrokeCap + ) + } ) Text( text = "Connecting to Tor Network...", @@ -88,3 +136,10 @@ fun LoadingProgress() { } } + +suspend fun loadProgress(updateProgress: (Float) -> Unit) { + for (i in 1..100) { + updateProgress(i.toFloat() / 100) + delay(100) + } +} \ No newline at end of file From c811bdefaeda88ac08f7588ed66e28fd7cd648fe Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 30 Oct 2024 09:16:29 +0530 Subject: [PATCH 03/31] Onboarding page --- .../composeResources/drawable/bisq_easy.svg | 9 + .../composeResources/drawable/fiat_btc.svg | 9 + .../drawable/learn_and_discover.svg | 9 + .../bisq/mobile/presentation/ui/App.kt | 5 +- .../mobile/presentation/ui/model/model.kt | 3 + .../ui/screens/OnBoardingScreen.kt | 256 ++++++++++++++++++ 6 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/learn_and_discover.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg new file mode 100644 index 00000000..76095603 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg new file mode 100644 index 00000000..64451f40 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/learn_and_discover.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/learn_and_discover.svg new file mode 100644 index 00000000..c8ba4bc7 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/learn_and_discover.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index e9f1b4aa..2efb678d 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -17,6 +17,7 @@ import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.compose_multiplatform import kotlinx.coroutines.flow.StateFlow import org.koin.compose.koinInject +import network.bisq.mobile.presentation.ui.screens.OnBoardingScreen import network.bisq.mobile.presentation.ui.screens.SplashScreen interface AppPresenter { @@ -35,8 +36,10 @@ interface AppPresenter { @Preview fun App() { val presenter: AppPresenter = koinInject() + MaterialTheme { - SplashScreen() + //SplashScreen() + OnBoardingScreen() } // Collecting state from presenter diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt new file mode 100644 index 00000000..b92e4d5b --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt @@ -0,0 +1,3 @@ +package network.bisq.mobile.presentation.ui.model + +data class OnBoardingPage(val title: String, val image: String, val desc: String) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt new file mode 100644 index 00000000..50f1a7d8 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -0,0 +1,256 @@ +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PageSize +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import kotlinx.coroutines.launch +import network.bisq.mobile.presentation.ui.model.OnBoardingPage +import network.bisq.mobile.presentation.ui.theme.backgroundColor +import network.bisq.mobile.presentation.ui.theme.grey1 +import network.bisq.mobile.presentation.ui.theme.grey2 +import network.bisq.mobile.presentation.ui.theme.primaryStandard +import network.bisq.mobile.presentation.ui.theme.secondaryColor +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.Font + +val list = listOf( + OnBoardingPage( + title = "Introducing Bisq Easy", + image = "drawable/bisq_easy.svg", + desc = "Getting your first Bitcoin privately has never been easier" + ), + OnBoardingPage( + title = "Learn & Discover", + image = "drawable/learn_and_discover.svg", + desc = "Get a gentle introduction into Bitcoin through our guides and community chat" + ), + OnBoardingPage( + title = "Coming soon", + image = "drawable/fiat_btc.svg", + desc = "Choose how to trade: Bisq MuSig, Lightning, Submarine Swaps,..." + ) +) +private lateinit var pagerState: PagerState + + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun OnBoardingScreen() { + Scaffold( + containerColor = backgroundColor, + ) { innerPadding -> + Column( + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(bottom = 20.dp) + ) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + AsyncImage( + model = Res.getUri("drawable/logo_with_slogan.svg"), + contentDescription = null, + modifier = Modifier.height(62.dp).width(200.dp), + ) + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = "Welcome to Bisq", + fontSize = 32.sp, + color = grey1 + ) + } + + PagerView() + Column { + val coroutineScope = rememberCoroutineScope() + + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = primaryStandard) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + if (pagerState.currentPage == 2) { + // navigate to next page + } else { + coroutineScope.launch { + pagerState.animateScrollToPage( + pagerState.currentPage + 1 + ) + } + } + + }) + .padding(horizontal = 64.dp, vertical = 12.dp), + text = if (pagerState.currentPage == 2) "Create profile" else "Next", + color = Color.White, + ) + + } + } + } +} + +@Composable +fun PagerView() { + + + pagerState = rememberPagerState(pageCount = { list.size }) + + + CompositionLocalProvider(values = arrayOf()) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(64.dp, Alignment.CenterVertically), + ) { + HorizontalPager( + pageSpacing = 56.dp, + contentPadding = PaddingValues(horizontal = 56.dp), + pageSize = PageSize.Fill, + verticalAlignment = Alignment.CenterVertically, + state = pagerState + ) { index -> + list.getOrNull( + index % (list.size) + )?.let { item -> + BannerItem( + image = item.image, + title = item.title, + desc = item.desc, + index = index, + ) + } + } + LineIndicator(pagerState = pagerState) + } + } +} + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun BannerItem( + title: String, + image: String, + desc: String, + index: Int +) { + Box( + modifier = Modifier + .clip(RoundedCornerShape(18.dp)), + contentAlignment = Alignment.Center + ) { + Column( + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxWidth() + .background(color = secondaryColor) + .padding(vertical = 56.dp) + ) { + + AsyncImage( + modifier = Modifier.size(120.dp), + model = Res.getUri(image), + contentDescription = null, + ) + Spacer(modifier = Modifier.height(if (index == 1) 48.dp else 70.dp)) + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = title, + color = Color.White, + fontSize = 22.sp, + ) + Spacer(modifier = Modifier.height(24.dp)) + Text( + text = desc, + color = grey2, + fontSize = 14.sp, + modifier = Modifier.padding(horizontal = 16.dp), + textAlign = TextAlign.Center, + ) + } + } + } +} + +@Composable +fun LineIndicator(pagerState: PagerState) { + Box( + contentAlignment = Alignment.CenterStart + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + repeat(pagerState.pageCount) { + Box( + modifier = Modifier + .size(width = 76.dp, height = 2.dp) + .background( + color = grey2, + ) + ) + } + } + Box( + Modifier + .slidingLineTransition( + pagerState, + 76f * LocalDensity.current.density + ) + .size(width = 76.dp, height = 3.dp) + .background( + color = primaryStandard, + shape = RoundedCornerShape(4.dp), + ) + ) + } +} + +fun Modifier.slidingLineTransition(pagerState: PagerState, distance: Float) = + graphicsLayer { + val scrollPosition = pagerState.currentPage + pagerState.currentPageOffsetFraction + translationX = scrollPosition * distance + } From 0e9cf8d7e70a8214a9c454e652b0ea5900a7c01f Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 30 Oct 2024 11:03:51 +0530 Subject: [PATCH 04/31] Nav module --- bisqapps/shared/presentation/build.gradle.kts | 2 + .../bisq/mobile/presentation/ui/App.kt | 30 +++++++------- .../presentation/ui/navigation/Routes.kt | 9 ++++ .../ui/navigation/graph/RootNavGraph.kt | 41 +++++++++++++++++++ .../presentation/ui/screens/ExchangeScreen.kt | 12 ++++++ .../presentation/ui/screens/HomeScreen.kt | 12 ++++++ .../presentation/ui/screens/MyTrades.kt | 11 +++++ .../ui/screens/OnBoardingScreen.kt | 3 +- .../presentation/ui/screens/SettingsScreen.kt | 12 ++++++ .../presentation/ui/screens/SplashScreen.kt | 13 ++++-- 10 files changed, 126 insertions(+), 19 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt diff --git a/bisqapps/shared/presentation/build.gradle.kts b/bisqapps/shared/presentation/build.gradle.kts index 85e3fda4..6b887e92 100644 --- a/bisqapps/shared/presentation/build.gradle.kts +++ b/bisqapps/shared/presentation/build.gradle.kts @@ -93,6 +93,8 @@ kotlin { implementation("io.coil-kt.coil3:coil-compose:3.0.0-rc02") implementation("io.coil-kt.coil3:coil-svg:3.0.0-rc02") + implementation("org.jetbrains.androidx.navigation:navigation-compose:2.7.0-alpha07") + //implementation("androidx.navigation:navigation-compose:2.8.3") //https://github.com/Kamel-Media/Kamel //implementation("media.kamel:kamel-image:1.0.0") //implementation("media.kamel:kamel-decoder-svg-std:1.0.0") diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index 2efb678d..ee639769 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -1,25 +1,18 @@ package network.bisq.mobile.presentation.ui -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import org.jetbrains.compose.resources.painterResource +import androidx.navigation.compose.rememberNavController import org.jetbrains.compose.ui.tooling.preview.Preview -import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.compose_multiplatform import kotlinx.coroutines.flow.StateFlow import org.koin.compose.koinInject import network.bisq.mobile.presentation.ui.screens.OnBoardingScreen import network.bisq.mobile.presentation.ui.screens.SplashScreen +import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph +import network.bisq.mobile.presentation.ui.navigation.SplashRouteScreen + interface AppPresenter { // Observables for state val isContentVisible: StateFlow @@ -37,10 +30,17 @@ interface AppPresenter { fun App() { val presenter: AppPresenter = koinInject() - MaterialTheme { + val navController = rememberNavController() + RootNavGraph( + rootNavController = navController, + innerPadding = PaddingValues(), + startDestination = SplashRouteScreen.Splash.route + ) + + //MaterialTheme { //SplashScreen() - OnBoardingScreen() - } + //OnBoardingScreen() + //} // Collecting state from presenter // val showContent by presenter.isContentVisible.collectAsState() diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt new file mode 100644 index 00000000..f71c4aff --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt @@ -0,0 +1,9 @@ +package network.bisq.mobile.presentation.ui.navigation + +sealed class SplashRouteScreen(var route: String) { + object Splash : SplashRouteScreen("splash") +} + +sealed class OnBoardingRouteScreen(var route: String) { + object OnBoard : OnBoardingRouteScreen("onboard") +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt new file mode 100644 index 00000000..a390e800 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt @@ -0,0 +1,41 @@ +package network.bisq.mobile.presentation.ui.navigation.graph + +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import network.bisq.mobile.presentation.ui.navigation.OnBoardingRouteScreen +import network.bisq.mobile.presentation.ui.navigation.SplashRouteScreen +import network.bisq.mobile.presentation.ui.screens.OnBoardingScreen +import network.bisq.mobile.presentation.ui.screens.SplashScreen +import network.bisq.mobile.presentation.ui.theme.backgroundColor + +@Composable +fun RootNavGraph( + rootNavController: NavHostController, + innerPadding: PaddingValues, + startDestination: String +) { + NavHost( + modifier = Modifier.background(color = backgroundColor), + navController = rootNavController, + startDestination = startDestination, + ) { + composable(route = SplashRouteScreen.Splash.route) { + SplashScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = OnBoardingRouteScreen.OnBoard.route,enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween(300) + ) + }) { + OnBoardingScreen(rootNavController = rootNavController) + } + } +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt new file mode 100644 index 00000000..e2069193 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt @@ -0,0 +1,12 @@ + +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun ExchangeScreen() { + Text("Exchange - Buy / Sell") +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt new file mode 100644 index 00000000..219303d8 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt @@ -0,0 +1,12 @@ + +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun SettingsScreen() { + Text("Settings") +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt new file mode 100644 index 00000000..1181a718 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt @@ -0,0 +1,11 @@ +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun MyTradesScreen() { + Text("My Trades") +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt index 50f1a7d8..c490d1b4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage @@ -71,7 +72,7 @@ private lateinit var pagerState: PagerState @OptIn(ExperimentalResourceApi::class) @Composable -fun OnBoardingScreen() { +fun OnBoardingScreen(rootNavController: NavController) { Scaffold( containerColor = backgroundColor, ) { innerPadding -> diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt new file mode 100644 index 00000000..55f78fee --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt @@ -0,0 +1,12 @@ + +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun SettingsScreen() { + Text("Home") +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 293bf5e6..903273cb 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.navigation.NavController import network.bisq.mobile.presentation.ui.theme.backgroundColor import network.bisq.mobile.presentation.ui.theme.grey2 import network.bisq.mobile.presentation.ui.theme.primaryStandard @@ -33,6 +34,8 @@ import kotlinx.coroutines.launch import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.LocalPlatformContext import coil3.request.ImageRequest +import network.bisq.mobile.presentation.ui.navigation.OnBoardingRouteScreen +import network.bisq.mobile.presentation.ui.navigation.SplashRouteScreen //import bisqapps.shared.presentation.generated.resources.logo_with_slogan //import io.kamel.image.KamelImage @@ -40,7 +43,8 @@ import coil3.request.ImageRequest @OptIn(ExperimentalResourceApi::class) @Composable -fun SplashScreen() { +fun SplashScreen(rootNavController: NavController, + innerPadding: PaddingValues) { Scaffold( containerColor = backgroundColor, ) { @@ -88,14 +92,14 @@ fun SplashScreen() { // Solution is to convert the SVG to VectorDrawable. // But doing that makes it work only in Android, not with iOS // Image(painterResource(Res.drawable.logo_with_slogan), null) - LoadingProgress() + LoadingProgress(rootNavController) } } } @Composable -fun LoadingProgress() { +fun LoadingProgress(navController: NavController) { var currentProgress by remember { mutableFloatStateOf(0f) } val scope = rememberCoroutineScope() @@ -105,6 +109,9 @@ fun LoadingProgress() { loadProgress { progress -> currentProgress = progress } + navController.navigate(OnBoardingRouteScreen.OnBoard.route) { + popUpTo(SplashRouteScreen.Splash.route) { inclusive = true } + } } } From 491c7814f960931b24d2fa04ff1bfe53ba9e1a45 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 30 Oct 2024 19:21:41 +0530 Subject: [PATCH 05/31] Bottom Tab bar nav - with Placeholder screens --- .../bisq/mobile/presentation/ui/App.kt | 6 +- .../mobile/presentation/ui/model/model.kt | 1 + .../ui/navigation/BottomNavigation.kt | 67 +++++++++++++++++++ .../presentation/ui/navigation/Routes.kt | 20 ++++-- .../ui/navigation/graph/RootNavGraph.kt | 30 +++++++-- .../ui/navigation/graph/TabNavGraph.kt | 37 ++++++++++ .../ui/screens/CreateProfileScreen.kt | 65 ++++++++++++++++++ .../presentation/ui/screens/ExchangeScreen.kt | 26 ++++++- .../presentation/ui/screens/HomeScreen.kt | 26 ++++++- .../presentation/ui/screens/MyTrades.kt | 27 +++++++- .../ui/screens/OnBoardingScreen.kt | 5 +- .../presentation/ui/screens/SettingsScreen.kt | 26 ++++++- .../presentation/ui/screens/SplashScreen.kt | 9 +-- .../ui/screens/TabContainerScreen.kt | 58 ++++++++++++++++ .../presentation/ui/screens/URLScreen.kt | 65 ++++++++++++++++++ 15 files changed, 439 insertions(+), 29 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index ee639769..a3996c13 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -9,9 +9,9 @@ import kotlinx.coroutines.flow.StateFlow import org.koin.compose.koinInject import network.bisq.mobile.presentation.ui.screens.OnBoardingScreen import network.bisq.mobile.presentation.ui.screens.SplashScreen +import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph -import network.bisq.mobile.presentation.ui.navigation.SplashRouteScreen interface AppPresenter { // Observables for state @@ -34,7 +34,7 @@ fun App() { RootNavGraph( rootNavController = navController, innerPadding = PaddingValues(), - startDestination = SplashRouteScreen.Splash.route + startDestination = Routes.Splash.name ) //MaterialTheme { @@ -42,7 +42,7 @@ fun App() { //OnBoardingScreen() //} - // Collecting state from presenter +// Collecting state from presenter // val showContent by presenter.isContentVisible.collectAsState() // val greeting by presenter.greetingText.collectAsState() // Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt index b92e4d5b..901d9f37 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt @@ -1,3 +1,4 @@ package network.bisq.mobile.presentation.ui.model +data class BottomNavigationItem(val title: String, val route: String, val icon: String) data class OnBoardingPage(val title: String, val image: String, val desc: String) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt new file mode 100644 index 00000000..ec584235 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt @@ -0,0 +1,67 @@ +package network.bisq.mobile.presentation.ui.navigation + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.size +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationBarItemColors +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import network.bisq.mobile.presentation.ui.model.BottomNavigationItem +import network.bisq.mobile.presentation.ui.theme.backgroundColor +import network.bisq.mobile.presentation.ui.theme.primaryGreenColor +import network.bisq.mobile.presentation.ui.theme.primaryStandard +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun BottomNavigation( + items: List, + currentRoute: String, + onItemClick: (BottomNavigationItem) -> Unit +) { + + NavigationBar( + containerColor = backgroundColor + ) { + items.forEach { navigationItem -> + NavigationBarItem( + colors = NavigationBarItemColors( + selectedIndicatorColor = backgroundColor, + selectedIconColor = primaryStandard, + selectedTextColor = primaryStandard, + unselectedIconColor = Color.White, + unselectedTextColor = Color.White, + disabledIconColor = Color.Red, + disabledTextColor = Color.Red + ), + interactionSource = remember { MutableInteractionSource() }, + selected = currentRoute == navigationItem.route, + onClick = { onItemClick(navigationItem) }, + icon = { + AsyncImage( + model = Res.getUri(navigationItem.icon), + contentDescription = null, + modifier = Modifier.size(32.dp), + colorFilter = ColorFilter.tint(color = if (navigationItem.route == currentRoute) primaryGreenColor else Color.White ) + ) + }, + label = { + Text( + text = navigationItem.title, + fontSize = 14.sp, + color = if (navigationItem.route == currentRoute) primaryGreenColor else Color.White + ) + } + ) + } + } +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt index f71c4aff..bf44f1b8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt @@ -1,9 +1,19 @@ package network.bisq.mobile.presentation.ui.navigation -sealed class SplashRouteScreen(var route: String) { - object Splash : SplashRouteScreen("splash") -} +import org.jetbrains.compose.resources.StringResource -sealed class OnBoardingRouteScreen(var route: String) { - object OnBoard : OnBoardingRouteScreen("onboard") +object Graph { + const val MainScreenGraph = "mainScreenGraph" } + +enum class Routes(val title: String) { + Splash(title = "splash"), + Onboarding(title = "onboarding"), + CreateProfile(title = "create_profile"), + BisqUrl(title = "bisq_url"), + TabContainer(title = "tab_container"), + TabHome(title = "tab_home"), + TabExchange(title = "tab_exchange"), + TabMyTrades(title = "tab_my_trades"), + TabSettings(title = "tab_settings"), +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt index a390e800..a94580b8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt @@ -9,10 +9,8 @@ import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable -import network.bisq.mobile.presentation.ui.navigation.OnBoardingRouteScreen -import network.bisq.mobile.presentation.ui.navigation.SplashRouteScreen -import network.bisq.mobile.presentation.ui.screens.OnBoardingScreen -import network.bisq.mobile.presentation.ui.screens.SplashScreen +import network.bisq.mobile.presentation.ui.navigation.* +import network.bisq.mobile.presentation.ui.screens.* import network.bisq.mobile.presentation.ui.theme.backgroundColor @Composable @@ -26,10 +24,10 @@ fun RootNavGraph( navController = rootNavController, startDestination = startDestination, ) { - composable(route = SplashRouteScreen.Splash.route) { + composable(route = Routes.Splash.name) { SplashScreen(rootNavController = rootNavController, innerPadding = innerPadding) } - composable(route = OnBoardingRouteScreen.OnBoard.route,enterTransition = { + composable(route = Routes.Onboarding.name, enterTransition = { slideIntoContainer( AnimatedContentTransitionScope.SlideDirection.Left, animationSpec = tween(300) @@ -37,5 +35,25 @@ fun RootNavGraph( }) { OnBoardingScreen(rootNavController = rootNavController) } + composable(route = Routes.CreateProfile.name, enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween(300) + ) + }) { + CreateProfileScreen(rootNavController = rootNavController) + } + composable(route = Routes.BisqUrl.name, enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween(300) + ) + }) { + URLScreen(rootNavController = rootNavController) + } + composable(route = Routes.TabContainer.name) { + TabContainerScreen(rootNavController = rootNavController) + } + TabNavGraph(rootNavController, innerPadding) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt new file mode 100644 index 00000000..3d629123 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt @@ -0,0 +1,37 @@ +package network.bisq.mobile.presentation.ui.navigation.graph + +import androidx.compose.foundation.layout.PaddingValues +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.compose.composable +import androidx.navigation.navigation +import network.bisq.mobile.presentation.ui.navigation.Routes +import network.bisq.mobile.presentation.ui.navigation.Graph +import network.bisq.mobile.presentation.ui.screens.ExchangeScreen +import network.bisq.mobile.presentation.ui.screens.HomeScreen +import network.bisq.mobile.presentation.ui.screens.MyTradesScreen +import network.bisq.mobile.presentation.ui.screens.SettingsScreen + +fun NavGraphBuilder.TabNavGraph( + rootNavController: NavHostController, + innerPadding: PaddingValues +) { + navigation( + startDestination = Routes.TabHome.name, + route = Graph.MainScreenGraph + ) { + composable(route = Routes.TabHome.name) { + HomeScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = Routes.TabExchange.name) { + ExchangeScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = Routes.TabMyTrades.name) { + MyTradesScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = Routes.TabSettings.name) { + SettingsScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + } + +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt new file mode 100644 index 00000000..d5fa6fe9 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt @@ -0,0 +1,65 @@ +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import network.bisq.mobile.presentation.ui.navigation.Routes +import network.bisq.mobile.presentation.ui.theme.backgroundColor +import network.bisq.mobile.presentation.ui.theme.primaryStandard +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun CreateProfileScreen( + rootNavController: NavController +) { + Scaffold( + containerColor = backgroundColor, + ) { innerPadding -> + Column( + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(bottom = 20.dp) + ) { + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = primaryStandard) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + rootNavController.navigate(Routes.BisqUrl.name) { + popUpTo(Routes.CreateProfile.name) { inclusive = true } + } + }) + .padding(horizontal = 64.dp, vertical = 12.dp), + text = "Next to BISQ Url", + color = Color.White + ) + + } + } +} + diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt index e2069193..06fe7d46 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt @@ -1,12 +1,34 @@ package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @Composable -fun ExchangeScreen() { - Text("Exchange - Buy / Sell") +fun ExchangeScreen(rootNavController: NavController, + innerPadding: PaddingValues +) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), // Applies the inner padding if necessary + contentAlignment = Alignment.Center // Centers the content within the Box + ) { + Text( + text = "Exchange - Buy / Sell", + fontSize = 32.sp, // Increases font size + color = Color.White // Sets font color to white + ) + } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt index 219303d8..04414196 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt @@ -1,12 +1,34 @@ package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @Composable -fun SettingsScreen() { - Text("Settings") +fun HomeScreen(rootNavController: NavController, + innerPadding: PaddingValues +) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), // Applies the inner padding if necessary + contentAlignment = Alignment.Center // Centers the content within the Box + ) { + Text( + text = "Home", + fontSize = 32.sp, // Increases font size + color = Color.White // Sets font color to white + ) + } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt index 1181a718..712b674b 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt @@ -1,11 +1,34 @@ + package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @Composable -fun MyTradesScreen() { - Text("My Trades") +fun MyTradesScreen(rootNavController: NavController, + innerPadding: PaddingValues +) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), // Applies the inner padding if necessary + contentAlignment = Alignment.Center // Centers the content within the Box + ) { + Text( + text = "My Trades", + fontSize = 32.sp, // Increases font size + color = Color.White // Sets font color to white + ) + } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt index c490d1b4..a95859e2 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -42,6 +42,7 @@ import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.model.OnBoardingPage +import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.backgroundColor import network.bisq.mobile.presentation.ui.theme.grey1 import network.bisq.mobile.presentation.ui.theme.grey2 @@ -113,7 +114,9 @@ fun OnBoardingScreen(rootNavController: NavController) { }, onClick = { if (pagerState.currentPage == 2) { - // navigate to next page + rootNavController.navigate(Routes.CreateProfile.name) { + popUpTo(Routes.Onboarding.name) { inclusive = true } + } } else { coroutineScope.launch { pagerState.animateScrollToPage( diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt index 55f78fee..4fb26f05 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt @@ -1,12 +1,34 @@ package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @Composable -fun SettingsScreen() { - Text("Home") +fun SettingsScreen(rootNavController: NavController, + innerPadding: PaddingValues +) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), // Applies the inner padding if necessary + contentAlignment = Alignment.Center // Centers the content within the Box + ) { + Text( + text = "Settings", + fontSize = 32.sp, // Increases font size + color = Color.White // Sets font color to white + ) + } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 903273cb..94cae56d 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -32,10 +32,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import bisqapps.shared.presentation.generated.resources.Res -import coil3.compose.LocalPlatformContext -import coil3.request.ImageRequest -import network.bisq.mobile.presentation.ui.navigation.OnBoardingRouteScreen -import network.bisq.mobile.presentation.ui.navigation.SplashRouteScreen +import network.bisq.mobile.presentation.ui.navigation.Routes //import bisqapps.shared.presentation.generated.resources.logo_with_slogan //import io.kamel.image.KamelImage @@ -109,8 +106,8 @@ fun LoadingProgress(navController: NavController) { loadProgress { progress -> currentProgress = progress } - navController.navigate(OnBoardingRouteScreen.OnBoard.route) { - popUpTo(SplashRouteScreen.Splash.route) { inclusive = true } + navController.navigate(Routes.Onboarding.name) { + popUpTo(Routes.Splash.name) { inclusive = true } } } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt new file mode 100644 index 00000000..3ddf4798 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt @@ -0,0 +1,58 @@ +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.navigation.NavController +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.rememberNavController +import network.bisq.mobile.presentation.ui.model.BottomNavigationItem +import network.bisq.mobile.presentation.ui.navigation.BottomNavigation +import network.bisq.mobile.presentation.ui.navigation.Graph +import network.bisq.mobile.presentation.ui.navigation.Routes +import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph +import network.bisq.mobile.presentation.ui.theme.secondaryColor + +val navigationListItem = listOf( + BottomNavigationItem("Home", Routes.TabHome.name, "drawable/home.svg"), + BottomNavigationItem("Buy/Sell", Routes.TabExchange.name, "drawable/market.svg"), + BottomNavigationItem("My Trades", Routes.TabMyTrades.name, "drawable/trades.svg"), + BottomNavigationItem("Settings", Routes.TabSettings.name, "drawable/settings.svg"), +) + + +@Composable +fun TabContainerScreen( rootNavController: NavController) { + val navController = rememberNavController() + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute by remember(navBackStackEntry) { + derivedStateOf { + navBackStackEntry?.destination?.route + } + } + + Scaffold( + containerColor = secondaryColor, + bottomBar = { + BottomNavigation( + items = navigationListItem, + currentRoute = currentRoute.orEmpty(), + onItemClick = { currentNavigationItem -> + navController.navigate(currentNavigationItem.route) { + navController.graph.startDestinationRoute?.let { route -> + popUpTo(route) { + saveState = true + } + } + launchSingleTop = true + restoreState = true + } + }) + } + + ) { innerPadding -> + RootNavGraph(rootNavController = navController,innerPadding = innerPadding, startDestination = Graph.MainScreenGraph) + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt new file mode 100644 index 00000000..8b403030 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt @@ -0,0 +1,65 @@ +package network.bisq.mobile.presentation.ui.screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import network.bisq.mobile.presentation.ui.navigation.Routes +import network.bisq.mobile.presentation.ui.theme.backgroundColor +import network.bisq.mobile.presentation.ui.theme.primaryStandard +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun URLScreen( + rootNavController: NavController +) { + Scaffold( + containerColor = backgroundColor, + ) { innerPadding -> + Column( + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(bottom = 20.dp) + ) { + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = primaryStandard) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + rootNavController.navigate(Routes.TabContainer.name) { + popUpTo(Routes.BisqUrl.name) { inclusive = true } + } + }) + .padding(horizontal = 64.dp, vertical = 12.dp), + text = "Next to Tab Home", + color = Color.White + ) + + } + } +} + From 5c6585f82cc22c9133082e74a595f70e1581a703 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Thu, 31 Oct 2024 14:59:31 +0530 Subject: [PATCH 06/31] Profile, Bisq URL screen - UI --- bisqapps/gradle.properties | 2 +- .../composeResources/drawable/bell.svg | 4 + .../composeResources/drawable/bitcoin.png | Bin 0 -> 23035 bytes .../composeResources/drawable/bot_image.svg | 9 + .../composeResources/drawable/copy.svg | 10 + .../composeResources/drawable/filter.xml | 9 + .../drawable/flag_of_india.xml | 96 ++++++++ .../composeResources/drawable/home.svg | 3 + .../drawable/ic_star_empty.xml | 10 + .../drawable/ic_start_filled.xml | 10 + .../drawable/logo_with_slogan_xml.xml | 10 + .../composeResources/drawable/market.svg | 3 + .../composeResources/drawable/qr.svg | 12 + .../drawable/question_mark.svg | 3 + .../composeResources/drawable/right_arrow.svg | 3 + .../composeResources/drawable/settings.svg | 3 + .../composeResources/drawable/trades.svg | 10 + .../ui/components/MaterialTextField.kt | 77 ++++++ .../ui/screens/CreateProfileScreen.kt | 120 +++++++--- .../presentation/ui/screens/SplashScreen.kt | 6 +- .../presentation/ui/screens/URLScreen.kt | 219 ++++++++++++++++-- 21 files changed, 568 insertions(+), 51 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bitcoin.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt diff --git a/bisqapps/gradle.properties b/bisqapps/gradle.properties index 0245fefd..cb5994a9 100644 --- a/bisqapps/gradle.properties +++ b/bisqapps/gradle.properties @@ -1,5 +1,5 @@ #Gradle -org.gradle.jvmargs=-Xmx4096M -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx4096M" +org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx8g" org.gradle.caching=true org.gradle.configuration-cache=true diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg new file mode 100644 index 00000000..e86007f0 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg @@ -0,0 +1,4 @@ + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bitcoin.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bitcoin.png new file mode 100644 index 0000000000000000000000000000000000000000..63084db447a481b86823febc9243bda4506edcb0 GIT binary patch literal 23035 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 literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg new file mode 100644 index 00000000..5508d6c7 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg new file mode 100644 index 00000000..b63853df --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml new file mode 100644 index 00000000..2972f723 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml @@ -0,0 +1,9 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml new file mode 100644 index 00000000..fd210361 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg new file mode 100644 index 00000000..085646c4 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml new file mode 100644 index 00000000..be22f749 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml new file mode 100644 index 00000000..7d7dc714 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml new file mode 100644 index 00000000..ac2a8116 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml @@ -0,0 +1,10 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg new file mode 100644 index 00000000..036bda12 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg new file mode 100644 index 00000000..68ee9ad9 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg new file mode 100644 index 00000000..aa6deb35 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg new file mode 100644 index 00000000..3d7c66ce --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg new file mode 100644 index 00000000..3aea4047 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg new file mode 100644 index 00000000..915bf9e4 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt new file mode 100644 index 00000000..6cdef2ff --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt @@ -0,0 +1,77 @@ +package network.bisq.mobile.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import bisqapps.shared.presentation.generated.resources.Res +import network.bisq.mobile.presentation.ui.theme.* +import org.jetbrains.compose.resources.Font + +@Composable +fun MaterialTextField(text: String,onValueChanged: (String) -> Unit) { + var isFocused by remember { mutableStateOf(false) } + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 12.dp) + .clip(shape = RoundedCornerShape(6.dp)) + .background(color = secondaryStandard) + ) { + TextField( + value = text, + singleLine = true, + modifier = Modifier.fillMaxWidth().clickable { isFocused = true } + .onFocusChanged { focusState -> + isFocused = focusState.isFocused + }, + textStyle = TextStyle(fontSize = 22.sp), + onValueChange = onValueChanged, + colors = TextFieldDefaults.colors( + focusedTextColor = primaryTextColor, + unfocusedTextColor = secondaryHover, + unfocusedIndicatorColor = secondaryStandard, + focusedIndicatorColor = Color.Transparent, + focusedContainerColor = secondaryStandard, + cursorColor = Color.Blue, + unfocusedContainerColor = secondaryStandard + ), + placeholder = { + Text( + text = "Choose your nickname", + fontSize = 16.sp + ) + } + ) + if (isFocused) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(2.dp) + .align(Alignment.BottomCenter) + .background(primaryStandard) + ) + } + } +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt index d5fa6fe9..4dbeee51 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt @@ -3,32 +3,37 @@ package network.bisq.mobile.presentation.ui.screens import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.navigation.NavController +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import network.bisq.mobile.components.MaterialTextField import network.bisq.mobile.presentation.ui.navigation.Routes -import network.bisq.mobile.presentation.ui.theme.backgroundColor -import network.bisq.mobile.presentation.ui.theme.primaryStandard +import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi +private lateinit var textState: MutableState + @OptIn(ExperimentalResourceApi::class) @Composable fun CreateProfileScreen( rootNavController: NavController ) { + textState = remember { mutableStateOf("") } Scaffold( containerColor = backgroundColor, ) { innerPadding -> @@ -40,26 +45,89 @@ fun CreateProfileScreen( .padding(innerPadding) .padding(bottom = 20.dp) ) { - Text( - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = primaryStandard) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - rootNavController.navigate(Routes.BisqUrl.name) { - popUpTo(Routes.CreateProfile.name) { inclusive = true } - } - }) - .padding(horizontal = 64.dp, vertical = 12.dp), - text = "Next to BISQ Url", - color = Color.White - ) + Column(horizontalAlignment = Alignment.CenterHorizontally) { + AsyncImage( + model = Res.getUri("drawable/log_with_slogan.svg"), + contentDescription = null, + modifier = Modifier.height(62.dp).width(200.dp), + ) + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = "Create your profile", + fontSize = 36.sp, + color = grey1 + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = "Your public profile consists of a nickname (picked by you) and bot icon (generated cryptographically)", + color = grey2, + fontSize = 16.sp, + modifier = Modifier.padding(horizontal = 24.dp), + textAlign = TextAlign.Center, + ) + Spacer(modifier = Modifier.height(40.dp)) + Column(modifier = Modifier.padding(horizontal = 54.dp)) { + Text(text = "Profile nickname", color = White2) + MaterialTextField(textState.value, onValueChanged = { textState.value = it }) + } + Spacer(modifier = Modifier.height(36.dp)) + AsyncImage( + model = Res.getUri("drawable/bot_image.svg"), + contentDescription = null, + modifier = Modifier.size(120.dp), + ) + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = "Sleepily-Distracted-Zyophyte-257", + fontSize = 18.sp, + color = Color.White + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = "BOT ID", + fontSize = 18.sp, + color = grey2 + ) + Spacer(modifier = Modifier.height(38.dp)) + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = Black5) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = {}) + .padding(horizontal = 64.dp, vertical = 12.dp), + text = "Generate new bot icon", + color = Color.White, + ) + Spacer(modifier = Modifier.height(40.dp)) + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = if (textState.value.isEmpty()) primaryDisabled else primaryStandard) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + if (textState.value.isNotEmpty()) { + rootNavController.navigate(Routes.BisqUrl.name) { + popUpTo(Routes.CreateProfile.name) { + inclusive = true + } + } + } + }) + .padding(horizontal = 64.dp, vertical = 12.dp), + text = "Next", + color = if (textState.value.isEmpty()) grey2 else Color.White + ) + } } } -} - +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 94cae56d..37e01610 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -31,10 +31,9 @@ import coil3.compose.AsyncImage import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import bisqapps.shared.presentation.generated.resources.Res import network.bisq.mobile.presentation.ui.navigation.Routes - -//import bisqapps.shared.presentation.generated.resources.logo_with_slogan +import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.logo_with_slogan //import io.kamel.image.KamelImage //import io.kamel.image.asyncPainterResource @@ -89,6 +88,7 @@ fun SplashScreen(rootNavController: NavController, // Solution is to convert the SVG to VectorDrawable. // But doing that makes it work only in Android, not with iOS // Image(painterResource(Res.drawable.logo_with_slogan), null) + // Image(painterResource(Res.drawable.logo_with_slogan), null) LoadingProgress(rootNavController) } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt index 8b403030..4e30623b 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt @@ -1,34 +1,56 @@ package network.bisq.mobile.presentation.ui.screens +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.slideInHorizontally import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.navigation.NavController +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import network.bisq.mobile.components.MaterialTextField import network.bisq.mobile.presentation.ui.navigation.Routes -import network.bisq.mobile.presentation.ui.theme.backgroundColor -import network.bisq.mobile.presentation.ui.theme.primaryStandard +import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi +private lateinit var textState: MutableState + @OptIn(ExperimentalResourceApi::class) @Composable fun URLScreen( rootNavController: NavController ) { + textState = remember { mutableStateOf("") } + val isConnected by remember { mutableStateOf(false) } Scaffold( containerColor = backgroundColor, ) { innerPadding -> @@ -40,26 +62,181 @@ fun URLScreen( .padding(innerPadding) .padding(bottom = 20.dp) ) { - Text( - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = primaryStandard) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - rootNavController.navigate(Routes.TabContainer.name) { - popUpTo(Routes.BisqUrl.name) { inclusive = true } - } - }) - .padding(horizontal = 64.dp, vertical = 12.dp), - text = "Next to Tab Home", - color = Color.White - ) + Column(horizontalAlignment = Alignment.CenterHorizontally) { + AsyncImage( + model = Res.getUri("drawable/log_with_slogan.svg"), + contentDescription = null, + modifier = Modifier.height(62.dp).width(200.dp), + ) + Spacer(modifier = Modifier.height(32.dp)) + Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Bisq URL", + fontSize = 28.sp, + color = Color.White + ) + AsyncImage( + model = Res.getUri("drawable/question_mark.svg"), + contentDescription = null, + modifier = Modifier.size(24.dp) + ) + } + + MaterialTextField(textState.value, onValueChanged = { textState.value = it }) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = Black5) + .padding(horizontal = 46.dp, vertical = 12.dp) + + ) { + AsyncImage( + model = Res.getUri("drawable/copy.svg"), + contentDescription = null, + modifier = Modifier.size(20.dp), + ) + Spacer(modifier = Modifier.width(10.dp)) + Text( + text = "Paste", + fontSize = 16.sp, + color = Color.White + ) + } + Row( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = primaryStandard) + .padding(horizontal = 46.dp, vertical = 12.dp) + ) { + AsyncImage( + model = Res.getUri("drawable/qr.svg"), + contentDescription = null, + modifier = Modifier.size(20.dp), + ) + Spacer(modifier = Modifier.width(10.dp)) + Text( + text = "Scan", + fontSize = 16.sp, + color = Color.White + ) + } + } + Spacer(modifier = Modifier.height(36.dp)) + Text( + text = "STATUS", + fontSize = 18.sp, + color = grey2 + ) + Spacer(modifier = Modifier.height(12.dp)) + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + text = if(isConnected) "Connected" else "Not Connected", + fontSize = 22.sp, + color = Color.White + ) + Spacer(modifier = Modifier.width(12.dp)) + Text( + text = "", + modifier = Modifier.clip( + RoundedCornerShape(5.dp) + ).background(color =if(isConnected) primaryStandard else Danger1).size(10.dp), + ) + } + + } + + } + var visible by remember { + mutableStateOf(false) + } + + + if (!visible) { + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = if (textState.value.isEmpty()) primaryDisabled else primaryStandard) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + visible = !visible + }) + .padding(horizontal = 32.dp, vertical = 12.dp), + text = "Test Connection", + color = if (textState.value.isEmpty()) grey2 else Color.White, + ) + } else { + Row (modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)){ + AnimatedVisibility( + visible = visible, + enter = slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(700)), + ) { + Text( + modifier = Modifier + + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = Black5) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + + }) + .padding(horizontal = 32.dp, vertical = 12.dp), + text = "Test Connection", + color = if (textState.value.isEmpty()) grey2 else Color.White, + ) + } + Spacer(modifier = Modifier.width(20.dp)) + AnimatedVisibility( + visible = visible, + enter = fadeIn(animationSpec = tween(300)), + + ) { + Text( + modifier = Modifier + .fillMaxWidth() + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = primaryStandard) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + rootNavController.navigate(Routes.TabContainer.name) { + popUpTo(Routes.BisqUrl.name) { + inclusive = true + } + } + }) + .padding(horizontal = 32.dp, vertical = 12.dp), + text = "Next", + textAlign = TextAlign.Center, + color = Color.White, + ) + } + } + + } + } + } } - From a903329f6119bce51edd2b60a9ae1e1171fa1b03 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Thu, 31 Oct 2024 17:37:04 +0530 Subject: [PATCH 07/31] Exchange screen - UI --- .../composeResources/drawable/euro.svg | 9 +++ .../composeResources/drawable/gpb.svg | 9 +++ .../composeResources/drawable/sort.svg | 3 + .../composeResources/drawable/usd.svg | 9 +++ .../ui/components/CurrencyProfileCard.kt | 49 ++++++++++++++ .../presentation/ui/components/TopBar.kt | 65 ++++++++++++++++++ .../ui/screens/CreateProfileScreen.kt | 2 +- .../presentation/ui/screens/ExchangeScreen.kt | 66 ++++++++++++++----- .../presentation/ui/screens/URLScreen.kt | 2 +- 9 files changed, 196 insertions(+), 18 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg new file mode 100644 index 00000000..c3edfee1 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg new file mode 100644 index 00000000..067ea620 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg new file mode 100644 index 00000000..fe6c3cc0 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg new file mode 100644 index 00000000..f59ccaec --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt new file mode 100644 index 00000000..16ba5628 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt @@ -0,0 +1,49 @@ +package network.bisq.mobile.presentation.ui.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import network.bisq.mobile.presentation.ui.theme.primaryStandard +import network.bisq.mobile.presentation.ui.theme.secondaryTextColor +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun CurrencyProfileCard(currencyName: String, currencyShort: String, imagePath: String) { + Row( + modifier = Modifier.fillMaxWidth().padding(horizontal = 14.dp, vertical = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + AsyncImage( + model = Res.getUri(imagePath), + contentDescription = null, + modifier = Modifier.size(36.dp), + ) + Spacer(modifier = Modifier.width(8.dp)) + Column { + Text(text = currencyName, color = Color.White) + Spacer(modifier = Modifier.height(8.dp)) + Text(text = currencyShort, color = secondaryTextColor) + } + } + Text(text = "43 offers", color = primaryStandard) + } +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt new file mode 100644 index 00000000..e09c359f --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt @@ -0,0 +1,65 @@ +package network.bisq.mobile.presentation.ui.components + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import network.bisq.mobile.presentation.ui.theme.backgroundColor +import org.jetbrains.compose.resources.ExperimentalResourceApi + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalResourceApi::class) +@Composable +fun TopBar(title: String = "",isHome:Boolean = false) { + TopAppBar( + modifier = Modifier.padding(horizontal = 16.dp).padding(end = 16.dp), + colors = TopAppBarDefaults.topAppBarColors( + containerColor = backgroundColor, + ), + title = { + if (isHome) { + AsyncImage( + model = Res.getUri("drawable/logo.svg"), + contentDescription = null, + modifier = Modifier.height(34.dp).width(100.dp), + ) + } else { + Text(title, color = Color.White) + } + }, + actions = { + Row(verticalAlignment = Alignment.CenterVertically) { + + AsyncImage( + model = Res.getUri("drawable/bell.svg"), + contentDescription = null, + modifier = Modifier.size(30.dp), + ) + + Spacer(modifier = Modifier.width(12.dp)) + + AsyncImage( + model = Res.getUri("drawable/bot_image.svg"), + contentDescription = null, + modifier = Modifier.size(40.dp), + ) + + } + + }, + ) +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt index 4dbeee51..a10d831c 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt @@ -47,7 +47,7 @@ fun CreateProfileScreen( ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { AsyncImage( - model = Res.getUri("drawable/log_with_slogan.svg"), + model = Res.getUri("drawable/logo_with_slogan.svg"), contentDescription = null, modifier = Modifier.height(62.dp).width(200.dp), ) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt index 06fe7d46..8128712a 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt @@ -1,34 +1,68 @@ - package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.sp +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import network.bisq.mobile.presentation.ui.components.CurrencyProfileCard +import network.bisq.mobile.components.MaterialTextField +import network.bisq.mobile.presentation.ui.components.TopBar import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @Composable -fun ExchangeScreen(rootNavController: NavController, - innerPadding: PaddingValues +fun ExchangeScreen( + rootNavController: NavController, + innerPadding: PaddingValues ) { - Box( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding), // Applies the inner padding if necessary - contentAlignment = Alignment.Center // Centers the content within the Box + val originDirection = LocalLayoutDirection.current + Column( + modifier = Modifier.fillMaxSize().padding( + start = innerPadding.calculateStartPadding(originDirection), + end = innerPadding.calculateEndPadding(originDirection), + bottom = innerPadding.calculateBottomPadding(), + ), ) { - Text( - text = "Exchange - Buy / Sell", - fontSize = 32.sp, // Increases font size - color = Color.White // Sets font color to white - ) + TopBar("Buy/Sell") + Column(modifier = Modifier.padding(vertical = 12.dp, horizontal = 32.dp)) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Box(modifier = Modifier.width(250.dp)) { + MaterialTextField(text = "Search", onValueChanged = {}) + } + AsyncImage( + model = Res.getUri("drawable/sort.svg"), + contentDescription = null, + modifier = Modifier.size(24.dp), + ) + } + Spacer(modifier = Modifier.height(12.dp)) + Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { + CurrencyProfileCard("US Dollars", "USD", "drawable/usd.svg") + CurrencyProfileCard("Euro", "EUR", "drawable/euro.svg") + CurrencyProfileCard("British Pounds", "GPB", "drawable/gpb.svg") + } + } } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt index 4e30623b..cacf6ec6 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt @@ -64,7 +64,7 @@ fun URLScreen( ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { AsyncImage( - model = Res.getUri("drawable/log_with_slogan.svg"), + model = Res.getUri("drawable/logo_with_slogan.svg"), contentDescription = null, modifier = Modifier.height(62.dp).width(200.dp), ) From 7c7b0676515da4ea9b8d77555c4b45f257e8b2b6 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 2 Nov 2024 15:32:36 +0530 Subject: [PATCH 08/31] Home screen --- .../composeResources/drawable/logo.svg | 9 + .../drawable/rounded_browser.svg | 4 + .../drawable/rounded_chat.svg | 4 + .../drawable/rounded_star.svg | 4 + .../presentation/ui/screens/HomeScreen.kt | 238 +++++++++++++++++- .../mobile/presentation/ui/theme/Color.kt | 2 + 6 files changed, 249 insertions(+), 12 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg new file mode 100644 index 00000000..ca281a8f --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg new file mode 100644 index 00000000..d96a3994 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg @@ -0,0 +1,4 @@ + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg new file mode 100644 index 00000000..9b00c9d3 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg @@ -0,0 +1,4 @@ + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg new file mode 100644 index 00000000..ac06d522 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg @@ -0,0 +1,4 @@ + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt index 04414196..90fdd856 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt @@ -1,34 +1,248 @@ - package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController +import bisqapps.shared.presentation.generated.resources.Res +import coil3.compose.AsyncImage +import network.bisq.mobile.presentation.ui.components.TopBar +import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.Font -@OptIn(ExperimentalResourceApi::class) @Composable -fun HomeScreen(rootNavController: NavController, - innerPadding: PaddingValues +fun HomeScreen( + rootNavController: NavController, + innerPadding: PaddingValues ) { - Box( + val originDirection = LocalLayoutDirection.current + Column( + modifier = Modifier.fillMaxSize().padding( + start = innerPadding.calculateStartPadding(originDirection), + end = innerPadding.calculateEndPadding(originDirection), + bottom = innerPadding.calculateBottomPadding(), + ), + ) { + TopBar(isHome = true) + Column( + modifier = Modifier.padding(horizontal = 32.dp, vertical = 15.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(42.dp) + ) { + Column { + PriceProfileCard( + price = "$ 60,000.00", + priceText = "Market price" + ) + Spacer(modifier = Modifier.height(16.dp)) + Row(modifier = Modifier.fillMaxWidth()) { + Box(modifier = Modifier.weight(1f)) { + PriceProfileCard( + price = "101", + priceText = "Offers online" + ) + } + Spacer(modifier = Modifier.width(16.dp)) + Box(modifier = Modifier.weight(1f)) { + PriceProfileCard( + price = "4,223", + priceText = "Published profiles" + ) + } + } + } + + WelcomeCard( + title = "Get your first BTC", + buttonText = "Enter Bisq Easy" + ) + Column { + InstructionCard( + imagePath = "drawable/fiat_btc.svg", + title = "Multiple trade protocols", + description = "Checkout the roadmap for upcoming trade protocols. Get an overview about the features of the different protocols.", + buttonText = "Explore trade protocols" + ) + Spacer(modifier = Modifier.height(24.dp)) + InstructionCard( + imagePath = "drawable/learn_and_discover.svg", + title = "Learn & discover", + description = "Learn about Bitcoin and checkout upcoming events. Meet other Bisq users in the discussion chat.", + buttonText = "Learn more" + ) + } + } + } +} + +@Composable +fun WelcomeCard(title: String, buttonText: String) { + NeumorphicCard{ + Column( + modifier = Modifier.shadow( + ambientColor = Color.Blue, spotColor = primaryStandard, + elevation = 2.dp, + shape = RoundedCornerShape(5.dp), + + ).clip(shape = RoundedCornerShape(5.dp)).background(color = Black2) + .padding(24.dp), + verticalArrangement = Arrangement.spacedBy(32.dp) + ) { + Text( + text = title, + color = Color.White, + fontSize = 28.sp + ) + Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { + FeatureCard( + imagePath = "drawable/rounded_browser.svg", + title = "Start trading or browser open offers in the offerbook" + ) + FeatureCard( + imagePath = "drawable/rounded_chat.svg", + title = "Chat based and guided user interface for trading" + ) + FeatureCard( + imagePath = "drawable/rounded_star.svg", + title = "Security is based on seller’s reputation" + ) + } + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(4.dp)) + .background(color = primaryStandard) + .fillMaxWidth() + .padding(vertical = 12.dp), + textAlign = TextAlign.Center, + text = buttonText, + fontSize = 16.sp, + color = Color.White + ) + } + } + +} + +@Composable +fun PriceProfileCard(price: String, priceText: String) { + Column( modifier = Modifier - .fillMaxSize() - .padding(innerPadding), // Applies the inner padding if necessary - contentAlignment = Alignment.Center // Centers the content within the Box + .clip(shape = RoundedCornerShape(4.dp)) + .background(color = Black3) + .padding(vertical = 12.dp).fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + textAlign = TextAlign.Center, + text = price, + fontSize = 18.sp, + color = Color.White + ) + Spacer(modifier = Modifier.height(18.dp)) + Text( + textAlign = TextAlign.Center, + text = priceText, + fontSize = 14.sp, + color = grey1 + ) + } +} + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun FeatureCard(imagePath: String, title: String) { + Row(verticalAlignment = Alignment.CenterVertically) { + AsyncImage( + model = Res.getUri(imagePath), + contentDescription = null, + modifier = Modifier.size(20.dp) + ) + Spacer(modifier = Modifier.width(9.dp)) + Text( + text = title, + color = Color.White, + fontSize = 16.sp + ) + } +} + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun InstructionCard(imagePath: String, title: String, description: String, buttonText: String) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.clip(shape = RoundedCornerShape(8.dp)).background(color = Black3) + .padding(vertical = 18.dp, horizontal = 12.dp), + verticalArrangement = Arrangement.spacedBy(18.dp) ) { + AsyncImage( + model = Res.getUri(imagePath), + contentDescription = null, + modifier = Modifier.size(50.dp) + ) Text( - text = "Home", - fontSize = 32.sp, // Increases font size - color = Color.White // Sets font color to white + text = title, + fontSize = 16.sp, + color = Color.White + ) + Text( + text = description, + fontSize = 14.sp, + textAlign = TextAlign.Center, + color = grey3 + ) + Text( + modifier = Modifier + .clip(shape = RoundedCornerShape(4.dp)) + .background(color = Black5) + .padding(horizontal = 18.dp, vertical = 6.dp), + text = buttonText, + fontSize = 12.sp, + color = Color.White ) } -} \ No newline at end of file +} + +@Composable +fun NeumorphicCard( + modifier: Modifier = Modifier, + content: @Composable () -> Unit +) { + + Box( + modifier = modifier + .shadow(elevation = 8.dp, shape = RoundedCornerShape(5.dp), spotColor = primaryStandard) + .padding(2.dp) + ) { + content() + } + +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt index 397cd628..d6097dff 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt @@ -12,9 +12,11 @@ val secondaryHover = Color(0xFF525252) val secondaryDisabled = Color(0x642F2F2F) val grey1 = Color(0xFF999999) val grey2 = Color(0xFF747474) +val grey3 = Color(0xFF6B6B6B) val White2 = Color(0xFFF8F8F8) val Black5 = Color(0xFF333333) val Black3 = Color(0xFF282828) +val Black2 = Color(0xFF212121) val Danger1 = Color(0xFFDB0000) From 1f0b8a624bc299c62d917917015ad12f621cbea9 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 6 Nov 2024 15:19:29 +0530 Subject: [PATCH 09/31] Theme - Colors, Typography classes --- .../composeResources/drawable/bisq_logo.png | Bin 0 -> 20916 bytes .../font/ibm_plex_sans_bold.ttf | Bin 0 -> 175712 bytes .../font/ibm_plex_sans_light.ttf | Bin 0 -> 178140 bytes .../font/ibm_plex_sans_medium.ttf | Bin 0 -> 177104 bytes .../font/ibm_plex_sans_regular.ttf | Bin 0 -> 175748 bytes .../font/ibm_plex_sans_thin.ttf | Bin 0 -> 178896 bytes .../bisq/mobile/presentation/ui/App.kt | 15 +- .../ui/components/foundation/BisqText.kt | 470 ++++++++++++++++++ .../presentation/ui/screens/SplashScreen.kt | 44 +- .../mobile/presentation/ui/theme/BisqColor.kt | 133 +++++ .../mobile/presentation/ui/theme/BisqTheme.kt | 30 ++ 11 files changed, 644 insertions(+), 48 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_logo.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_bold.ttf create mode 100755 bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_light.ttf create mode 100755 bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_medium.ttf create mode 100755 bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_regular.ttf create mode 100755 bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_thin.ttf create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt create mode 100755 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqTheme.kt diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_logo.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..42400b3e0761ed5d39c095269c15bb241c6465e0 GIT binary patch literal 20916 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 BC`AAO literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_bold.ttf b/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e5389d833ffadfad83fdea8ff707d149ab6c03f8 GIT binary patch literal 175712 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 OE*Nb}?`#^~uKhnq-os1) literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_light.ttf b/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_light.ttf new file mode 100755 index 0000000000000000000000000000000000000000..b3d035d5da3772f0f17f53463df8660e2d8cbb1f GIT binary patch literal 178140 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¿sF-kjnF+pO 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�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 z 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 P7q_K0wk_U*dHR0=O+c&= literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_medium.ttf b/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_medium.ttf new file mode 100755 index 0000000000000000000000000000000000000000..9395402b0ae00fa731c4ad63958a41dff26d9344 GIT binary patch literal 177104 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 literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_regular.ttf b/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_regular.ttf new file mode 100755 index 0000000000000000000000000000000000000000..b5819647e1dfa7dae61b29e582f3464a90c537e1 GIT binary patch literal 175748 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 Omrr(PR(4MAwEho+ftIfT literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_thin.ttf b/bisqapps/shared/presentation/src/commonMain/composeResources/font/ibm_plex_sans_thin.ttf new file mode 100755 index 0000000000000000000000000000000000000000..910458a9e8c595366546f20d9dcb513bc2fb0428 GIT binary patch literal 178896 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 Q{KyUKIx;&u*6lL>AKz%1D*ylh literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index a3996c13..d864123c 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -12,6 +12,7 @@ import network.bisq.mobile.presentation.ui.screens.SplashScreen import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph +import network.bisq.mobile.presentation.ui.theme.BisqTheme interface AppPresenter { // Observables for state @@ -31,11 +32,14 @@ fun App() { val presenter: AppPresenter = koinInject() val navController = rememberNavController() - RootNavGraph( - rootNavController = navController, - innerPadding = PaddingValues(), - startDestination = Routes.Splash.name - ) + + BisqTheme(darkTheme = true) { + RootNavGraph( + rootNavController = navController, + innerPadding = PaddingValues(), + startDestination = Routes.Splash.name + ) + } //MaterialTheme { //SplashScreen() @@ -55,7 +59,6 @@ fun App() { // Text("Compose: $greeting") // } // } -// } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt new file mode 100644 index 00000000..81e2548f --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt @@ -0,0 +1,470 @@ +package network.bisq.mobile.presentation.ui.components.foundation + +import androidx.compose.runtime.Composable +import androidx.compose.material3.Text +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.sp +import org.jetbrains.compose.resources.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.unit.TextUnit +import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_thin +import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_light +import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_regular +import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_medium +import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_bold +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +enum class FontWeight { + LIGHT, + REGULAR, + MEDIUM, + BOLD, +} + +enum class FontSize(val size: TextUnit) { + XSMALL(12.sp), + SMALL(14.sp), + BASE(16.sp), + LARGE(18.sp), + H6(20.sp), + H5(22.sp), + H4(25.sp), + H3(28.sp), + H2(32.sp), + H1(36.sp); +} + +object BisqText { + @Composable + fun styledText( + text: String, + color: Color = BisqTheme.colors.light1, + fontSize: FontSize = FontSize.BASE, + fontWeight: FontWeight = FontWeight.REGULAR, + ) { + + val fontFamily = when(fontWeight) { + FontWeight.LIGHT -> FontFamily(Font(Res.font.ibm_plex_sans_light)) + FontWeight.REGULAR -> FontFamily(Font(Res.font.ibm_plex_sans_regular)) + FontWeight.MEDIUM -> FontFamily(Font(Res.font.ibm_plex_sans_medium)) + FontWeight.BOLD -> FontFamily(Font(Res.font.ibm_plex_sans_bold)) + } + + return Text( + text = text, + color = color, + fontSize = fontSize.size, + fontFamily = fontFamily, + ) + } + + @Composable + fun xsmallLight(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.XSMALL, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun xsmallRegular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.XSMALL, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun xsmallMedium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.XSMALL, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun xsmallBold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.XSMALL, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun smallLight(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.SMALL, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun smallRegular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.SMALL, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun smallMedium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.SMALL, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun smallBold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.SMALL, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun baseLight(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.BASE, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun baseRegular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.BASE, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun baseMedium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.BASE, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun baseBold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.BASE, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun largeLight(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.LARGE, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun largeRegular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.LARGE, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun largeMedium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.LARGE, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun largeBold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.LARGE, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun h6Light(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H6, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun h6Regular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H6, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun h6Medium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H6, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun h6Bold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H6, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun h5Light(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H5, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun h5Regular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H5, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun h5Medium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H5, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun h5Bold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H5, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun h4Light(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H4, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun h4Regular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H4, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun h4Medium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H4, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun h4Bold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H4, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun h3Light(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H3, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun h3Regular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H3, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun h3Medium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H3, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun h3Bold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H3, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun h2Light(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H2, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun h2Regular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H2, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun h2Medium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H2, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun h2Bold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H2, + fontWeight = FontWeight.BOLD, + color=color, + ) + } + + + @Composable + fun h1Light(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H1, + fontWeight = FontWeight.LIGHT, + color=color, + ) + } + + @Composable + fun h1Regular(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H1, + fontWeight = FontWeight.REGULAR, + color=color, + ) + } + + @Composable + fun h1Medium(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H1, + fontWeight = FontWeight.MEDIUM, + color=color, + ) + } + + @Composable + fun h1Bold(text: String, color: Color = BisqTheme.colors.light1) { + styledText( + text = text, + fontSize = FontSize.H1, + fontWeight = FontWeight.BOLD, + color=color, + ) + } +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 37e01610..6cc89e15 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -27,15 +27,12 @@ import network.bisq.mobile.presentation.ui.theme.secondaryHover import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.ExperimentalResourceApi -import coil3.compose.AsyncImage import kotlinx.coroutines.delay import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.navigation.Routes import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.logo_with_slogan -//import io.kamel.image.KamelImage -//import io.kamel.image.asyncPainterResource +import bisqapps.shared.presentation.generated.resources.bisq_logo @OptIn(ExperimentalResourceApi::class) @Composable @@ -52,49 +49,12 @@ fun SplashScreen(rootNavController: NavController, .background(color = backgroundColor) .padding(top = 48.dp, bottom = 30.dp) ) { - // 3. Having issues rendering in both iOS and Android using Kamel (TODO: Yet to understand how ktor integration works with the lib, to properly try) - // KamelImage( - // { asyncPainterResource("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg") }, contentDescription = "Hi" - // ) - // KamelImage( - // { asyncPainterResource("drawable/logo_with_slogan.svg") }, contentDescription = null - // ) - - // 2. Image not loading in iOS, though some Image placeholder is placed. - // Though it's said that with Coil3.0.0, iOS is supported - AsyncImage( - model = Res.getUri("drawable/logo_with_slogan.svg"), - contentDescription = "Bisq logo with slogan", - modifier = Modifier.height(92.dp).width(300.dp), - ) - // TODO: Have to try this sample setup using 'viewModel' - // https://github.com/coil-kt/coil/blob/main/samples/compose/src/commonMain/kotlin/sample/compose/App.kt - // AsyncImage( - // model = ImageRequest.Builder(LocalPlatformContext.current) - // .data(screen.image.uri) - // .placeholderMemoryCacheKey(screen.placeholder) - // .extras(screen.image.extras) - // .build(), - // contentDescription = null, - // modifier = Modifier.fillMaxSize(), - // ) - // AsyncImage( - // model = Res.getUri("https://image.nostr.build/resp/1080p/1f323cd199ad021209f74166e2de3693548918f8842eb2f29eb2fb9c04c3bdd8.jpg"), - // contentDescription = "Bisq logo with slogan", - // modifier = Modifier.height(92.dp).width(300.dp), - // ) - // - // 1. Loading images from resources, doesn't work with SVG. - // Solution is to convert the SVG to VectorDrawable. - // But doing that makes it work only in Android, not with iOS - // Image(painterResource(Res.drawable.logo_with_slogan), null) - // Image(painterResource(Res.drawable.logo_with_slogan), null) + Image(painterResource(Res.drawable.bisq_logo), "Bisq Logo") LoadingProgress(rootNavController) } } } - @Composable fun LoadingProgress(navController: NavController) { var currentProgress by remember { mutableFloatStateOf(0f) } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt new file mode 100644 index 00000000..2fd77d94 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt @@ -0,0 +1,133 @@ +package network.bisq.mobile.presentation.ui.theme + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color + +@Immutable +data class BisqColors ( + val dark1: Color, + val dark2: Color, + val dark3: Color, + val dark4: Color, + val dark5: Color, + val light1: Color, + val light2: Color, + val light3: Color, + val light4: Color, + val light5: Color, + val grey1: Color, + val grey2: Color, + val grey3: Color, + val grey4: Color, + val grey5: Color, + val primary: Color, + val primaryHover: Color, + val primaryDisabled: Color, + val primary2: Color, + val secondary: Color, + val secondaryHover: Color, + val secondaryDisabled: Color, + val danger: Color, + val dangerHover: Color, + val dangerDisabled: Color, + val warning: Color, + val warningHover: Color, + val warningDisabled: Color, +) + + +val LocalBisqColors = staticCompositionLocalOf { + BisqColors( + dark1 = Color.Unspecified, + dark2 = Color.Unspecified, + dark3 = Color.Unspecified, + dark4 = Color.Unspecified, + dark5 = Color.Unspecified, + light1 = Color.Unspecified, + light2 = Color.Unspecified, + light3 = Color.Unspecified, + light4 = Color.Unspecified, + light5 = Color.Unspecified, + grey1 = Color.Unspecified, + grey2 = Color.Unspecified, + grey3 = Color.Unspecified, + grey4 = Color.Unspecified, + grey5 = Color.Unspecified, + primary = Color.Unspecified, + primaryHover = Color.Unspecified, + primaryDisabled = Color.Unspecified, + primary2 = Color.Unspecified, + secondary = Color.Unspecified, + secondaryHover = Color.Unspecified, + secondaryDisabled = Color.Unspecified, + danger = Color.Unspecified, + dangerHover = Color.Unspecified, + dangerDisabled = Color.Unspecified, + warning = Color.Unspecified, + warningHover = Color.Unspecified, + warningDisabled = Color.Unspecified, + ) +} + +val lightColors = BisqColors( + dark1 = Color(0xFFFFFFFF), + dark2 = Color(0xFFF8F8F8), + dark3 = Color(0xFFF4F4F4), + dark4 = Color(0xFFF0F0F0), + dark5 = Color(0xFFEFEFEF), + light1 = Color(0xFF1D1D1D), + light2 = Color(0xFF212121), + light3 = Color(0xFF262626), + light4 = Color(0xFF282828), + light5 = Color(0xFF333333), + grey1 = Color(0xFF999999), + grey2 = Color(0xFF747474), + grey3 = Color(0xFF6B6B6B), + grey4 = Color(0xFF515151), + grey5 = Color(0xFF4F4F4F), + primary = Color(0xFF25B135), + primaryHover = Color(0xFF56C262), + primaryDisabled = Color(0x6625B135), + primary2 = Color(0xFF0A2F0F), + secondary = Color(0xFF2F2F2F), + secondaryHover = Color(0xFF525252), + secondaryDisabled = Color(0x662F2F2F), + danger = Color(0xFFDB0000), + dangerHover = Color(0xFFAC2B2B), + dangerDisabled = Color(0x66DB0000), + warning = Color(0xFFFF9823), + warningHover = Color(0xFFFFAC4E), + warningDisabled = Color(0xB3FF9823), +) + +val darkColors = BisqColors( + dark1 = Color(0xFF1D1D1D), + dark2 = Color(0xFF212121), + dark3 = Color(0xFF262626), + dark4 = Color(0xFF282828), + dark5 = Color(0xFF333333), + light1 = Color(0xFFFFFFFF), + light2 = Color(0xFFF8F8F8), + light3 = Color(0xFFF4F4F4), + light4 = Color(0xFFF0F0F0), + light5 = Color(0xFFEFEFEF), + grey1 = Color(0xFF999999), + grey2 = Color(0xFF747474), + grey3 = Color(0xFF6B6B6B), + grey4 = Color(0xFF515151), + grey5 = Color(0xFF4F4F4F), + primary = Color(0xFF25B135), + primaryHover = Color(0xFF56C262), + primaryDisabled = Color(0x6625B135), + primary2 = Color(0xFF0A2F0F), + secondary = Color(0xFF2F2F2F), + secondaryHover = Color(0xFF525252), + secondaryDisabled = Color(0x662F2F2F), + danger = Color(0xFFDB0000), + dangerHover = Color(0xFFAC2B2B), + dangerDisabled = Color(0x66DB0000), + warning = Color(0xFFFF9823), + warningHover = Color(0xFFFFAC4E), + warningDisabled = Color(0xB3FF9823), +) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqTheme.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqTheme.kt new file mode 100755 index 00000000..ae567cc3 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqTheme.kt @@ -0,0 +1,30 @@ +package network.bisq.mobile.presentation.ui.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider + +@Composable +fun BisqTheme( + darkTheme: Boolean = true, + content: @Composable () -> Unit +) { + + val extendedColors = if (darkTheme) { + darkColors + } else { + lightColors + } + + CompositionLocalProvider(LocalBisqColors provides extendedColors) { + MaterialTheme( + content = content + ) + } +} + +object BisqTheme { + val colors: BisqColors + @Composable + get() = LocalBisqColors.current +} \ No newline at end of file From f841c3235b8c2b51ec6239cd1ae8194037cd9465 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Thu, 7 Nov 2024 11:31:41 +0530 Subject: [PATCH 10/31] Implemented Theme colors, Typography classes across other screens --- .../ui/components/CurrencyProfileCard.kt | 19 +- .../ui/components/MaterialTextField.kt | 19 +- .../presentation/ui/components/TopBar.kt | 10 +- .../ui/components/foundation/BisqText.kt | 366 ++++++++++++++++-- .../ui/navigation/BottomNavigation.kt | 20 +- .../ui/navigation/graph/RootNavGraph.kt | 4 +- .../ui/navigation/graph/TabNavGraph.kt | 7 +- .../ui/screens/CreateProfileScreen.kt | 45 ++- ...{HomeScreen.kt => GettingStartedScreen.kt} | 90 ++--- .../presentation/ui/screens/MyTrades.kt | 7 +- .../ui/screens/OnBoardingScreen.kt | 39 +- .../presentation/ui/screens/SettingsScreen.kt | 7 +- .../presentation/ui/screens/SplashScreen.kt | 25 +- .../ui/screens/TabContainerScreen.kt | 4 +- .../presentation/ui/screens/URLScreen.kt | 116 +++--- .../mobile/presentation/ui/theme/BisqColor.kt | 4 + .../mobile/presentation/ui/theme/Color.kt | 35 -- .../presentation/ui/theme/Typography.kt | 12 - 18 files changed, 536 insertions(+), 293 deletions(-) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/{HomeScreen.kt => GettingStartedScreen.kt} (81%) delete mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt delete mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt index 16ba5628..3c49480e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt @@ -17,8 +17,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage -import network.bisq.mobile.presentation.ui.theme.primaryStandard -import network.bisq.mobile.presentation.ui.theme.secondaryTextColor +import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @@ -39,11 +39,20 @@ fun CurrencyProfileCard(currencyName: String, currencyShort: String, imagePath: ) Spacer(modifier = Modifier.width(8.dp)) Column { - Text(text = currencyName, color = Color.White) + BisqText.baseRegular( + text = currencyName, + color = BisqTheme.colors.light1, + ) Spacer(modifier = Modifier.height(8.dp)) - Text(text = currencyShort, color = secondaryTextColor) + BisqText.baseRegular( + text = currencyShort, + color = BisqTheme.colors.grey2, + ) } } - Text(text = "43 offers", color = primaryStandard) + BisqText.smallRegular( + text = "43 offers", + color = BisqTheme.colors.primary, + ) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt index 6cdef2ff..8ee962d0 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import bisqapps.shared.presentation.generated.resources.Res +import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.Font @@ -37,7 +38,7 @@ fun MaterialTextField(text: String,onValueChanged: (String) -> Unit) { .fillMaxWidth() .padding(vertical = 12.dp) .clip(shape = RoundedCornerShape(6.dp)) - .background(color = secondaryStandard) + .background(color = BisqTheme.colors.secondary) ) { TextField( value = text, @@ -49,18 +50,18 @@ fun MaterialTextField(text: String,onValueChanged: (String) -> Unit) { textStyle = TextStyle(fontSize = 22.sp), onValueChange = onValueChanged, colors = TextFieldDefaults.colors( - focusedTextColor = primaryTextColor, - unfocusedTextColor = secondaryHover, - unfocusedIndicatorColor = secondaryStandard, + focusedTextColor = BisqTheme.colors.light3, + unfocusedTextColor = BisqTheme.colors.secondaryHover, + unfocusedIndicatorColor = BisqTheme.colors.secondary, focusedIndicatorColor = Color.Transparent, - focusedContainerColor = secondaryStandard, + focusedContainerColor = BisqTheme.colors.secondary, cursorColor = Color.Blue, - unfocusedContainerColor = secondaryStandard + unfocusedContainerColor = BisqTheme.colors.secondary ), placeholder = { - Text( + BisqText.h5Regular( text = "Choose your nickname", - fontSize = 16.sp + color = BisqTheme.colors.secondaryHover, ) } ) @@ -70,7 +71,7 @@ fun MaterialTextField(text: String,onValueChanged: (String) -> Unit) { .fillMaxWidth() .height(2.dp) .align(Alignment.BottomCenter) - .background(primaryStandard) + .background(BisqTheme.colors.primary) ) } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt index e09c359f..102b390c 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt @@ -19,7 +19,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage -import network.bisq.mobile.presentation.ui.theme.backgroundColor +import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalMaterial3Api::class, ExperimentalResourceApi::class) @@ -28,7 +29,7 @@ fun TopBar(title: String = "",isHome:Boolean = false) { TopAppBar( modifier = Modifier.padding(horizontal = 16.dp).padding(end = 16.dp), colors = TopAppBarDefaults.topAppBarColors( - containerColor = backgroundColor, + containerColor = BisqTheme.colors.backgroundColor, ), title = { if (isHome) { @@ -38,7 +39,10 @@ fun TopBar(title: String = "",isHome:Boolean = false) { modifier = Modifier.height(34.dp).width(100.dp), ) } else { - Text(title, color = Color.White) + BisqText.h4Medium( + text = title, + color = BisqTheme.colors.light1, + ) } }, actions = { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt index 81e2548f..1c8f2c34 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt @@ -2,10 +2,12 @@ package network.bisq.mobile.presentation.ui.components.foundation import androidx.compose.runtime.Composable import androidx.compose.material3.Text +import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.sp import org.jetbrains.compose.resources.Font import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.TextUnit import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_thin @@ -42,6 +44,8 @@ object BisqText { color: Color = BisqTheme.colors.light1, fontSize: FontSize = FontSize.BASE, fontWeight: FontWeight = FontWeight.REGULAR, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, ) { val fontFamily = when(fontWeight) { @@ -56,415 +60,697 @@ object BisqText { color = color, fontSize = fontSize.size, fontFamily = fontFamily, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun xsmallLight(text: String, color: Color = BisqTheme.colors.light1) { + fun xsmallLight( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun xsmallRegular(text: String, color: Color = BisqTheme.colors.light1) { + fun xsmallRegular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun xsmallMedium(text: String, color: Color = BisqTheme.colors.light1) { + fun xsmallMedium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun xsmallBold(text: String, color: Color = BisqTheme.colors.light1) { + fun xsmallBold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun smallLight(text: String, color: Color = BisqTheme.colors.light1) { + fun smallLight( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun smallRegular(text: String, color: Color = BisqTheme.colors.light1) { + fun smallRegular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun smallMedium(text: String, color: Color = BisqTheme.colors.light1) { + fun smallMedium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun smallBold(text: String, color: Color = BisqTheme.colors.light1) { + fun smallBold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun baseLight(text: String, color: Color = BisqTheme.colors.light1) { + fun baseLight( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun baseRegular(text: String, color: Color = BisqTheme.colors.light1) { + fun baseRegular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun baseMedium(text: String, color: Color = BisqTheme.colors.light1) { + fun baseMedium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun baseBold(text: String, color: Color = BisqTheme.colors.light1) { + fun baseBold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun largeLight(text: String, color: Color = BisqTheme.colors.light1) { + fun largeLight( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun largeRegular(text: String, color: Color = BisqTheme.colors.light1) { + fun largeRegular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun largeMedium(text: String, color: Color = BisqTheme.colors.light1) { + fun largeMedium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun largeBold(text: String, color: Color = BisqTheme.colors.light1) { + fun largeBold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h6Light(text: String, color: Color = BisqTheme.colors.light1) { + fun h6Light( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H6, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h6Regular(text: String, color: Color = BisqTheme.colors.light1) { + fun h6Regular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H6, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h6Medium(text: String, color: Color = BisqTheme.colors.light1) { + fun h6Medium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H6, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h6Bold(text: String, color: Color = BisqTheme.colors.light1) { + fun h6Bold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H6, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h5Light(text: String, color: Color = BisqTheme.colors.light1) { + fun h5Light( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H5, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h5Regular(text: String, color: Color = BisqTheme.colors.light1) { + fun h5Regular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H5, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h5Medium(text: String, color: Color = BisqTheme.colors.light1) { + fun h5Medium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H5, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h5Bold(text: String, color: Color = BisqTheme.colors.light1) { + fun h5Bold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H5, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h4Light(text: String, color: Color = BisqTheme.colors.light1) { + fun h4Light( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H4, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h4Regular(text: String, color: Color = BisqTheme.colors.light1) { + fun h4Regular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H4, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h4Medium(text: String, color: Color = BisqTheme.colors.light1) { + fun h4Medium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H4, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h4Bold(text: String, color: Color = BisqTheme.colors.light1) { + fun h4Bold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H4, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h3Light(text: String, color: Color = BisqTheme.colors.light1) { + fun h3Light( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H3, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h3Regular(text: String, color: Color = BisqTheme.colors.light1) { + fun h3Regular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H3, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h3Medium(text: String, color: Color = BisqTheme.colors.light1) { + fun h3Medium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H3, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h3Bold(text: String, color: Color = BisqTheme.colors.light1) { + fun h3Bold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H3, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h2Light(text: String, color: Color = BisqTheme.colors.light1) { + fun h2Light( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H2, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h2Regular(text: String, color: Color = BisqTheme.colors.light1) { + fun h2Regular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H2, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h2Medium(text: String, color: Color = BisqTheme.colors.light1) { + fun h2Medium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H2, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h2Bold(text: String, color: Color = BisqTheme.colors.light1) { + fun h2Bold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H2, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h1Light(text: String, color: Color = BisqTheme.colors.light1) { + fun h1Light( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H1, fontWeight = FontWeight.LIGHT, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h1Regular(text: String, color: Color = BisqTheme.colors.light1) { + fun h1Regular( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H1, fontWeight = FontWeight.REGULAR, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h1Medium(text: String, color: Color = BisqTheme.colors.light1) { + fun h1Medium( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H1, fontWeight = FontWeight.MEDIUM, color=color, + textAlign = textAlign, + modifier = modifier, ) } @Composable - fun h1Bold(text: String, color: Color = BisqTheme.colors.light1) { + fun h1Bold( + text: String, + color: Color = BisqTheme.colors.light1, + textAlign: TextAlign = TextAlign.Start, + modifier: Modifier = Modifier, + ) { styledText( text = text, fontSize = FontSize.H1, fontWeight = FontWeight.BOLD, color=color, + textAlign = textAlign, + modifier = modifier, ) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt index ec584235..033fa18b 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt @@ -15,10 +15,9 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage +import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.model.BottomNavigationItem -import network.bisq.mobile.presentation.ui.theme.backgroundColor -import network.bisq.mobile.presentation.ui.theme.primaryGreenColor -import network.bisq.mobile.presentation.ui.theme.primaryStandard +import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @@ -30,14 +29,14 @@ fun BottomNavigation( ) { NavigationBar( - containerColor = backgroundColor + containerColor = BisqTheme.colors.backgroundColor ) { items.forEach { navigationItem -> NavigationBarItem( colors = NavigationBarItemColors( - selectedIndicatorColor = backgroundColor, - selectedIconColor = primaryStandard, - selectedTextColor = primaryStandard, + selectedIndicatorColor = BisqTheme.colors.backgroundColor, + selectedIconColor = BisqTheme.colors.primary, + selectedTextColor = BisqTheme.colors.primary, unselectedIconColor = Color.White, unselectedTextColor = Color.White, disabledIconColor = Color.Red, @@ -51,14 +50,13 @@ fun BottomNavigation( model = Res.getUri(navigationItem.icon), contentDescription = null, modifier = Modifier.size(32.dp), - colorFilter = ColorFilter.tint(color = if (navigationItem.route == currentRoute) primaryGreenColor else Color.White ) + colorFilter = ColorFilter.tint(color = if (navigationItem.route == currentRoute) BisqTheme.colors.primary else Color.White ) ) }, label = { - Text( + BisqText.baseRegular( text = navigationItem.title, - fontSize = 14.sp, - color = if (navigationItem.route == currentRoute) primaryGreenColor else Color.White + color = if (navigationItem.route == currentRoute) BisqTheme.colors.primary else BisqTheme.colors.light1, ) } ) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt index a94580b8..525508aa 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt @@ -11,7 +11,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import network.bisq.mobile.presentation.ui.navigation.* import network.bisq.mobile.presentation.ui.screens.* -import network.bisq.mobile.presentation.ui.theme.backgroundColor +import network.bisq.mobile.presentation.ui.theme.BisqTheme @Composable fun RootNavGraph( @@ -20,7 +20,7 @@ fun RootNavGraph( startDestination: String ) { NavHost( - modifier = Modifier.background(color = backgroundColor), + modifier = Modifier.background(color = BisqTheme.colors.backgroundColor), navController = rootNavController, startDestination = startDestination, ) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt index 3d629123..94bd2754 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt @@ -7,10 +7,7 @@ import androidx.navigation.compose.composable import androidx.navigation.navigation import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.Graph -import network.bisq.mobile.presentation.ui.screens.ExchangeScreen -import network.bisq.mobile.presentation.ui.screens.HomeScreen -import network.bisq.mobile.presentation.ui.screens.MyTradesScreen -import network.bisq.mobile.presentation.ui.screens.SettingsScreen +import network.bisq.mobile.presentation.ui.screens.* fun NavGraphBuilder.TabNavGraph( rootNavController: NavHostController, @@ -21,7 +18,7 @@ fun NavGraphBuilder.TabNavGraph( route = Graph.MainScreenGraph ) { composable(route = Routes.TabHome.name) { - HomeScreen(rootNavController = rootNavController, innerPadding = innerPadding) + GettingStartedScreen(rootNavController = rootNavController, innerPadding = innerPadding) } composable(route = Routes.TabExchange.name) { ExchangeScreen(rootNavController = rootNavController, innerPadding = innerPadding) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt index a10d831c..8e5e9bb3 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt @@ -22,6 +22,7 @@ import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage import network.bisq.mobile.components.MaterialTextField +import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi @@ -35,7 +36,7 @@ fun CreateProfileScreen( ) { textState = remember { mutableStateOf("") } Scaffold( - containerColor = backgroundColor, + containerColor = BisqTheme.colors.backgroundColor, ) { innerPadding -> Column( verticalArrangement = Arrangement.SpaceBetween, @@ -52,25 +53,25 @@ fun CreateProfileScreen( modifier = Modifier.height(62.dp).width(200.dp), ) Spacer(modifier = Modifier.height(32.dp)) - Text( + BisqText.h1Light( text = "Create your profile", - fontSize = 36.sp, - color = grey1 + color = BisqTheme.colors.grey1, ) Spacer(modifier = Modifier.height(12.dp)) - Text( + BisqText.largeRegular( text = "Your public profile consists of a nickname (picked by you) and bot icon (generated cryptographically)", - color = grey2, - fontSize = 16.sp, + color = BisqTheme.colors.grey3, modifier = Modifier.padding(horizontal = 24.dp), textAlign = TextAlign.Center, ) Spacer(modifier = Modifier.height(40.dp)) Column(modifier = Modifier.padding(horizontal = 54.dp)) { - Text(text = "Profile nickname", color = White2) + BisqText.h6Regular( + text = "Profile nickname", + color = BisqTheme.colors.light2, + ) MaterialTextField(textState.value, onValueChanged = { textState.value = it }) } - Spacer(modifier = Modifier.height(36.dp)) AsyncImage( model = Res.getUri("drawable/bot_image.svg"), @@ -78,22 +79,22 @@ fun CreateProfileScreen( modifier = Modifier.size(120.dp), ) Spacer(modifier = Modifier.height(32.dp)) - Text( + BisqText.largeRegular( text = "Sleepily-Distracted-Zyophyte-257", - fontSize = 18.sp, - color = Color.White + color = BisqTheme.colors.light1, ) Spacer(modifier = Modifier.height(12.dp)) - Text( + BisqText.largeRegular( text = "BOT ID", - fontSize = 18.sp, - color = grey2 + color = BisqTheme.colors.grey2, ) Spacer(modifier = Modifier.height(38.dp)) - Text( + BisqText.baseMedium( + text = "Generate new bot icon", + color = BisqTheme.colors.light1, modifier = Modifier .clip(shape = RoundedCornerShape(8.dp)) - .background(color = Black5) + .background(color = BisqTheme.colors.dark5) .clickable( indication = null, interactionSource = remember { @@ -101,14 +102,14 @@ fun CreateProfileScreen( }, onClick = {}) .padding(horizontal = 64.dp, vertical = 12.dp), - text = "Generate new bot icon", - color = Color.White, ) Spacer(modifier = Modifier.height(40.dp)) - Text( + BisqText.largeMedium( + text = "Next", + color = BisqTheme.colors.light1, modifier = Modifier .clip(shape = RoundedCornerShape(8.dp)) - .background(color = if (textState.value.isEmpty()) primaryDisabled else primaryStandard) + .background(color = if (textState.value.isEmpty()) BisqTheme.colors.primaryDisabled else BisqTheme.colors.primary) .clickable( indication = null, interactionSource = remember { @@ -124,8 +125,6 @@ fun CreateProfileScreen( } }) .padding(horizontal = 64.dp, vertical = 12.dp), - text = "Next", - color = if (textState.value.isEmpty()) grey2 else Color.White ) } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt similarity index 81% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt index 90fdd856..3ab1eb43 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/HomeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt @@ -20,6 +20,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -33,24 +34,29 @@ import androidx.compose.ui.unit.sp import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage +import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.presentation.ui.components.TopBar +import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.Font @Composable -fun HomeScreen( +fun GettingStartedScreen( rootNavController: NavController, - innerPadding: PaddingValues + innerPadding: PaddingValues, ) { - val originDirection = LocalLayoutDirection.current Column( - modifier = Modifier.fillMaxSize().padding( - start = innerPadding.calculateStartPadding(originDirection), - end = innerPadding.calculateEndPadding(originDirection), - bottom = innerPadding.calculateBottomPadding(), - ), +// modifier = Modifier.fillMaxSize().padding( +// start = innerPadding.calculateStartPadding(originDirection), +// end = innerPadding.calculateEndPadding(originDirection), +// bottom = innerPadding.calculateBottomPadding(), +// ), + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), ) { + // Should be a child of Scaffold, in TabContainerScreen TopBar(isHome = true) Column( modifier = Modifier.padding(horizontal = 32.dp, vertical = 15.dp) @@ -79,7 +85,6 @@ fun HomeScreen( } } } - WelcomeCard( title = "Get your first BTC", buttonText = "Enter Bisq Easy" @@ -108,18 +113,17 @@ fun WelcomeCard(title: String, buttonText: String) { NeumorphicCard{ Column( modifier = Modifier.shadow( - ambientColor = Color.Blue, spotColor = primaryStandard, + ambientColor = Color.Blue, spotColor = BisqTheme.colors.primary, elevation = 2.dp, shape = RoundedCornerShape(5.dp), - ).clip(shape = RoundedCornerShape(5.dp)).background(color = Black2) + ).clip(shape = RoundedCornerShape(5.dp)).background(color = BisqTheme.colors.dark2) .padding(24.dp), verticalArrangement = Arrangement.spacedBy(32.dp) ) { - Text( + BisqText.h3Regular( text = title, - color = Color.White, - fontSize = 28.sp + color = BisqTheme.colors.light1, ) Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { FeatureCard( @@ -135,16 +139,15 @@ fun WelcomeCard(title: String, buttonText: String) { title = "Security is based on seller’s reputation" ) } - Text( + BisqText.baseMedium( + text = buttonText, + color = BisqTheme.colors.light1, + textAlign = TextAlign.Center, modifier = Modifier .clip(shape = RoundedCornerShape(4.dp)) - .background(color = primaryStandard) + .background(color = BisqTheme.colors.primary) .fillMaxWidth() .padding(vertical = 12.dp), - textAlign = TextAlign.Center, - text = buttonText, - fontSize = 16.sp, - color = Color.White ) } } @@ -156,22 +159,22 @@ fun PriceProfileCard(price: String, priceText: String) { Column( modifier = Modifier .clip(shape = RoundedCornerShape(4.dp)) - .background(color = Black3) + .background(color = BisqTheme.colors.dark3) .padding(vertical = 12.dp).fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { - Text( - textAlign = TextAlign.Center, + BisqText.largeRegular( text = price, - fontSize = 18.sp, - color = Color.White + color = BisqTheme.colors.light1, + textAlign = TextAlign.Center, ) + Spacer(modifier = Modifier.height(18.dp)) - Text( - textAlign = TextAlign.Center, + + BisqText.smallRegular( text = priceText, - fontSize = 14.sp, - color = grey1 + color = BisqTheme.colors.grey1, + textAlign = TextAlign.Center, ) } } @@ -186,11 +189,11 @@ fun FeatureCard(imagePath: String, title: String) { modifier = Modifier.size(20.dp) ) Spacer(modifier = Modifier.width(9.dp)) - Text( + BisqText.baseRegular( text = title, - color = Color.White, - fontSize = 16.sp + color = BisqTheme.colors.light1, ) + } } @@ -199,7 +202,7 @@ fun FeatureCard(imagePath: String, title: String) { fun InstructionCard(imagePath: String, title: String, description: String, buttonText: String) { Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.clip(shape = RoundedCornerShape(8.dp)).background(color = Black3) + modifier = Modifier.clip(shape = RoundedCornerShape(8.dp)).background(color = BisqTheme.colors.dark3) .padding(vertical = 18.dp, horizontal = 12.dp), verticalArrangement = Arrangement.spacedBy(18.dp) ) { @@ -208,25 +211,22 @@ fun InstructionCard(imagePath: String, title: String, description: String, butto contentDescription = null, modifier = Modifier.size(50.dp) ) - Text( + BisqText.baseRegular( text = title, - fontSize = 16.sp, - color = Color.White + color = BisqTheme.colors.light1, ) - Text( + BisqText.smallRegular( text = description, - fontSize = 14.sp, + color = BisqTheme.colors.grey3, textAlign = TextAlign.Center, - color = grey3 ) - Text( + BisqText.xsmallRegular( + text = buttonText, + color = BisqTheme.colors.light1, modifier = Modifier .clip(shape = RoundedCornerShape(4.dp)) - .background(color = Black5) + .background(color = BisqTheme.colors.dark5) .padding(horizontal = 18.dp, vertical = 6.dp), - text = buttonText, - fontSize = 12.sp, - color = Color.White ) } } @@ -239,7 +239,7 @@ fun NeumorphicCard( Box( modifier = modifier - .shadow(elevation = 8.dp, shape = RoundedCornerShape(5.dp), spotColor = primaryStandard) + .shadow(elevation = 8.dp, shape = RoundedCornerShape(5.dp), spotColor = BisqTheme.colors.primary) .padding(2.dp) ) { content() diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt index 712b674b..c6230eb8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt @@ -12,6 +12,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.sp import androidx.navigation.NavController +import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @@ -25,10 +27,9 @@ fun MyTradesScreen(rootNavController: NavController, .padding(innerPadding), // Applies the inner padding if necessary contentAlignment = Alignment.Center // Centers the content within the Box ) { - Text( + BisqText.h2Regular( text = "My Trades", - fontSize = 32.sp, // Increases font size - color = Color.White // Sets font color to white + color = BisqTheme.colors.light1, ) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt index a95859e2..953ed9e4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -41,13 +41,10 @@ import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage import kotlinx.coroutines.launch +import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.model.OnBoardingPage import network.bisq.mobile.presentation.ui.navigation.Routes -import network.bisq.mobile.presentation.ui.theme.backgroundColor -import network.bisq.mobile.presentation.ui.theme.grey1 -import network.bisq.mobile.presentation.ui.theme.grey2 -import network.bisq.mobile.presentation.ui.theme.primaryStandard -import network.bisq.mobile.presentation.ui.theme.secondaryColor +import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.Font @@ -75,7 +72,7 @@ private lateinit var pagerState: PagerState @Composable fun OnBoardingScreen(rootNavController: NavController) { Scaffold( - containerColor = backgroundColor, + containerColor = BisqTheme.colors.backgroundColor, ) { innerPadding -> Column( verticalArrangement = Arrangement.SpaceBetween, @@ -92,10 +89,9 @@ fun OnBoardingScreen(rootNavController: NavController) { modifier = Modifier.height(62.dp).width(200.dp), ) Spacer(modifier = Modifier.height(32.dp)) - Text( + BisqText.h1Light( text = "Welcome to Bisq", - fontSize = 32.sp, - color = grey1 + color = BisqTheme.colors.grey1, ) } @@ -103,10 +99,12 @@ fun OnBoardingScreen(rootNavController: NavController) { Column { val coroutineScope = rememberCoroutineScope() - Text( + BisqText.largeMedium( + text = if (pagerState.currentPage == 2) "Create profile" else "Next", + color = BisqTheme.colors.light1, modifier = Modifier .clip(shape = RoundedCornerShape(8.dp)) - .background(color = primaryStandard) + .background(color = BisqTheme.colors.primary) .clickable( indication = null, interactionSource = remember { @@ -127,10 +125,7 @@ fun OnBoardingScreen(rootNavController: NavController) { }) .padding(horizontal = 64.dp, vertical = 12.dp), - text = if (pagerState.currentPage == 2) "Create profile" else "Next", - color = Color.White, ) - } } } @@ -189,7 +184,7 @@ fun BannerItem( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxWidth() - .background(color = secondaryColor) + .background(color = BisqTheme.colors.dark3) .padding(vertical = 56.dp) ) { @@ -202,16 +197,14 @@ fun BannerItem( Column( horizontalAlignment = Alignment.CenterHorizontally ) { - Text( + BisqText.h4Regular( text = title, - color = Color.White, - fontSize = 22.sp, + color = BisqTheme.colors.light1, ) Spacer(modifier = Modifier.height(24.dp)) - Text( + BisqText.largeRegular( text = desc, - color = grey2, - fontSize = 14.sp, + color = BisqTheme.colors.grey2, modifier = Modifier.padding(horizontal = 16.dp), textAlign = TextAlign.Center, ) @@ -233,7 +226,7 @@ fun LineIndicator(pagerState: PagerState) { modifier = Modifier .size(width = 76.dp, height = 2.dp) .background( - color = grey2, + color = BisqTheme.colors.grey2, ) ) } @@ -246,7 +239,7 @@ fun LineIndicator(pagerState: PagerState) { ) .size(width = 76.dp, height = 3.dp) .background( - color = primaryStandard, + color = BisqTheme.colors.primary, shape = RoundedCornerShape(4.dp), ) ) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt index 4fb26f05..cb570319 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt @@ -12,6 +12,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.sp import androidx.navigation.NavController +import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @@ -25,10 +27,9 @@ fun SettingsScreen(rootNavController: NavController, .padding(innerPadding), // Applies the inner padding if necessary contentAlignment = Alignment.Center // Centers the content within the Box ) { - Text( + BisqText.h2Regular( text = "Settings", - fontSize = 32.sp, // Increases font size - color = Color.White // Sets font color to white + color = BisqTheme.colors.light1, ) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 6cc89e15..71c16449 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -20,10 +20,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.navigation.NavController -import network.bisq.mobile.presentation.ui.theme.backgroundColor -import network.bisq.mobile.presentation.ui.theme.grey2 -import network.bisq.mobile.presentation.ui.theme.primaryStandard -import network.bisq.mobile.presentation.ui.theme.secondaryHover import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.ExperimentalResourceApi @@ -33,20 +29,22 @@ import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.navigation.Routes import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.bisq_logo +import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.theme.* @OptIn(ExperimentalResourceApi::class) @Composable fun SplashScreen(rootNavController: NavController, innerPadding: PaddingValues) { Scaffold( - containerColor = backgroundColor, + containerColor = BisqTheme.colors.backgroundColor, ) { Column( verticalArrangement = Arrangement.SpaceBetween, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxSize() - .background(color = backgroundColor) + .background(color = BisqTheme.colors.backgroundColor) .padding(top = 48.dp, bottom = 30.dp) ) { Image(painterResource(Res.drawable.bisq_logo), "Bisq Logo") @@ -72,9 +70,11 @@ fun LoadingProgress(navController: NavController) { } } + val grey2Color = BisqTheme.colors.grey2 + LinearProgressIndicator( - trackColor = grey2, - color = primaryStandard, + trackColor = BisqTheme.colors.grey2, + color = BisqTheme.colors.primary, progress = { currentProgress }, gapSize = 0.dp, modifier = Modifier @@ -86,16 +86,17 @@ fun LoadingProgress(navController: NavController) { drawStopIndicator( drawScope = this, stopSize = 0.dp, - color = grey2, + color = grey2Color, strokeCap = ProgressIndicatorDefaults.LinearStrokeCap ) } ) - Text( + + BisqText.smallRegular( text = "Connecting to Tor Network...", - color = secondaryHover, + color = BisqTheme.colors.secondaryHover, textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt index 3ddf4798..ca295f47 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt @@ -13,7 +13,7 @@ import network.bisq.mobile.presentation.ui.navigation.BottomNavigation import network.bisq.mobile.presentation.ui.navigation.Graph import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph -import network.bisq.mobile.presentation.ui.theme.secondaryColor +import network.bisq.mobile.presentation.ui.theme.BisqTheme val navigationListItem = listOf( BottomNavigationItem("Home", Routes.TabHome.name, "drawable/home.svg"), @@ -34,7 +34,7 @@ fun TabContainerScreen( rootNavController: NavController) { } Scaffold( - containerColor = secondaryColor, + containerColor = BisqTheme.colors.dark3, bottomBar = { BottomNavigation( items = navigationListItem, diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt index cacf6ec6..b58c05ee 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt @@ -38,6 +38,7 @@ import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage import network.bisq.mobile.components.MaterialTextField +import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi @@ -52,7 +53,7 @@ fun URLScreen( textState = remember { mutableStateOf("") } val isConnected by remember { mutableStateOf(false) } Scaffold( - containerColor = backgroundColor, + containerColor = BisqTheme.colors.backgroundColor, ) { innerPadding -> Column( verticalArrangement = Arrangement.SpaceBetween, @@ -75,10 +76,9 @@ fun URLScreen( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text( + BisqText.h3Regular( text = "Bisq URL", - fontSize = 28.sp, - color = Color.White + color = BisqTheme.colors.light1, ) AsyncImage( model = Res.getUri("drawable/question_mark.svg"), @@ -96,7 +96,7 @@ fun URLScreen( Row( modifier = Modifier .clip(shape = RoundedCornerShape(8.dp)) - .background(color = Black5) + .background(color = BisqTheme.colors.dark5) .padding(horizontal = 46.dp, vertical = 12.dp) ) { @@ -106,16 +106,15 @@ fun URLScreen( modifier = Modifier.size(20.dp), ) Spacer(modifier = Modifier.width(10.dp)) - Text( + BisqText.baseMedium( text = "Paste", - fontSize = 16.sp, - color = Color.White + color = BisqTheme.colors.light1, ) } Row( modifier = Modifier .clip(shape = RoundedCornerShape(8.dp)) - .background(color = primaryStandard) + .background(color = BisqTheme.colors.primary) .padding(horizontal = 46.dp, vertical = 12.dp) ) { AsyncImage( @@ -124,32 +123,29 @@ fun URLScreen( modifier = Modifier.size(20.dp), ) Spacer(modifier = Modifier.width(10.dp)) - Text( + BisqText.baseMedium( text = "Scan", - fontSize = 16.sp, - color = Color.White + color = BisqTheme.colors.light1, ) } } Spacer(modifier = Modifier.height(36.dp)) - Text( + BisqText.largeRegular( text = "STATUS", - fontSize = 18.sp, - color = grey2 + color = BisqTheme.colors.grey2, ) Spacer(modifier = Modifier.height(12.dp)) Row(verticalAlignment = Alignment.CenterVertically) { - Text( + BisqText.h5Regular( text = if(isConnected) "Connected" else "Not Connected", - fontSize = 22.sp, - color = Color.White + color = BisqTheme.colors.light1, ) Spacer(modifier = Modifier.width(12.dp)) - Text( + BisqText.baseRegular( text = "", modifier = Modifier.clip( RoundedCornerShape(5.dp) - ).background(color =if(isConnected) primaryStandard else Danger1).size(10.dp), + ).background(color =if(isConnected) BisqTheme.colors.primary else BisqTheme.colors.danger).size(10.dp), ) } @@ -162,10 +158,12 @@ fun URLScreen( if (!visible) { - Text( + BisqText.baseMedium( + text = "Test Connection", + color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, modifier = Modifier .clip(shape = RoundedCornerShape(8.dp)) - .background(color = if (textState.value.isEmpty()) primaryDisabled else primaryStandard) + .background(color = if (textState.value.isEmpty()) BisqTheme.colors.primaryDisabled else BisqTheme.colors.primary) .clickable( indication = null, interactionSource = remember { @@ -175,8 +173,6 @@ fun URLScreen( visible = !visible }) .padding(horizontal = 32.dp, vertical = 12.dp), - text = "Test Connection", - color = if (textState.value.isEmpty()) grey2 else Color.White, ) } else { Row (modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)){ @@ -184,22 +180,22 @@ fun URLScreen( visible = visible, enter = slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(700)), ) { - Text( - modifier = Modifier - - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = Black5) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - - }) - .padding(horizontal = 32.dp, vertical = 12.dp), - text = "Test Connection", - color = if (textState.value.isEmpty()) grey2 else Color.White, + BisqText.baseMedium( + text = "Test Connection", + color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, + modifier = Modifier + + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = BisqTheme.colors.dark5) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + + }) + .padding(horizontal = 32.dp, vertical = 12.dp), ) } Spacer(modifier = Modifier.width(20.dp)) @@ -208,27 +204,27 @@ fun URLScreen( enter = fadeIn(animationSpec = tween(300)), ) { - Text( - modifier = Modifier - .fillMaxWidth() - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = primaryStandard) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - rootNavController.navigate(Routes.TabContainer.name) { - popUpTo(Routes.BisqUrl.name) { - inclusive = true + BisqText.baseMedium( + text = "Next", + color = BisqTheme.colors.light1, + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .clip(shape = RoundedCornerShape(8.dp)) + .background(color = BisqTheme.colors.primary) + .clickable( + indication = null, + interactionSource = remember { + MutableInteractionSource() + }, + onClick = { + rootNavController.navigate(Routes.TabContainer.name) { + popUpTo(Routes.BisqUrl.name) { + inclusive = true + } } - } - }) - .padding(horizontal = 32.dp, vertical = 12.dp), - text = "Next", - textAlign = TextAlign.Center, - color = Color.White, + }) + .padding(horizontal = 32.dp, vertical = 12.dp), ) } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt index 2fd77d94..e4fb14de 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/BisqColor.kt @@ -34,6 +34,7 @@ data class BisqColors ( val warning: Color, val warningHover: Color, val warningDisabled: Color, + val backgroundColor: Color, ) @@ -67,6 +68,7 @@ val LocalBisqColors = staticCompositionLocalOf { warning = Color.Unspecified, warningHover = Color.Unspecified, warningDisabled = Color.Unspecified, + backgroundColor = Color.Unspecified, ) } @@ -99,6 +101,7 @@ val lightColors = BisqColors( warning = Color(0xFFFF9823), warningHover = Color(0xFFFFAC4E), warningDisabled = Color(0xB3FF9823), + backgroundColor = Color(0xFF1C1C1C), ) val darkColors = BisqColors( @@ -130,4 +133,5 @@ val darkColors = BisqColors( warning = Color(0xFFFF9823), warningHover = Color(0xFFFFAC4E), warningDisabled = Color(0xB3FF9823), + backgroundColor = Color(0xFF1C1C1C), ) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt deleted file mode 100644 index d6097dff..00000000 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Color.kt +++ /dev/null @@ -1,35 +0,0 @@ -package network.bisq.mobile.presentation.ui.theme - -import androidx.compose.ui.graphics.Color - -//Branding -val backgroundColor = Color(0xFF1C1C1C) -val primaryStandard = Color(0xFF25B135) -val primaryHover = Color(0x56C262) -val primaryDisabled = Color(0x6425B135) -val secondaryStandard = Color(0xFF2F2F2F) -val secondaryHover = Color(0xFF525252) -val secondaryDisabled = Color(0x642F2F2F) -val grey1 = Color(0xFF999999) -val grey2 = Color(0xFF747474) -val grey3 = Color(0xFF6B6B6B) -val White2 = Color(0xFFF8F8F8) -val Black5 = Color(0xFF333333) -val Black3 = Color(0xFF282828) -val Black2 = Color(0xFF212121) -val Danger1 = Color(0xFFDB0000) - - - - -val primaryColor = Color(0xFF262626) -val primaryTextColor = Color(0xFFF4F4F4) -val secondaryTextColor = Color(0xFF474747) -val progressColor = Color(0xFF707070) -val primaryGreenColor = Color(0xFF25B135) -val paragraphColor = Color(0xFF777777) -val secondaryColor = Color(0xFF2B2B2B) -val indicatorTrackColor = Color(0xFF2F2F2F) -val nextStepColor = Color(0xFF767676) -val smallTextColor = Color(0xFFCBCBCB) -val progressSecondaryColor = Color(0xFF303030) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt deleted file mode 100644 index 1d6fcb25..00000000 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/Typography.kt +++ /dev/null @@ -1,12 +0,0 @@ -package network.bisq.mobile.presentation.ui.theme - -import androidx.compose.material3.Typography -import androidx.compose.ui.text.font.FontFamily - -val ibmPlexSansFontFamily = FontFamily( - -) - -val Typography = Typography( - -) \ No newline at end of file From a8df92de3f44654cf644185cefa6a03e7c90bcbe Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Thu, 7 Nov 2024 17:11:06 +0530 Subject: [PATCH 11/31] Components: Layout, Button, Logo; Font adjustments in inital setup screens --- .../composeResources/drawable/icon_copy.svg | 3 + .../composeResources/drawable/icon_qr.svg | 12 + .../drawable/icon_question_mark.svg | 3 + .../drawable/img_bisq_Easy.png | Bin 0 -> 21782 bytes .../drawable/img_bot_image.png | Bin 0 -> 24006 bytes .../drawable/img_fiat_btc.png | Bin 0 -> 24594 bytes .../drawable/img_learn_and_discover.png | Bin 0 -> 15557 bytes .../ui/components/atoms/Button.kt | 50 ++++ .../ui/components/atoms/ProgressBar.kt | 39 +++ .../{foundation/BisqText.kt => atoms/Text.kt} | 20 +- .../ui/components/atoms/icons/Logo.kt | 12 + .../ui/components/layout/ScrollLayout.kt | 34 +++ .../ui/components/layout/StaticLayout.kt | 32 ++ .../mobile/presentation/ui/model/model.kt | 4 +- .../ui/screens/CreateProfileScreen.kt | 164 ++++------ .../ui/screens/GettingStartedScreen.kt | 53 ++-- .../ui/screens/OnBoardingScreen.kt | 127 +++----- .../presentation/ui/screens/SplashScreen.kt | 60 +--- .../presentation/ui/screens/URLScreen.kt | 279 +++++++----------- 19 files changed, 440 insertions(+), 452 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_copy.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_qr.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_bisq_Easy.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_bot_image.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_fiat_btc.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_learn_and_discover.png create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/{foundation/BisqText.kt => atoms/Text.kt} (99%) create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_copy.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_copy.svg new file mode 100644 index 00000000..8824cb83 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_qr.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_qr.svg new file mode 100644 index 00000000..d2d0bca8 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_qr.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg new file mode 100644 index 00000000..e68697a1 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg @@ -0,0 +1,3 @@ + + + diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_bisq_Easy.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_bisq_Easy.png new file mode 100644 index 0000000000000000000000000000000000000000..88ba938a802c4e28e32711e50c8ee561191dd282 GIT binary patch literal 21782 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 M1x@)%S?jR>0+ksAGynhq literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_bot_image.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_bot_image.png new file mode 100644 index 0000000000000000000000000000000000000000..4f39c56b2a50415f91639aeb5f22fcf44bfcc62e GIT binary patch literal 24006 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 literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_fiat_btc.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_fiat_btc.png new file mode 100644 index 0000000000000000000000000000000000000000..067f96932561477f8d5feb6689e85098c1dfa6b8 GIT binary patch literal 24594 zcmb5V<98;!7w=u$HmA02+qT_awcDv}durQuJ9VdauiCcH{d=Bu{($phXD4}+WUZ`Z z=es|NQdX2ggu{aa0Rcgjkrr3|&u{(DV4(gh@pb2d{&TPZX&qM(5G;!S8K{ivuiO7R zL0wg)L_z9i3C{j&Kv;<=h=71JCcuB1K!Si6mCJ~WsC$84^}_pUoVZhUt+c-go}5OZ zz?g?LB7mWrn+1bxvZ$r7Bd^8}D%x{RC(|eIT(&1n;?LhBWO#Co;t_Rn%#W)zx4O@CL}VqQINvQT=p|O z^Z4F07wo>T_%akhz@q(Dw4_dS zj8v^BRvvrl>||xl0e$OPmd5RGrF7(_1lArcDk&a)E%&b|)>ql}o_G z0~@B}V6WOrmhvvSoW!HZhk;7(zt@aP&~^ina6DmS%p1VHM$-UND<*_WiC2 zE9VN7+vOPjRbq>qT3kzeh?b9UwGrXeBEinaihz!`k4^Qux$4LF&Yg~T;>|R9rAg5Y zPu3>KkV`YZ;&SK?R&7#eu&q1eNS^9X-bOC1#Ks1q0NAlGoteFrt1ZGAMDb>xjhKXuKoJ6{dkVql=0fG>b1Q0_BQp~{j*h}px7P!V zzVe19JpFpS53b;6IBsj`C~ce5?q{#?fM5LzZ(`2`S4u4z|4sB|pyn6=NxPIaz%Po# zL|RMCraUdo+e-fO&-`05J^GA3lKJ=PT4C#~saQn4?D~CxjpmeS?Ri@9d4myQhn_(C zRO+6k!y`XRCb+1+lc(i7wU;q*{ASVE`Z!cGiT82ZtVg*gSCVFU#l2*K`NgzYV?y|UAYki) zbu8F*-X6!?i<(7nF^c|M({gE_K3j(YIsU_H6B2=A zK0WEeb(37)`_P2a*C`l$`P6!T7=1tThnALLmTmZcD&bv*yBo9acP90nJi+ux@3g>6HM;NMAHw_IEk&pjo%n6N1Fb-^lT%s`^iw%L}4BHFm zN2xKJ{gd%s&;`@kyYFybrL1-49U82*9N&ZLBaHoi@`6;!iT)UHp7)qs6Njj=N<3MeH6%Mr*Q$GTL>!> z4;t%SM=m+^AB3x81eR`xxpjd1y@9v)+etG%_$J~s;RETQ?&(+-y%*o_S}B`w;Di)W zWBhgh+80A()#MXwIc`8(_#3CbKeY{X2XP!GX$maMHl#K-1f`$<(REyX$YxLS16+3% zSUte+qL3&XCewC6zyR>i8!ajBhB95NmYlvzP0-CAyI~Dz6O7kbA+

i z2IO*5m7Tc_{0y15;QFne!)40V3M6IjK;wb|?dVTy`IB4k3>C_9ux~n#Ezzj^1F{wq zVbYPGcvK~=M}dfkCu5iVwM(JV0e7NQiaK{xERGCl{vRro6=(XzjZh+M6Ugf$N@fRX zNT|Ri7&4tmlm0QY8m%C(-=tJw9g2|V8m1X*%Ex^!$ zPUoL{_P+7~?Zpxeyc0RQV|M8U3kPr*{^Aa>o;p0P2C#ltfPvlZA-Mj7RPmHn?LYs! z6APY(wOnXy2v1I`0lH@HxqxYE?Da}sUq8FeSU)Z{NOZ~$W!GK=tezH&L>WA$x#Zl4 zl7*lra4I4JKxiE(847F&T};X=3{sH^2s4{%E+}+V9A&YCil}`@LP#PNoyBd)%Yc>> z&xGhFHAthyEzj`1z`H~_x!Oo~Rhdw6SAvNf*0nLs-31a!;lgu3FSfqLKY>n>xbW0vr3?VN@i zo;Y?{?$!w93O>vMCAT*DMT|t1R>{pU@P{2LA&v}GfnfOeW^L45;mOaQkK`o^*2pS|qs7{_t(B#xTn zsPl-6E@UG=X?FYp7P-=a9;im$NF-h(FN|NC+jqd2?Nno&{}zfAlDdFGj5%fRw|?o= z0qu00X(zvWfqX3_rv@@TfaZGk+sum{Jm?~tTYVZR?8WnW!B^At-vu7$=KDAyghnLk z?~gk!V{v;RA)B+Y=15OaFO!b)RC2zyHrhf(ZC}j!#@=Wjbyb45(xT40Tp4{n;9@9! z+rqkoC;n1N7k18^Rbp1Qin9yAyVwPz@G#yV#kozciK1h642GApY*n#^H}73`M#`SH zrn&|I)exb3*Ze2;(!_m-g$0a){J@V!BM~av( z@bmgn%$D^_l79)D!pLA$2vbz@64n&Kh!>YI%Wsn#wQFG^y1qg33y+j7Iv8vi;xfsD z$oO%JUJk(sE!VtS2jJ04QsKYAAk2oao%tIe$L0WAmRBEn5uo_0qsXlvVU0Yifp_QIRV^9zy!gzk!lhON=Ab*P(27 z`CaWhFTslP>}XrPm`baIu8w0bpz;7T5E6^`vUH$***humrOe~u;@!p~xu;H}-9dzO z7%(8-d_=7OKm!9e>iqVASN}wT6Gh2QE7&A#DQV!lJ zd}@9Uw!@xcho=YRp?n{X4f8yPm z$pc??yGbriu$ZyDBvDyV&B<#1-KaqMtDSZ;f|M^z&O#!)Q24M%{kzYFTGP$lI1*v; z1%x6bm0t%8tHd(7B(4ziT#(|0bR}P-et5T0m?uP0NMqO_D984BgD-Y&(23J-^B%{k zpFw<%Po4Vou~NYK5k9RGU>d>`b|f8cSbb9E$t!V+(P^(w6^BTMC$&@ts^bjBa0|px z*Ce$%(p&H`5|Ly8V+Q2+N6T1&WbG=N>?pf67!ms5s7Ak!Uj9xdZCHyD!6%8f9N<-t ze81bHgJ9od8^$q|^pN4rYJ!W4&@)c4vu6*)Z>9{)wQc6fV$ZzmvCZ(Zvp)gq1CU_(OZ(ZP{EsQ-V~`}_OgensnmW9x z9;k+m_1o%dt$NJ^VL^bmECR<(bUBfyqg=mb+%M*8Da{@_GPS`sry*cYxe0p7-Jd2} zIk8Ui4P=VzCPb;p5iC&_*)8;&Wl1)OF~kSl6dFhofVQ)jBECObS?y@YF=bD&Ug0?7 z0ACLxZv}>_F66-~ncuVa#WiO4O@QX)l&7CdU}~k%cnniq7EqLlLn$JFd~1IBj+_QK z_%tlCvHEtJB$y2*jBGt3rxzyTK`|H=YzU4-GLhHtr?Y5No^G&pUZs3@{0|tbqdjN; z!cW;7iLm_@5K?zh)pMDhOcGk{cT4P6AL%Tl*jsK$)o z*WFSe36&HBl)ubMAl?fpOM!d5s$JuB-CFk^`u*m#+FO6xkv>BepJlKamw`j9VI;H$ zjU?!_T*zwx5!oC?Hd!P(2oty?2#365F}jKkYE5Q8MB^1q+Gj>^3%TiaDw;l(dzYir zDA+0uqsrme#i=Oyjn29@tDnC;IeUX@oKi__l1yp1tk}0nWEoe^X{PD1o)Q~@Re={H zvNL%?0@}I9?QuwLS{nA2&;1jY-w)(8VQWVoM{;89OLv?&2MZY@Q0jqAC>q(-44uG_ zE=Uf+K#&pH(OyIy*0%PKO)%lSB;)8vfEL}ooc6WCq#81FSSRMLu9HI;m5}!oD~uCUbbP5bL9HyNXim9-+mVry>uc32(*P$NEV@<%VOaNr zzh_LSLQVF#+8g}`QG}#3#_ERJ7-dcVVj`2mq3pYZ!`iV{#ubBo6@Ynz=OfHF91QRpO_fH`kfOT`q(hjlO-evFPjmj5f@!|Y&_Wztes9z z?r0_xBmms#LxI^(AVn6CyYDSBVXqP2g~>avG#a~t6aaW{A|7~$=ULDgG0Gg4fLaR_ zRUvNFcDH=n(d_8uR#HJ}7bq`4t|@(`PL+w?XSJf|CHjmHeT!0ZA-?)U%;8(B(2-`S zO`oxc`z6-Y`S%fY9UJ+o-TbT+96!Rh#kzKvi)gS>HCqgUzzp9MX2u&w4O0c;eF@|j z1;ua-Czax_D(WS1)9hy1MOeT3GU|Q9l}%rj6;DXH$?G^FN;!qPS{hSYx$TWw8V|>H z)gtb^W7`G}om>5_XuoJ*QEgIpJbR0v6=onaMH1wla{F^iU5zH-$wo34b!ka%prydFeuf zR=PT4^v7)>x3--r%k9oSxYx6=Xo^$*+;R&<_!cq^XY(X1etM$7{?dN`Nikr~(*1{q zHch-y(C~8s8B)pQFPYucqtHxXM#+tN3?JSj$R9OCJyi?4IJ4V_A3vkscre&su=N)( zEb$i)-0M|>HG|3}_7S67HrT)L?_I*$`;l=am9NE$`keC{%yg#Qr79osh>!#a_gc5l zjXtE$5=EuVxdpaGV zGXMgA(q>iPb=^I^Lv~n=Qb8YC9s83c=N?KMuY{R6Qfo67p8sLPt8<#WMLBHm>^QG> z88P7e)0KI0o_;hF_F8)jquBceif>B4ZR8Hl;E|Y3k)&(n#TpINg*QUvnOBfAzDbeR zm5p-hBGr^B1TIw#zxZrck&{MQyu5XX>FHvGhKD#wCeTaG+1V(0yIb)LTr?MV-qEBG~HAA z@_-l2%$=H1_@*PYz;GZbVjFqwr0UI^9!sCY`QbVJYM#o8V)YQ3Zmo9+^^9B1aK)c@ zuS_i|UoSelu|b`XoK8|)1i2>kVA-cGd$q+?j_^sP@WE=sa+?i@Z7`3Rp7Vm&NEVcy zkU|B|c2K&P5c#yezsqj*#dE1O>Xn_wIgO-c83*_>jM8)nXWD_7d%>CeVcfs(^pH5) z`<5m4V|s`L90|k=^!wGNC}89VOCCL8NhT)WV>xnXh6Gt$GjVXB6C0Y*__d^*_>mHO zfuZQ+`*f8=vBffM-@lK7)iI{fMpB~^7++s*oqO8TTAy9LoEP5&m7{V~Wp)A2iDA2P z>U0B1xh*sNPxeRrTc^=?SgvWLdpCX*Y}y}r(sMU-QloQGu{T-0FvBLDlqMyEWRTsI zAb`6UMRSnSW*q;mfQEHVqA2@Ru)t$|Tb1DN#PmlBJFIdvKcEvq#v$G-kH$_r894Dc zh+q|9tk3JU$R&82kjIQLE9k6GZ@koa1w1(@@cXtMH++j*iHJRPph;o5CrIs9x=@8) zUdH4V`ur}EeJJa8DpR#CCbK_-#!E_P)87emOjdQ<*Zl)KU~ozwfqWw*(JDqg39+>5 z_&W=cyYmW2{MTjlI*w2kMFzK-&`9rghXEQvhsmh1+nqRk2iZ!L1=vWo2Y^MBCm*xF z*KK{dp2;-KVKH+G;s1(^YJvJCAXK<6yXLwVm*DPkZhu$f;%L5M5xTt{G11YdL8%e5xEj{g<(9 ztu61y4(kWu&`rd#lf!!`?64%iuXjJ1F$!+0v_Fmc;xYHE9hKnQrycun5}*SDwhYw_ z*$}A`n|4Hpn!XJUU8+B9I0HH4c0u@v&S6<$i0X!R3BF zzdUoczV5xUTNcCwngieE9p4Nbp-&P&6g%xRqc~g65fg?Z`OrO*^Z}RE@ULyIk&-N; zNdY-DgQUuup%14aZ9kYfQ$(Vvl-qv-k|wW0T7v#_M!uj%{JbIVU5!%N)TJD;XaL@e zHET5dmFZGQ;s-y&HIF| z4C1r$)L|Kx%wvjxG?Vsg&nC&RUgx&o09Fg38~{uV@o&U0;SFd$^8glFj4C|)x=a-X zm)KanI}4q%C4XTqIg_D`&pvXF{@yb?q4aSTIiaZa~PYl|Ad;-lG3>L{gZgFzdN zn#I!rY&F{bkpcuLW@;^R1Pe!9Z6;<3aE$vs$(t!wd#jx9j{A3q(sxjvJO9-IFQQqKrxm}9emP~k&Er#SIB_2(Trnnh z`nsht;kjT&9!s*d?=BOUh|jyMW&sZl*JO7a6dlLDi@)k4c1&40Q?h=80(O~EjU#ljtDr?7Y zrR17EJSlDvEr`07=QL2>7kEu7Ylj79UnaRN_PS?WSJ^fmdkiTkrm#06m8c- zIJCECMi9Z@?*G8}@b7!N02<}fwfTOuc>ngQ-qYqd=jMoPw+DSNK)rNf8g}V9 z>&38m(+|zj?)#4O%t#O%vAfL+Ek{=w9DUYBiF`(16)$5mEQu`QCmJ62Q}cDC^;;RfD5{QiB-Wz{)u-_7w-_FjIAvsfaXc$bMr;1z9QmY#`QnVu4c zC%ApfQ*A-ywM~mGYGt#2_jt2XFoo{&{urK|ROp@a4R975*qUUOA)TZ=V$iWxxXl17 zp*N7CBUkF}%T*@5XyKUHZnzuR&bMwVTHGZ_Ns_r`)kfrc4|9MLwOilK$Txu&hk|q- z3?0oq4;8z3o3|yQ6V!PRKxN}*Ww~C-46Ps~IIU1^`SvLWY5kMPf^%w*6h~$^k^HebjKi+7BddLyk5PVeUGS z!5OhGB{rr>Vt6iFx8fF=ZTh$)1_qPr-#r3pojxV7Q~r&?35nmWR;mUh{5)1^3+lui zpT@rZ`+A}3bX#8tj#rrc2ki~1{Ecp7Q|u<2`>!0*u9FY{DT?9CyJD5zgp?&pdz~D> ztnyo;lPGJ$3r+tGub|k7{!-lF#*7KIAUbdB=(>sn)Cdm|_AbcjLn>ysQoCcd$GtY- z<5B3~B6;9qi>pBjJ)tT%N)3Pv`bv?S&Cil?j^NJi(<|g(h-vrP85%{B=Vu%GpJiaX}<=}+5 zirsE!BgOT7GB?46ZtiJjLkZ*94~&pDrSO$`F;$Ocf3)gm+ckT$ zV|JP+6?`dg3#jH~A_`?_l))Ywh~@`T2=w<~Y?GG?D#RmOha<=z>Gjc>1}1&8J)K?+ zXnGUp&UQ1*3i^xm^Y40g^c6%jo|Z2|h;(81tL{rw3d8%wf-e6e2w%}B6H6;>+Ly8O z%6;7ZCp0NqD3_v=;dW* zC79e4C)=HPxk+ND+OBtd>yT2{4T|6D&^1X#{AL_V$#&(wXf%l3P9)6Ngx>3TS3CWe z!z@cQKJ{BsNeHRdZ?LMr*R!0}WN%IC#i-;Wwy_)1SUu50C6g!juej4w?7S}h`f-X( zR}A|@b*MJYM2G?Q@U7C8Ed$no3dHKyo=3IOptt*e?=0-wCmEC(Dpf*_pJr){kA@ls z1v#nVenb#kZU7qi149ZCZTV3wS%*vG!Zk}7l7Ws!TX$g&({mWj>Yfk7M3Q~M=uEMP zDf-7|ons7Z(x4;BX3ptb1}#O~Gp;oEOT_H(2;0>}<27Md$=Dud>R?3(K9&8#G=Us5@GQsa?|fx&uQMq559nLi+6TkQeas45V{MhcS$Bei+%bhJJvUeqig5sLwBR zhPhXE1FP7);jE=Zq%XmabofR?)uvgqbST7k811-Mu@MNS!Ra^^#;7+A`lig6A1l91 zXH){6U8darVcbK4oY6Nhw>-}24`xXCL7f*7M9x)UiAn`_*3E{5k)fQmptsd@V;N@ak71EGtsv3Wab z4)*QZHH*U+;mT3tp~wW~vxCHfS~53}(<#8BE6z=d!v=IxD)!HW}$uPup6Zvbq z!jAxEPBMEy#i`nh;OHDQPaga`zf)Pm_u9ZgHsEZ; z40=4zUr6V_XD%Y7h?8u@dg{TGUTd6vPXPpz5uDghx2!K>=0D^EMlCbrPbdkf>C{x# zfrfRmagd;Gr;Lq9DXC?uEPKEW$*U%ax85`HF%kE8ZPHQlBDq*M(4I!d0hK!G#8~B1 zFJqhUt~pStjrkI=+tun}GEF=Z0q#6pQ{2KH8le*m9T({(c_h51N~|J#xfjs#I*Dak zbD*m(ahMT92^#OFVUIM*%?c6{!*HaD5R(q1?TP;3zt7t9nKL$>6b<&9`-XQ6cZ5T% z4R7g0O<6kuFbu7m?@tB;mG*NDg6@7|auk&${ik^1^z5pY`ZUi4^wi|vyi7K4FGqqA z6s3Yz2Bny1%@?xYAh`OKVOX<{a4ejR&@2ij-DwJ?O8@FesV=3+TUF%MxJ(zwffAxj z>23k=z}>?LiuJo@#c}tWpj_IPm2B76(9V%!;x)t5f17AaI0Obwtp-0#XIw&D`Yxos zKZP3(CiI0v=MJ{HP_K5K<`QU0wFND*YAi*u;SpEe`bL$~n-CKdG%ZLwlYz(EB9f`} z8I%YPWl*A0GEXK_??@63Ka;LW^B%3yFn#S+3$hca#TRY^QenDml`e)rQZU6sp@iJ< zh7z@CSJ@A?W>Bf(cyb0^Imz&<2O(z}O4SV#vd}r?%TOG)5z9Kez*d0QL_Nh{7*E6z zdr`*+U#+GP9&*azm-vvj@=RldneDbO;d92>U$GcSWT=F3v7kH9@r^f6wIBWZJ5KBE zoO4Q$kf#8^HQrbAvpN4P?F_l9v1FKsNMNWucc@5bz1e1A#1vglzrSZKMNokr6^1kOl9d5mv;$JxAj=RlgZNfPU%D5{)oge%j zd{~ckMsceMuqR~m0@s4<0ItCfU%%nQmGY7(d3^w8@id-{aA@3q1xLId@B4u33J*LP zKcoRH#JEL@r`TuC`Dt~f#f4+TtlJcV6EVAu)2;cI z5dnk;=l50LDYdf`4=TstQAt>;ct+$MMSPk{()xBNy#?K9mi7)XI#~<&8a&gu z8}-64>M31+>)@Ep(0t%BOu&|WX)WAUCST6WR-Q_mEqnJZsHk5m0>s&`sboabx%n=5 zK)h>m-0$69+7ulP1A|1|8X55kXRvd(D7Q64lR|uSf2JiIivl)Ib!&rbAm0@Pmm`u@ zF|n-iVs!uS&G)w{=zV{jX(K2Nx8A<10XD6VD+j)n%`8YuL_ID;p82!bBz;O!VbVWn zDY!)XB(WCcMM{%lZjvrtg7$&9p)Q9bE8zWZt*-Hrwr?F6#m=eCvuoP&Rq3pVUTm1U z1gG>qr5*eo;2s1h>0LNbT`7bwS84?tfuEBHNUngU+^bbdM|{T40TjN8bkI|DJBm7A zlO?umLTc@Pf`@>usnwkeTuK~b$6f!Ijrr3bXmU%z@VLlyw77ezrrLv~kbcF*SZ7!6 z6jwRJ>?XkvY?+Xp1_dkBMLP=1vSP zJ>djuGP`C-oUU|(GK%%3u099BDgcGv3_QUQeKItikhlLPe6by7Sx-f=0?ck6@k0CsL7kE+|GO~ASLq+_DqEL}{FO<$OGf9fAwT^)hC6pd z=N!Mc_t7dF`3)$9hNyye25cr8c}N;UWbk>3OX$4eo*IH{)(wTBc1l>U8_13(U?3Yg z8X+KMa2H2CwOi#yP$fCBNOA6 zQ2Zw;`;n{?%%uNI3LAk4^!e{6i3y3RMIQOC)ED)1Id z|KA4Ef|8qzL-N@RIUgUG%C5j{JS78awxz_;?U!F}0tzR~l3U`M*<0gXaus;|=xzI` z4I(GBlGwC6?BEtU;jcAFbML{G0#7yHYUc{CrhRJ1!jGMP#5cSz)M;yUQdug4L+d$& znJP$OqkBKI>*PIRH(2qn<0b&q$zcvkeAeiG>Gl}Wsd84Y=hRH$NhH-}SEIYs71s=* zz4?0Vr48ozmaGv3<)XD;JGwbIU#z`;3cbW*A+YHB<0~h938ODsR}R|#f~m zv6R0CIq_NB5`IhiW$qT+{l446zsqdjZfg{l5U&ng_a{xzZR7t(@dFxZ^Tb!SZ_v36`t@97}|!wD?%sc<65m z73`c?2m~qrjmeznf#Yw9++xXyy({Httv&9xENG*wCI@*8Ny}3WJ+82~B6q(7JZ{D< zJflUITNQ0oZ^6($pN3j*ZO@d@vY=tjcwX~El4;ZKI8=uA+WS;bo5O&bMf!E!+%**X{u{K*Sg=T81^U<*h<{}&h@Piruqj{|?-7*q+c0?6 zt4Nvld-Xr%JLf;xjv<1@_uKIiKLF84HaZyEX!qGv70m=nc2YD^n1XDq)H7oQ6ZXaIe*KrH(3elzOR_bn>ow%X!v z)A8L6Wk#u^8dtX4+=Ap%Q`hnt*@SbYXk?}A#e^D(1*QE+O1zO)gzO5zF`mz3`wF=T zZa3GoG{w}yeEf5U^l02F1LGSp8wb~G`9q{6rGBW0_b}cCB|_OxTQ(?GM$bzxpQHlL zAA>$I%Xe5E(Tg8Q9VpCqCMEw%Wg!Jp%1bOSrdZ=Cf9G=L55g8qjSH99r#YFUs)}>$ zqv_?y0-gvFp@IGCg)U;r1V4IBS-;ZP&nlBYm70-M|=AR#k>lfRH ze9gF{`N|07^*={c#8Gpdb{R7f)tWZ=F}P4c3w6iy@M%cBQ)C=lh4E?&iWAH67w2g5 zx)SYVH4jj-Spf$bVNR7?s+V(2u22zpgOxvkM@)P@l$D3A8;!Sj(V=ZiqG*w2;|-eY z#JL7GKi%{O2JJw7pMg(Y)EPk}PYOvu!4T$@v&qpS{s#@SKQPkUl}ALe<9Mh-?pR~a zTOs#&T4O~fZgxOgJx&LszVQbSUq$rrWO=?&iDHCP&4hr1)^!I(V}ad77sjy(nDIG_ zV9{5l0YH`@HCJtSLH~ACs~O?tX>oax%t-=vKT_y;2)g}=sRK3LKEJ-6MJT09=dK~T zgLYB1e+*#mIp1R^7o)mTwb|r8JS--@A$>=s$n@6stHgNZC_&y}iYL|xp=&2qbL8a= zSJH{xt|9B_=<(dG>aCS4q;|hM;{KxLCu8}GAi@_jeOpQ*mI8v3lgxT#qspP1v#i=W zm70^BI;e8iOR|K1{+Mn24mgF60Q2#PK{Pa6H=?!TQp!Q%qR^bI3{RyVNUP@@(-|uv zUR~Ik%tRjA_@zSU+!B%W=u=^Np3`(Vps#9!KE%3k1gTGZ4!nX?-k2P}^!)M}SJDWZ zRL4aehKpsiG*RqduE z?VwYsm~!(L>om}P?}Gf~-%N&j47DFd?^Q}i`Rni%`1edq)PI2(>AOGKLt%xj(gY0j zB*a(b(?xY*P!k_rkrG04MuomqTOc8&DM6$X<|cI= z1*$Tx))Sm;*DME(F1TRX&@)0+qEFF(4%C^Q9g<3}jceRvMwzvQa+;hSe0v7}lO%kJ1 z(!Vc&6v4k5afGwt=;)G$Ir@R;t4+)?$*QVuJtLZXGlJM?R}NB+Ceo;7S#_qskbgA) zk0#eJ&qiFY8Y805CU5#{^ zG*80#TLmJ*(+>99WdoZj9m_H+dr5;Qw|I!JwJ|KRB=+4FFd{V8Xyk7=l-Aia3vfn!%f)%L(u7W-{&lanwu)UddU@x zbE9UiksfBMZFaVG=$$36n6OSJUHeT;*N6U=hSt0(Eq)sE>Sl*I3#xbzcd49$-E!74&PgjYfJKYNY-10UMwZq9pv+b*91ly>%BM06 zMBk9nRL(s{*vl2AJYvzmkfO{!mjmsEQW;yQhIH*zssnIKQXIEzW@1s!Xd{TjDdXINAhTdw`WEu zRD{Q8N{}?v>u|TxUDw5wvpXm>P8rgi=4`;D?``?{khj~c`3DSgg@5xj{H=uO?{o-6 z)KpXRoTZAg?vtKb2uo!b`*4@lXAVMT7!YM4rWR{N6SB^k2Q^b6n!TGmhgly=3Q;*y zk^)K0sVe2!kUp(Fi`6ErZ>h=CwU+VdYrgt!ur8RkpYKmPN9l7qq1nFhk>T0cY8xI% zWY<<_8*g8D{^?e3nj}Zc;ClE?avgbz1VEXdcAEWXE76eR=+@qffHQEV@d1;x}{Hy>DJZ@VO5!9AC!`MCHlPz;%cj)5Ya6s{lQRTcFVc_L_ zhwb!#{{j?g8o4DX=FpM;Kc+*MNB^Nc=PFj_+fUC8da{ZgAa7#nVy;MMq_9+}nmxY= zE6?U6^6#6s)YlWE3GsWKDt}5Xm?lJ;c-|%;n?06@Ag%hhke5vhhYJSyE~bGj-(#>@ zM*&!XNaOh`BLZ$EZ9mM3v*g8}g^398lZyzu5Oodri|}x$DV`0%El%2@zN5CjAZSFrE!Cv*^ALzvlv3VIn zx_0jC&MS|PW4~ohp!Uzm^ri9AM+j`tm6x!YZG9cA^PdWE&)MKsanIF7A}U|H!z-_I z$ur+U5e)u#tGSjGjOHRzeMNpbo+|u@R^FBvah}en3*6pbntR}lfZGksrfKJor*I=* z96fAs8)?R$3w__Zo=^{R6h9ePuLc(O52aS!kaz^5&guG@>zU`UaAs=ltOj|#>3K}- zp~@U0(B4Wu94^irCbW(Ww2F2p>*?jtmciaOtx{6=+XiA=q7O9U&g zj*0%P;H6K9_jdLBtL%-m7}(FkDAc08-CzwTPzqGDgP%NVa zECoi+jwMKJPH#5N+kZQSW5!_qkkPBq4X&rF{fhW0ExY|lTqGWF`UUrAjMD=m1O0+R zkl1o2ur4iU2{()6S6c(Kvi(R;8x-$Du~!+IA4vemzj92RP&dZ+geIorAx@pLPuh=~ z%>wHj!0olVh}#^3#W~n&J(n(ns$_kz(AD6c%WIM~E$dnc_^gYDGfLC3$o^Wf@IFhqYLF2*i27Yo7l(f zq#AL%v(;!?LAz#?uY zJ$h4JBa5cY!aZA(&Q%C+aI(4^@3yNQa*B#NgyVze zDrQqRsVi3q!H1EX*7^B z#OD0;&}{x`UiVPc2>S^awIKn}KB&VHG^Anl|EoLDx;W}NZwC-OD^?8=2 zIjUy%>(L)?n;_`Cd}uc9Pf*PbwRPD1Vjj{SzS}Mo}1UUuWsvj@?$rH2Gi&Cp2_-2 z-pDznNi_6$3T}ig;*gxG`sO+%djvI6fZ7S*+G(Z*)%J zEL(9_F8v23D`NgStM^OkGIMu1U7(0pEh%GT=_W7}2fOs6lIY6Dco$XR_X4s21><6_ z15hD?)tUNc8+vgkGoQet5yXM@ouL0-v{#L(OFgb)`tsJ=Ej{De(3u6{6!j5RE={{7 zyl++z&_R_YBgv9;8153rHo?+Qea<^vK=#39(%Llr11%iQb|B~~KEBm}j<$zUNRqLT ztjV8Qsm<`Go7P!xP;j|TBRK@Z1aU;J zGPGniY=7ksbI{^EZ3dIhWzYXIY?xxa^SAbLZDDwDT9#b$7;GWH)KJv30ByP}g*{7b z;awR1Q|DA;QDdYVWZXVEGftJI@J?i(dx`&3$ys&9)r9Ld1oz+`g44LWy9bxx?$UUI z1$PLff#41Sn#QehcXxNU;0}jx?{j-D&M#PN)u=JnTTjhry40UP^u6ULx)!Zq1F*=o z{4^2UkBWZXShH8ghtXW|e%=jP2tyW0DTA05YOd!TQ+ws$bl4? z$U`?(9I(ctf%>f+6zI(DgvSib zn2y=TB(J8ld@sC)yTC-}toe>0z_YC)QW~fsIpS5w+p-E%DKKg7tt8Ggv4vfEZ%6{` zc?rq2pd&Z4c+Og?LF}E3YE+F1IK8`jY~Izs$V?JAQ-pS{Vug-vgUSlx5t@~_6sJl? z_!GZ;z$tzqOpCXsGgLbcAxRmAGeWh33m1IsajT!XE?p%V-`KOLZ$_q~K?l_E|La!P zTMsq`0A1tZ!wz90T+7O}rWVd+*<4h*R$AW<<_?uDQDWpbSIj;r8t+HNm`jMz`z>k= z-7GxGHwW4N7LxQFc}tw@T5Ss$g|5V0x|zD5i96vF2~;Byoo-rcnfWWNz@7&)8!wvi zFY(hEOACO5YI7*k?U5PSM*MQwHMDQQLRVg_cB<%4&EbVbHME%FJ_i!&k;k)ylQV_M z-xVNt=t*A%PYNU))fw#4C`eOf*TyxaeGSl!XvyvkZ~@}9UhE6fcs&xOnhbT78`@Fy zB3?)s@sHBwf64tD!~cD!Ko~+S0JDY*4V5NsWb!qCX^-n-gFU;I7aH^+q~%B36jyHH zoq7G7CV`ymM&F?N?Ysyv3_r`zq;%-`0z>qJ{W^A`Zlc)ko5BH5@ynWkHNnoAC!S8Y z=>iycR&lKC!?Jz;)1V$N4AOb%AtluHux(G6q>agxWI{NAczz|M?2#1QN)9A7p7Ms2 z2zAF$@|6R|6I06u8azU4(JPbEXpzHx$SX0*D6lM8$`qNZ5_7vv+kQ=n!)qz&Wu=&p zNaU*%Oaf;)TsM>4p~~j{o6(MZc6Zu>dN zZ2IVYMPtIh&oy~mxTUw0+_-?%Ok}Sl@=3F@DC`eHPt%F9HL@MMero)`~u|@^+1h_~EW~$c<2m3i})q+i*-PE`d-M;T1sN@AzrfvT!``MM~ zFeXeDYV_tX-q2p)QDWX->WOt;)c2tvqXN-it?9&%bRB%8duffdinfL8^ zRmF}4o?Wl1B980qKHHZP@QX*lK423qTcMnN-WE5LuhBH4Vo6KzkTc&SAkK_yN4R*T zKZ=-L<+QJ=FmS@7?P zO?+|Uzc|_HGqgZ?j||^yIXXkcpTGT-!}pq5nlk%8H}OPT4D!yg)U~niz6koZ!uA^l zvcpKmJQB%%zq>D12|z!-o5mFr{6U^|$WFVD&y;Q|ydG246t)1>rG3v@{}-yaq7Uah z{gt`-fw%0R2j0$}pqyJiFeh8+=Dy)XMV_rDl%h2iFZx0FNT&22ud!vFrPQSl&ps1L zdv0Fe@KA~8EuAIw%0n&yg~f{wVen-G|BgQ2D5qr0Mf{%O!3Y5(emrU}vYke)%%XtP2P|tQYEWR%cmS6qC$v!sJm4om7_F+mlpmhg;J z8Jzk!;(WQ&ZqYaNnqi9OwSVRJcg0`0{0a`=o6;KWWurXwk`3k((C94{_LIMHKZB?^ zIHzMj>?N+)@82yKv7E}KI>|3@{;mBYooiFduUYEf5}wwiRVC(b<$RCt#KMf{8jB9Y z;ZYx-vH3uA`0IOBAofDU?Pgdct)`x>!=yYf0@s;$^-*j~KR7iDt=4^FRUI~flS@Pf`JJ#j0FLjMv9+-OGwsU zoCTTiY(+^PbJ&V&>r7o>`r1-h|4`6tn%dZ^!?hzdylsU4$Gvk&`}XGByO{=YQO1pdqcS7sWqHDE$j#(>8Tk<^O2)2#{KX!%EKzlKR<7HEj&A=wH$H`FPzUchkVhsEeb zAJj}Jqr4@&E1hapnX?#$qA-pe#JFy}1Wen6$BC;Sgo>K6m0-9)Uvl?vrf`E}HB@D+ z9qk?TOdUv0?2@suw|h?LX|js_HB9B~uMni7ai~!krBGMyCB7D)@s@s}UG{T_rP$@0 zL$p8>#FbvZtK`MxNne6O8Soc!F%7hk&>5Fk2?NtlEuKku-G%$zU{~X zsGWP~n6Zx6-jZ0PQs9BZBSN|{pSBO1)pDITbbKQp>&?qwY?z#ZRQt%|oIMoR9F36&-u(*zmR(8Z!t^v(Ky)a{CK%9mZ-^x05 zg;cd5eq<#Eb%83lC`SH`Ee02>!ULf)==6P7z!239?p|cj9vitQ<)hde$_P-h$Fpup%Z4H0 zXU2j>8iVpaSUzM?_IfeyrK6;w4BypH`RZa~Itp_YCKV|E8L#|Z8n!+@g{m*SXhE09 zI?fQ}^MJz|P0rF_H~%=_xl0Z6DWs3QA=FLc5#F{}%8~q4rR6CjA~}E;*F$ZHFd~T~ z%HPDutiZ7a84{3WS7e`SQ>a>>k z9ZCsC|MvxftFe3(9?26Q-PaQyh-xuzbB&xthXHt9Et2qTfYT!OEQb}|X*#ypr zQliz6_4BLgk`QL(U&%!er)C{Aep-!h7tm}8AsPpVPj0ACvHpC>uZ}-|%#QYYiwBv^ zZNK}09En2ln)S&)6kl|X(lD1`2^iI!KOL*bQElzTINx)WMI+4?E97D<=vW|Jd}LuO zLEUv^E1DV1?%7G&zTBfn$@>aw=VKTFk(iE1)B98ynD{lFzz8xF7EcJ2MVLNYBJVR~ zQ{iHeRDbp|%+ynMaU^$Q%y^u6-F9NQf%O&-5a)E{wK$dgRC7}?v`!;Qp4{G~;NG~O zlJm7il@_X+K5KnkeFrM{bHhYavC2yM$MQ7$4;v*01WAYP$i=$ZkeKnXLg9}32nCO9 z&x(MQ|F0xQ@{ z%Fm+wFrq%VD{L%M{wTnarw%`()Q%3!s@C+mcLYM{}?ki@kGArov8pn&plG%8M#=gxCj)s^{XGP zY-ZQSe&t$+r|>^l*^WfP3x4DBw=LUbn6EF5<;tA! zoxLa|k(+b-EN0lrl#0VU&2x`)H0wsovxMHQ8e}ViWV+9*bz0n;za-mU>90$)lFjh8SWZxrt z#loNAA+amppz)!b=o)AyuqpX{NPHjeBT{}!+jZ(vj59JcY!K{);MP=%?qs|ZHofY% zMm9j=O6gW7v)SGteIA|h%>-qk1Nj%S>X}rxpy@dzcIlk;y!&yJ^ z>N0haK$Sn|aa^}|`=w3~J$b$dxw7%Z_KRbbZk;OCXB1w#5MNdj5TG{z{xJ>t1q+&J|!}7&l*+3 z3l+YEcKVS3_0ZthDrB)EAql_&q#bdX=;}YOU`0PhVXVc-$d)*8n@y>G1ck8slcH8#HlI z-wcWLIm0%Hsq3xN4)|WR1*$U&>UpK;3DWP}eT9+t$D73G`8AtlYr8hPgq8R(dFU7( z5FyT{R9geXa(EtkQot4n?w^-oI`8jEge5q4`0>MBN6U$R`5pGE1&Q`w`JsipiOHG5 zX~+O zjM*(~(4T~F(lCkS6t(!EyHs)XrCksUu#PS`|WAU& ze=vSk1z}X=OkfWpKZer<-22E*gz>T~LoZ>E zDjNtlUm8VPYSYn6Fp0{YQ?%>7k0-D+Plw#?qxDGIIGp3Jcz^A}x`Z7YBOm+aD01&} zfZU$lU4GI~WHd>~NU9p~n$-8{P9{=_=JGV1Bg!Ee=7|O|G80J)7#N`iRBE;Sk#T`~ zdmZFV`VnTvw`WH->{kiyp^Jn`e|}sRVe4K~eUL4UdR2W&Bl~T|r1$t9bte@j230tt z(ysLaUo@KVGdQ0`im%zBGAn#=1U@Xr`2;Eh|NTkE8VdJf0-Jy8nA%gVHC2z2i+k?~ zto5=z`vc5r(ulsg6ldKV*S}JczFN!0NKBzFcZiSJH4WH~IMFF%DQPwoq|oj2FPi^k zqv{SZE773pI*9%Z>F>Pz8T#M+nEJT}1U7R#w(P+++dVXVOYG zUW060C?ijYaEYZ`zNY;zb91TGgR8Qv^TwazHFekF3uHYmj$-!$1XP;XE|`|&`jy2Y zTst%>lvg+n$#pgSlTu)h5ko`g=HdSphufe=*S{Ov;7QWaGr7g@&JRQ55N_>+p=CwO zyO#(p>S5zYok^r(?h2V2$FTZ6zI(IhH%U(7zf z&|oEoPO?=VgI^w+6^@Pi^(J-E zRZ;TftaM_$SWx7g^9nZ?I*N~)5L%C||Fcd6PH{nsS(nCz zbsI+4xUG*FX|PuF&fhnDEG#oPm0;&>Fs+tNkA=PwV zKonMe7|?sBTwwyYi+2V)jDVIW*m0V?#FFLbH{Q;DfK;rAG)7qqhq%5=T%{7UfRJ=cS;Vv42S4>F>b#N7QxIdXXT%oNp>9e0ANu>Y676*SF^zBePgRM&&&!Bt6Ql{W@ zzbfcj`)hL~2<#+cnk6KdC)5VLxC+IN$|avW)&Yy-He;)2v_V{ygrt2>qeRlefNcws zqa)f;?6gk?F^xj{^*8bQ+5SFlPpg^&4uQtUIG@yrry@AAHH^^nB`=3s! zT5q0A*7OpYObUJ6OAg|8!MPr{L!%~Iy!q4jUgvD};p}`27xx%_EiCJlS8KnO-x4(L zd1yn>c14++rpl4BpIE$nVg7OcC|L+TJe}-&O9PurvrcGkmGozF*I7F{CaSY92)X{o zO$&vvv~H*bHyfgH{AP6>KVoQ|4lJtRvV8s?UCJ?{4DO;6cjq<#AgZMOXewwLXx_8i zci2As@wN30%<)=?X_f91PGtzeaax=HmWt918vfi^`S4u{n`7a~WwMg#QY0e%$!Hz= zHp~@j^PhB7QpIu*sIXs=%ut)DIc<0h7R+@^+@`GXWTvT@T1sPo5Mopm!XasoOue|H zsJn(2xNj|i#)WjZVwRScx{Dye{wc3^N)u#LeKJ+T8lzp6pzc?(DsSXuTy6o(bCO$} z?idfbx7E4s%aG4OI%^gE*(rDJ@HaCC zOHIn`4pRce*s)YiPHD?}U997qKMwEIyU3Zn;uTqh#r)OTfhlR@x5hO!WLF-nP(_Gr zrV^guf{ouK>N0KnZqGx7(7(baNamtFv zNeWkEAa{`xPjT~S8`}UO>CDWVhcB#6zm8qjqjy$&(uaF2$?j6!owJJG<)rCw;P-%2 zE4i}IZxCWaqLtu(XG}PWS+J`X4nq1xW3`6SzkT)HP>8_~$7ubwTRiO}h@WiX9JUd| z))yNnaJY-$M7O0S|CF7{m@&5IEQe{5*tBZ%a!l2*xfuNvo>L*_H|R6v5!lR-^hfM8z`Y=u;b1ds`RAn4&3|@HMDj&ZZ*8!^2S3)#eyicZQeW(NtU1Z){yzT4f zoxqQ187=NyvrA|S$pT2*iSD5N2tkyDJDDf-Y#y25W+M>I?X%$R_42t6g3GAJ-Q1H= zWlYi{TF_fdtz-Rn2bmRh1lUAYlWTwR+f(mr6OvJE5OdzYW5akZWk|MhXh!2>&+#oT;Y0k;yl?Z#B!lw+EJK6(e%mDTilDi}FvI1+6sW zOs>Yz^*cn)`n4dP@BtZ=tM0lnwJMH9>+IlaGR*dW9#ED4@V56-LP+%6|Is%tur*qdkA-T_po41UCH5FvHS&iPtm`#w_)MddLd_*}`uoEh+%ogs37W8<1_l(QlX4r#h#)CEBobU}!yB1W%R2nqR>~;mjMKD?Pt|02QV3km9kP2Eib^}#L@hBF&ItBpB6m+ZCh}jV2R0r9ThJnG*&}{X zNDato6yj#NQ9WEsXW)r^)vI9y;l}JVRtH z-7J!IL{h5A^G~vDL&xk4nZVjjuM2{TXOl#zZCZr{5;ErCks)ubJY)J)A?*y1Sp z4h$Jy)oMkyto}I?AKJ3?78=9Aw87UiCI|?}ZRsc-v?qF%UY0J8@^Y)O;Yd!u`>ffl zI&!9{he6wZq#zAsl2|?vNoS~b%+?PLl;5y*@Hu_mF0a`zdY`-RSX>VVBEvCAbBW@l z3Y6G9XJ+-Vl=rXJlM63j+Pgm~gr*%YQUGc&+Vh%_Wi(21IWV(nphd5jFgZS0^MR_u zi#%HcU6C?LOuRrngnG-X#*kgcUldPuQ`Vq73OosSi*5V<(IWJgw5C#9z_x$+e;eIi zris9FNxmF$|Mw&7ume4bK5W0GY}=`k-3{AhCw@Gi6bziFWsz3_FM|jQdo>);o!o!@ z_hp#?q;BQ@M(TZ44LFxbmQa~jnHf~I`dey6w!_8i7*au=jUP$N4Ym_D8r+h!iNZUJ zyM{Y^CT>2KlnNc?0L2;!Tmt?~NznfR+zZ%> literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_learn_and_discover.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/img_learn_and_discover.png new file mode 100644 index 0000000000000000000000000000000000000000..d05285fd5aef95a82ae9c07519379e36ddbe5664 GIT binary patch literal 15557 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 ZGq8W5`V8!Wb{&6{5RnzG{;ePI{{V6Lr9uDz literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt new file mode 100644 index 00000000..2f0b6da8 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt @@ -0,0 +1,50 @@ +package network.bisq.mobile.presentation.ui.components.foundation + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import coil3.Image +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +// TODO: +// leftIcon, rightIcon -> Not happening right +@Composable +fun BisqButton( + text: String, + onClick: () -> Unit, + color: Color = BisqTheme.colors.light1, + backgroundColor: Color = BisqTheme.colors.primary, + padding: PaddingValues = PaddingValues(horizontal = 48.dp, vertical = 4.dp), + leftIcon: Unit? = null, + rightIcon: Unit? = null, + modifier: Modifier = Modifier +) { + + // Apply proper rounded corner + Button( + onClick = { onClick() }, + contentPadding = padding, + colors = ButtonColors( + containerColor = backgroundColor, + disabledContainerColor = backgroundColor, + contentColor = color, + disabledContentColor = color) + ) { + Row { + if(leftIcon != null) leftIcon + if(leftIcon != null) Spacer(modifier = Modifier.width(10.dp)) + BisqText.baseMedium( + text = text, + color = BisqTheme.colors.light1, + ) + if(rightIcon != null) Spacer(modifier = Modifier.width(10.dp)) + if(rightIcon != null) rightIcon + } + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt new file mode 100644 index 00000000..050ec883 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt @@ -0,0 +1,39 @@ +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.ProgressIndicatorDefaults +import androidx.compose.material3.ProgressIndicatorDefaults.drawStopIndicator +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +@Composable +fun BisqProgressBar( + progress: Float, + modifier: Modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 100.dp) + .padding(bottom = 20.dp) + .height(2.dp) +) { + + val grey2Color = BisqTheme.colors.grey2 + + LinearProgressIndicator( + progress = {progress}, + modifier = modifier, + trackColor = BisqTheme.colors.grey2, + color = BisqTheme.colors.primary, + gapSize = 0.dp, + drawStopIndicator = { + drawStopIndicator( + drawScope = this, + stopSize = 0.dp, + color = grey2Color, + strokeCap = ProgressIndicatorDefaults.LinearStrokeCap + ) + } + ) +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt similarity index 99% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt index 1c8f2c34..0f0519c2 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/foundation/BisqText.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt @@ -25,16 +25,16 @@ enum class FontWeight { } enum class FontSize(val size: TextUnit) { - XSMALL(12.sp), - SMALL(14.sp), - BASE(16.sp), - LARGE(18.sp), - H6(20.sp), - H5(22.sp), - H4(25.sp), - H3(28.sp), - H2(32.sp), - H1(36.sp); + XSMALL(10.sp), + SMALL(12.sp), + BASE(14.sp), + LARGE(16.sp), + H6(18.sp), + H5(20.sp), + H4(22.sp), + H3(25.sp), + H2(28.sp), + H1(32.sp); } object BisqText { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt new file mode 100644 index 00000000..827c6b73 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt @@ -0,0 +1,12 @@ +package network.bisq.mobile.presentation.ui.components.atoms.icons + +import androidx.compose.foundation.Image +import androidx.compose.runtime.Composable +import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.bisq_logo +import org.jetbrains.compose.resources.painterResource + +@Composable +fun BisqLogo() { + Image(painterResource(Res.drawable.bisq_logo), "Bisq Logo") +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt new file mode 100644 index 00000000..cdb89770 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt @@ -0,0 +1,34 @@ +package network.bisq.mobile.presentation.ui.components.layout + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +@Composable +fun BisqScrollLayout( + innerPadding: PaddingValues = PaddingValues(top = 24.dp, bottom = 12.dp, start = 12.dp, end = 12.dp), + content: @Composable ColumnScope.() -> Unit +) { + Scaffold( + containerColor = BisqTheme.colors.backgroundColor, + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .background(color = BisqTheme.colors.backgroundColor) + .padding(innerPadding) + .verticalScroll(rememberScrollState()) + ) { + content() + } + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt new file mode 100644 index 00000000..792541db --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt @@ -0,0 +1,32 @@ +package network.bisq.mobile.presentation.ui.components.layout + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +@Composable +fun BisqStaticLayout( + innerPadding: PaddingValues = PaddingValues(top = 48.dp, bottom = 30.dp), + content: @Composable ColumnScope.() -> Unit +) { + Scaffold( + containerColor = BisqTheme.colors.backgroundColor, + ) { + Column( + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .background(color = BisqTheme.colors.backgroundColor) + .padding(innerPadding) + ) { + content() + } + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt index 901d9f37..12c3f9c9 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt @@ -1,4 +1,6 @@ package network.bisq.mobile.presentation.ui.model +import org.jetbrains.compose.resources.DrawableResource + data class BottomNavigationItem(val title: String, val route: String, val icon: String) -data class OnBoardingPage(val title: String, val image: String, val desc: String) +data class OnBoardingPage(val title: String, val image: DrawableResource, val desc: String) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt index 8e5e9bb3..9cc4ab5b 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt @@ -1,31 +1,26 @@ package network.bisq.mobile.presentation.ui.screens -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.* import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res -import coil3.compose.AsyncImage +import bisqapps.shared.presentation.generated.resources.img_bot_image import network.bisq.mobile.components.MaterialTextField +import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo +import network.bisq.mobile.presentation.ui.components.foundation.BisqButton import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.layout.BisqScrollLayout import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource private lateinit var textState: MutableState @@ -35,98 +30,61 @@ fun CreateProfileScreen( rootNavController: NavController ) { textState = remember { mutableStateOf("") } - Scaffold( - containerColor = BisqTheme.colors.backgroundColor, - ) { innerPadding -> - Column( - verticalArrangement = Arrangement.SpaceBetween, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxSize() - .padding(innerPadding) - .padding(bottom = 20.dp) - ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - AsyncImage( - model = Res.getUri("drawable/logo_with_slogan.svg"), - contentDescription = null, - modifier = Modifier.height(62.dp).width(200.dp), - ) - Spacer(modifier = Modifier.height(32.dp)) - BisqText.h1Light( - text = "Create your profile", - color = BisqTheme.colors.grey1, - ) - Spacer(modifier = Modifier.height(12.dp)) - BisqText.largeRegular( - text = "Your public profile consists of a nickname (picked by you) and bot icon (generated cryptographically)", - color = BisqTheme.colors.grey3, - modifier = Modifier.padding(horizontal = 24.dp), - textAlign = TextAlign.Center, - ) - Spacer(modifier = Modifier.height(40.dp)) - Column(modifier = Modifier.padding(horizontal = 54.dp)) { - BisqText.h6Regular( - text = "Profile nickname", - color = BisqTheme.colors.light2, - ) - MaterialTextField(textState.value, onValueChanged = { textState.value = it }) - } - Spacer(modifier = Modifier.height(36.dp)) - AsyncImage( - model = Res.getUri("drawable/bot_image.svg"), - contentDescription = null, - modifier = Modifier.size(120.dp), - ) - Spacer(modifier = Modifier.height(32.dp)) - BisqText.largeRegular( - text = "Sleepily-Distracted-Zyophyte-257", - color = BisqTheme.colors.light1, - ) - Spacer(modifier = Modifier.height(12.dp)) - BisqText.largeRegular( - text = "BOT ID", - color = BisqTheme.colors.grey2, - ) - Spacer(modifier = Modifier.height(38.dp)) - BisqText.baseMedium( - text = "Generate new bot icon", - color = BisqTheme.colors.light1, - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = BisqTheme.colors.dark5) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = {}) - .padding(horizontal = 64.dp, vertical = 12.dp), - ) - Spacer(modifier = Modifier.height(40.dp)) - BisqText.largeMedium( - text = "Next", - color = BisqTheme.colors.light1, - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = if (textState.value.isEmpty()) BisqTheme.colors.primaryDisabled else BisqTheme.colors.primary) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - if (textState.value.isNotEmpty()) { - rootNavController.navigate(Routes.BisqUrl.name) { - popUpTo(Routes.CreateProfile.name) { - inclusive = true - } - } - } - }) - .padding(horizontal = 64.dp, vertical = 12.dp), - ) - } + BisqScrollLayout() { + BisqLogo() + Spacer(modifier = Modifier.height(24.dp)) + BisqText.h1Light( + text = "Create your profile", + color = BisqTheme.colors.grey1, + ) + Spacer(modifier = Modifier.height(12.dp)) + BisqText.baseRegular( + text = "Your public profile consists of a nickname (picked by you) and bot icon (generated cryptographically)", + color = BisqTheme.colors.grey3, + modifier = Modifier.padding(horizontal = 24.dp), + textAlign = TextAlign.Center, + ) + Spacer(modifier = Modifier.height(36.dp)) + Column(modifier = Modifier.padding(horizontal = 24.dp)) { + //TODO: Convert this into a Form field component, which is Label + TextField + BisqText.baseRegular( + text = "Profile nickname", + color = BisqTheme.colors.light2, + ) + MaterialTextField(textState.value, onValueChanged = { textState.value = it }) } + Spacer(modifier = Modifier.height(36.dp)) + Image(painterResource(Res.drawable.img_bot_image), "Crypto generated image (PoW)") + Spacer(modifier = Modifier.height(32.dp)) + BisqText.baseRegular( + text = "Sleepily-Distracted-Zyophyte-257", + color = BisqTheme.colors.light1, + ) + Spacer(modifier = Modifier.height(12.dp)) + BisqText.baseRegular( + text = "BOT ID", + color = BisqTheme.colors.grey2, + ) + Spacer(modifier = Modifier.height(38.dp)) + BisqButton( + text ="Generate new bot iconnn", + backgroundColor = BisqTheme.colors.dark5, + padding = PaddingValues(horizontal = 64.dp, vertical = 12.dp), + onClick = {} + ) + Spacer(modifier = Modifier.height(40.dp)) + BisqButton( + "Next", + onClick = { + if (textState.value.isNotEmpty()) { + rootNavController.navigate(Routes.BisqUrl.name) { + popUpTo(Routes.CreateProfile.name) { + inclusive = true + } + } + } + }, + backgroundColor = if (textState.value.isEmpty()) BisqTheme.colors.primaryDisabled else BisqTheme.colors.primary + ) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt index 3ab1eb43..0ab86a1b 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt @@ -1,5 +1,6 @@ package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -7,8 +8,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.calculateEndPadding -import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -18,28 +17,25 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.img_fiat_btc +import bisqapps.shared.presentation.generated.resources.img_learn_and_discover import coil3.compose.AsyncImage -import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.presentation.ui.components.TopBar import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.theme.* +import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi -import org.jetbrains.compose.resources.Font +import org.jetbrains.compose.resources.painterResource @Composable fun GettingStartedScreen( @@ -47,22 +43,20 @@ fun GettingStartedScreen( innerPadding: PaddingValues, ) { Column( -// modifier = Modifier.fillMaxSize().padding( -// start = innerPadding.calculateStartPadding(originDirection), -// end = innerPadding.calculateEndPadding(originDirection), -// bottom = innerPadding.calculateBottomPadding(), -// ), modifier = Modifier .fillMaxSize() .padding(innerPadding), ) { - // Should be a child of Scaffold, in TabContainerScreen + // TODO: Should be a child of Scaffold, in TabContainerScreen TopBar(isHome = true) + + // TODO: Should use BisqScrollLayout. But it has Scaffold inside it already! Column( modifier = Modifier.padding(horizontal = 32.dp, vertical = 15.dp) .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(42.dp) + verticalArrangement = Arrangement.spacedBy(24.dp) ) { + Column { PriceProfileCard( price = "$ 60,000.00", @@ -91,14 +85,14 @@ fun GettingStartedScreen( ) Column { InstructionCard( - imagePath = "drawable/fiat_btc.svg", + image = Res.drawable.img_fiat_btc, title = "Multiple trade protocols", description = "Checkout the roadmap for upcoming trade protocols. Get an overview about the features of the different protocols.", buttonText = "Explore trade protocols" ) Spacer(modifier = Modifier.height(24.dp)) InstructionCard( - imagePath = "drawable/learn_and_discover.svg", + image = Res.drawable.img_learn_and_discover, title = "Learn & discover", description = "Learn about Bitcoin and checkout upcoming events. Meet other Bisq users in the discussion chat.", buttonText = "Learn more" @@ -121,7 +115,7 @@ fun WelcomeCard(title: String, buttonText: String) { .padding(24.dp), verticalArrangement = Arrangement.spacedBy(32.dp) ) { - BisqText.h3Regular( + BisqText.h4Regular( text = title, color = BisqTheme.colors.light1, ) @@ -169,7 +163,7 @@ fun PriceProfileCard(price: String, priceText: String) { textAlign = TextAlign.Center, ) - Spacer(modifier = Modifier.height(18.dp)) + Spacer(modifier = Modifier.height(12.dp)) BisqText.smallRegular( text = priceText, @@ -189,7 +183,7 @@ fun FeatureCard(imagePath: String, title: String) { modifier = Modifier.size(20.dp) ) Spacer(modifier = Modifier.width(9.dp)) - BisqText.baseRegular( + BisqText.smallRegular( text = title, color = BisqTheme.colors.light1, ) @@ -199,28 +193,29 @@ fun FeatureCard(imagePath: String, title: String) { @OptIn(ExperimentalResourceApi::class) @Composable -fun InstructionCard(imagePath: String, title: String, description: String, buttonText: String) { +fun InstructionCard(image: DrawableResource, title: String, description: String, buttonText: String) { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.clip(shape = RoundedCornerShape(8.dp)).background(color = BisqTheme.colors.dark3) .padding(vertical = 18.dp, horizontal = 12.dp), verticalArrangement = Arrangement.spacedBy(18.dp) ) { - AsyncImage( - model = Res.getUri(imagePath), - contentDescription = null, - modifier = Modifier.size(50.dp) - ) +// AsyncImage( +// model = Res.getUri(imagePath), +// contentDescription = null, +// modifier = Modifier.size(50.dp) +// ) + Image(painterResource(image), "") BisqText.baseRegular( text = title, color = BisqTheme.colors.light1, ) - BisqText.smallRegular( + BisqText.baseRegular( text = description, color = BisqTheme.colors.grey3, textAlign = TextAlign.Center, ) - BisqText.xsmallRegular( + BisqText.smallRegular( text = buttonText, color = BisqTheme.colors.light1, modifier = Modifier diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt index 953ed9e4..cc75a067 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -1,151 +1,117 @@ package network.bisq.mobile.presentation.ui.screens +import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PageSize import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.navigation.NavController - +import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res -import coil3.compose.AsyncImage +import bisqapps.shared.presentation.generated.resources.img_bisq_Easy +import bisqapps.shared.presentation.generated.resources.img_learn_and_discover + import kotlinx.coroutines.launch +import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo +import network.bisq.mobile.presentation.ui.components.foundation.BisqButton import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.layout.BisqScrollLayout import network.bisq.mobile.presentation.ui.model.OnBoardingPage import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* +import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi -import org.jetbrains.compose.resources.Font +import org.jetbrains.compose.resources.painterResource val list = listOf( OnBoardingPage( title = "Introducing Bisq Easy", - image = "drawable/bisq_easy.svg", + image = Res.drawable.img_bisq_Easy, desc = "Getting your first Bitcoin privately has never been easier" ), OnBoardingPage( title = "Learn & Discover", - image = "drawable/learn_and_discover.svg", + image = Res.drawable.img_learn_and_discover, desc = "Get a gentle introduction into Bitcoin through our guides and community chat" ), OnBoardingPage( title = "Coming soon", - image = "drawable/fiat_btc.svg", + image = Res.drawable.img_fiat_btc, desc = "Choose how to trade: Bisq MuSig, Lightning, Submarine Swaps,..." ) ) private lateinit var pagerState: PagerState - @OptIn(ExperimentalResourceApi::class) @Composable fun OnBoardingScreen(rootNavController: NavController) { - Scaffold( - containerColor = BisqTheme.colors.backgroundColor, - ) { innerPadding -> - Column( - verticalArrangement = Arrangement.SpaceBetween, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxSize() - .padding(innerPadding) - .padding(bottom = 20.dp) - ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - AsyncImage( - model = Res.getUri("drawable/logo_with_slogan.svg"), - contentDescription = null, - modifier = Modifier.height(62.dp).width(200.dp), - ) - Spacer(modifier = Modifier.height(32.dp)) - BisqText.h1Light( - text = "Welcome to Bisq", - color = BisqTheme.colors.grey1, - ) - } - - PagerView() - Column { - val coroutineScope = rememberCoroutineScope() - - BisqText.largeMedium( - text = if (pagerState.currentPage == 2) "Create profile" else "Next", - color = BisqTheme.colors.light1, - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = BisqTheme.colors.primary) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - if (pagerState.currentPage == 2) { - rootNavController.navigate(Routes.CreateProfile.name) { - popUpTo(Routes.Onboarding.name) { inclusive = true } - } - } else { - coroutineScope.launch { - pagerState.animateScrollToPage( - pagerState.currentPage + 1 - ) - } - } + BisqScrollLayout() { + BisqLogo() + Spacer(modifier = Modifier.height(24.dp)) + BisqText.h1Light( + text = "Welcome to Bisq", + color = BisqTheme.colors.grey1, + ) + Spacer(modifier = Modifier.height(56.dp)) + PagerView() + Spacer(modifier = Modifier.height(56.dp)) + Column { + val coroutineScope = rememberCoroutineScope() + BisqButton( + text = if (pagerState.currentPage == 2) "Create profile" else "Next", + onClick = { + if (pagerState.currentPage == 2) { + rootNavController.navigate(Routes.CreateProfile.name) { + popUpTo(Routes.Onboarding.name) { inclusive = true } + } + } else { + coroutineScope.launch { + pagerState.animateScrollToPage(pagerState.currentPage + 1) + } + } + } + ) - }) - .padding(horizontal = 64.dp, vertical = 12.dp), - ) - } } } + } @Composable fun PagerView() { - pagerState = rememberPagerState(pageCount = { list.size }) - CompositionLocalProvider(values = arrayOf()) { Column( horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(64.dp, Alignment.CenterVertically), + verticalArrangement = Arrangement.spacedBy(36.dp, Alignment.CenterVertically), ) { HorizontalPager( pageSpacing = 56.dp, - contentPadding = PaddingValues(horizontal = 56.dp), + contentPadding = PaddingValues(horizontal = 36.dp), pageSize = PageSize.Fill, verticalAlignment = Alignment.CenterVertically, state = pagerState @@ -170,7 +136,7 @@ fun PagerView() { @Composable fun BannerItem( title: String, - image: String, + image: DrawableResource, desc: String, index: Int ) { @@ -187,12 +153,7 @@ fun BannerItem( .background(color = BisqTheme.colors.dark3) .padding(vertical = 56.dp) ) { - - AsyncImage( - modifier = Modifier.size(120.dp), - model = Res.getUri(image), - contentDescription = null, - ) + Image(painterResource(image), title, modifier = Modifier.size(120.dp),) Spacer(modifier = Modifier.height(if (index == 1) 48.dp else 70.dp)) Column( horizontalAlignment = Alignment.CenterHorizontally diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 71c16449..a2499e33 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -1,13 +1,8 @@ package network.bisq.mobile.presentation.ui.screens +import BisqProgressBar import androidx.compose.foundation.Image -import androidx.compose.foundation.background import androidx.compose.foundation.layout.* -import androidx.compose.material3.LinearProgressIndicator -import androidx.compose.material3.ProgressIndicatorDefaults -import androidx.compose.material3.ProgressIndicatorDefaults.drawStopIndicator -import androidx.compose.material3.Text -import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -15,10 +10,8 @@ import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp import androidx.navigation.NavController import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.ExperimentalResourceApi @@ -29,27 +22,18 @@ import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.navigation.Routes import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.bisq_logo +import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout import network.bisq.mobile.presentation.ui.theme.* @OptIn(ExperimentalResourceApi::class) @Composable fun SplashScreen(rootNavController: NavController, innerPadding: PaddingValues) { - Scaffold( - containerColor = BisqTheme.colors.backgroundColor, - ) { - Column( - verticalArrangement = Arrangement.SpaceBetween, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxSize() - .background(color = BisqTheme.colors.backgroundColor) - .padding(top = 48.dp, bottom = 30.dp) - ) { - Image(painterResource(Res.drawable.bisq_logo), "Bisq Logo") - LoadingProgress(rootNavController) - } + BisqStaticLayout() { + BisqLogo() + LoadingProgress(rootNavController) } } @@ -61,38 +45,16 @@ fun LoadingProgress(navController: NavController) { Column { LaunchedEffect(true) { scope.launch { - loadProgress { progress -> - currentProgress = progress - } - navController.navigate(Routes.Onboarding.name) { + loadProgress { progress ->currentProgress = progress } + navController.navigate(Routes.BisqUrl.name) { popUpTo(Routes.Splash.name) { inclusive = true } } } } - val grey2Color = BisqTheme.colors.grey2 - - LinearProgressIndicator( - trackColor = BisqTheme.colors.grey2, - color = BisqTheme.colors.primary, - progress = { currentProgress }, - gapSize = 0.dp, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 100.dp) - .padding(bottom = 20.dp) - .height(2.dp), - drawStopIndicator = { - drawStopIndicator( - drawScope = this, - stopSize = 0.dp, - color = grey2Color, - strokeCap = ProgressIndicatorDefaults.LinearStrokeCap - ) - } - ) + BisqProgressBar(progress = currentProgress) - BisqText.smallRegular( + BisqText.baseRegular( text = "Connecting to Tor Network...", color = BisqTheme.colors.secondaryHover, textAlign = TextAlign.Center, @@ -105,6 +67,6 @@ fun LoadingProgress(navController: NavController) { suspend fun loadProgress(updateProgress: (Float) -> Unit) { for (i in 1..100) { updateProgress(i.toFloat() / 100) - delay(100) + delay(25) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt index b58c05ee..53484551 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt @@ -4,19 +4,11 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.slideInHorizontally +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -36,12 +28,18 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.icon_copy +import bisqapps.shared.presentation.generated.resources.icon_question_mark import coil3.compose.AsyncImage import network.bisq.mobile.components.MaterialTextField +import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo +import network.bisq.mobile.presentation.ui.components.foundation.BisqButton import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.layout.BisqScrollLayout import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource private lateinit var textState: MutableState @@ -52,187 +50,114 @@ fun URLScreen( ) { textState = remember { mutableStateOf("") } val isConnected by remember { mutableStateOf(false) } - Scaffold( - containerColor = BisqTheme.colors.backgroundColor, - ) { innerPadding -> + + BisqScrollLayout() { + BisqLogo() + Spacer(modifier = Modifier.height(24.dp)) Column( verticalArrangement = Arrangement.SpaceBetween, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxSize() - .padding(innerPadding) - .padding(bottom = 20.dp) + modifier = Modifier.fillMaxSize().padding(horizontal = 24.dp) ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - AsyncImage( - model = Res.getUri("drawable/logo_with_slogan.svg"), - contentDescription = null, - modifier = Modifier.height(62.dp).width(200.dp), + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + BisqText.baseRegular( + text = "Bisq URL", + color = BisqTheme.colors.light1, ) - Spacer(modifier = Modifier.height(32.dp)) - Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - BisqText.h3Regular( - text = "Bisq URL", - color = BisqTheme.colors.light1, - ) - AsyncImage( - model = Res.getUri("drawable/question_mark.svg"), - contentDescription = null, - modifier = Modifier.size(24.dp) - ) - } - - MaterialTextField(textState.value, onValueChanged = { textState.value = it }) - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - Row( - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = BisqTheme.colors.dark5) - .padding(horizontal = 46.dp, vertical = 12.dp) - - ) { - AsyncImage( - model = Res.getUri("drawable/copy.svg"), - contentDescription = null, - modifier = Modifier.size(20.dp), - ) - Spacer(modifier = Modifier.width(10.dp)) - BisqText.baseMedium( - text = "Paste", - color = BisqTheme.colors.light1, - ) - } - Row( - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = BisqTheme.colors.primary) - .padding(horizontal = 46.dp, vertical = 12.dp) - ) { - AsyncImage( - model = Res.getUri("drawable/qr.svg"), - contentDescription = null, - modifier = Modifier.size(20.dp), - ) - Spacer(modifier = Modifier.width(10.dp)) - BisqText.baseMedium( - text = "Scan", - color = BisqTheme.colors.light1, - ) - } - } - Spacer(modifier = Modifier.height(36.dp)) - BisqText.largeRegular( - text = "STATUS", - color = BisqTheme.colors.grey2, - ) - Spacer(modifier = Modifier.height(12.dp)) - Row(verticalAlignment = Alignment.CenterVertically) { - BisqText.h5Regular( - text = if(isConnected) "Connected" else "Not Connected", - color = BisqTheme.colors.light1, - ) - Spacer(modifier = Modifier.width(12.dp)) - BisqText.baseRegular( - text = "", - modifier = Modifier.clip( - RoundedCornerShape(5.dp) - ).background(color =if(isConnected) BisqTheme.colors.primary else BisqTheme.colors.danger).size(10.dp), - ) - } - - } - - } - var visible by remember { - mutableStateOf(false) + Image(painterResource(Res.drawable.icon_question_mark), "Question mark") } + MaterialTextField(textState.value, onValueChanged = { textState.value = it }) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + BisqButton( + text = "Paste", + onClick = {}, + backgroundColor = BisqTheme.colors.dark5, + color = BisqTheme.colors.light1, + //leftIcon=Image(painterResource(Res.drawable.icon_copy), "Copy button") + ) - if (!visible) { - BisqText.baseMedium( - text = "Test Connection", - color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, - modifier = Modifier - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = if (textState.value.isEmpty()) BisqTheme.colors.primaryDisabled else BisqTheme.colors.primary) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - visible = !visible - }) - .padding(horizontal = 32.dp, vertical = 12.dp), + BisqButton( + text = "Scan", + onClick = {}, + //leftIcon=Image(painterResource(Res.drawable.icon_qr), "Scan button") ) - } else { - Row (modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)){ - AnimatedVisibility( - visible = visible, - enter = slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(700)), - ) { - BisqText.baseMedium( - text = "Test Connection", - color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, - modifier = Modifier + } + Spacer(modifier = Modifier.height(36.dp)) + BisqText.baseRegular( + text = "STATUS", + color = BisqTheme.colors.grey2, + ) + Spacer(modifier = Modifier.height(12.dp)) + Row(verticalAlignment = Alignment.CenterVertically) { + BisqText.largeRegular( + text = if (isConnected) "Connected" else "Not Connected", + color = BisqTheme.colors.light1, + ) + Spacer(modifier = Modifier.width(12.dp)) + BisqText.baseRegular( + text = "", + modifier = Modifier.clip( + RoundedCornerShape(5.dp) + ).background(color = if (isConnected) BisqTheme.colors.primary else BisqTheme.colors.danger) + .size(10.dp), + ) + } + } - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = BisqTheme.colors.dark5) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { + Spacer(modifier = Modifier.height(56.dp)) - }) - .padding(horizontal = 32.dp, vertical = 12.dp), - ) - } - Spacer(modifier = Modifier.width(20.dp)) - AnimatedVisibility( - visible = visible, - enter = fadeIn(animationSpec = tween(300)), + var visible by remember { + mutableStateOf(false) + } - ) { - BisqText.baseMedium( - text = "Next", - color = BisqTheme.colors.light1, - textAlign = TextAlign.Center, - modifier = Modifier - .fillMaxWidth() - .clip(shape = RoundedCornerShape(8.dp)) - .background(color = BisqTheme.colors.primary) - .clickable( - indication = null, - interactionSource = remember { - MutableInteractionSource() - }, - onClick = { - rootNavController.navigate(Routes.TabContainer.name) { - popUpTo(Routes.BisqUrl.name) { - inclusive = true - } - } - }) - .padding(horizontal = 32.dp, vertical = 12.dp), - ) - } + if (!visible) { + BisqButton( + text = "Test Connection", + color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, + onClick = { visible = !visible }, + padding = PaddingValues(horizontal = 32.dp, vertical = 12.dp), + ) + } else { + Row(modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)) { + AnimatedVisibility( + visible = visible, + enter = slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(700)), + ) { + BisqButton( + text = "Test Connection", + color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, + onClick = { }, + padding = PaddingValues(horizontal = 32.dp, vertical = 12.dp), + ) } + Spacer(modifier = Modifier.width(20.dp)) + AnimatedVisibility( + visible = visible, + enter = fadeIn(animationSpec = tween(300)), + ) { + BisqButton( + text = "Next", + color = BisqTheme.colors.light1, + onClick = { + rootNavController.navigate(Routes.TabContainer.name) { + popUpTo(Routes.BisqUrl.name) { + inclusive = true + } + } + }, + padding = PaddingValues(horizontal = 32.dp, vertical = 12.dp), + ) + } } - - } - } } From 1f76e7ddf1d6982e809aa67b342b8174696c9311 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 9 Nov 2024 21:04:37 +0530 Subject: [PATCH 12/31] MVP pattern for Splash, Onboarding, GettingStarted screens --- bisqapps/gradle/libs.versions.toml | 2 + bisqapps/shared/domain/build.gradle.kts | 11 +++- .../data/repository/BisqStatsRepository.kt | 9 +++ .../data/repository/NetworkRepository.kt | 15 +++++ .../domain/data/repository/PriceRepository.kt | 54 +++++++++++++++++ .../composeResources/drawable/bisq_easy.svg | 9 --- .../drawable/bisq_logo_small.png | Bin 0 -> 11567 bytes .../composeResources/drawable/bot_image.svg | 9 --- .../bisq/mobile/presentation/BasePresenter.kt | 7 +++ .../ui/components/atoms/icons/Icons.kt | 19 ++++++ .../ui/components/atoms/icons/Logo.kt | 11 +++- .../ui/components/{ => molecules}/TopBar.kt | 31 +++++----- .../mobile/presentation/ui/model/model.kt | 2 +- .../ui/navigation/BottomNavigation.kt | 15 ++--- .../ui/navigation/graph/TabNavGraph.kt | 5 +- .../ui/screens/GettingStartedPresenter.kt | 38 ++++++++++++ .../ui/screens/GettingStartedScreen.kt | 18 +++++- .../ui/screens/OnBoardingPresenter.kt | 52 ++++++++++++++++ .../ui/screens/OnBoardingScreen.kt | 46 ++++++-------- .../ui/screens/SplashPresenter.kt | 30 +++++++++ .../presentation/ui/screens/SplashScreen.kt | 57 ++++++++---------- .../ui/screens/TabContainerScreen.kt | 13 ++-- 22 files changed, 340 insertions(+), 113 deletions(-) create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_logo_small.png delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/{ => molecules}/TopBar.kt (66%) create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedPresenter.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingPresenter.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt diff --git a/bisqapps/gradle/libs.versions.toml b/bisqapps/gradle/libs.versions.toml index 20bad801..5ff8d219 100644 --- a/bisqapps/gradle/libs.versions.toml +++ b/bisqapps/gradle/libs.versions.toml @@ -48,6 +48,7 @@ grpc = { strictly = '1.61.0' } i2p-lib = { strictly = '1.8.0' } i2p-v2 = { strictly = '2.4.0' } jackson-lib = { strictly = '2.17.2' } +ktorClientCore = "3.0.0" koin = "4.0.0" lombok-lib = { strictly = '1.18.34' } @@ -73,6 +74,7 @@ androidx-activity-compose = { module = "androidx.activity:activity-compose", ver androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" } androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } +ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktorClientCore" } logging-kermit = { group = "co.touchlab", name = "kermit", version.ref = "kermit" } lombok = { module = 'org.projectlombok:lombok', version.ref = 'lombok-lib' } diff --git a/bisqapps/shared/domain/build.gradle.kts b/bisqapps/shared/domain/build.gradle.kts index 68a37263..12c50ae3 100644 --- a/bisqapps/shared/domain/build.gradle.kts +++ b/bisqapps/shared/domain/build.gradle.kts @@ -35,6 +35,15 @@ kotlin { //put your multiplatform dependencies here implementation(libs.koin.core) implementation(libs.kotlinx.coroutines) + + // Coroutines + // implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0") + + // Ktor client for HTTP requests + implementation("io.ktor:ktor-client-core:3.0.0") + implementation("io.ktor:ktor-client-cio:3.0.0") // Replace with the appropriate engine for your platform + implementation("io.ktor:ktor-client-content-negotiation:3.0.0") + implementation("io.ktor:ktor-serialization-kotlinx-json:3.0.0") } commonTest.dependencies { implementation(libs.kotlin.test) @@ -56,4 +65,4 @@ android { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } -} \ No newline at end of file +} diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt new file mode 100644 index 00000000..01919f1a --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt @@ -0,0 +1,9 @@ +package network.bisq.mobile.domain.data.repository + + +class BisqStatsRepository() { + + fun getOffersOnline() = 120 + + fun getPublishedProfiles() = 610 +} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt new file mode 100644 index 00000000..bbf115b3 --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt @@ -0,0 +1,15 @@ +package network.bisq.mobile.domain.data.repository + +import kotlinx.coroutines.delay + +object NetworkRepository { + suspend fun initializeNetwork(updateProgress: (Float) -> Unit) { + //1. Initialize Tor here + //2. Connect to peers (for androidNode), to Bisq instance (for xClients) + //3. Do any other app initialization + for (i in 1..100) { + updateProgress(i.toFloat() / 100) + delay(25) + } + } +} diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt new file mode 100644 index 00000000..e41787df --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt @@ -0,0 +1,54 @@ +import io.ktor.client.* +import io.ktor.client.call.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.serialization.kotlinx.json.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.withContext +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json + +class PriceRepository { + + // Ktor client setup with ContentNegotiation plugin + private val client = HttpClient { + install(ContentNegotiation) { + json(Json { ignoreUnknownKeys = true }) // Configures JSON serialization + } + } + + /** + * Fetches the current BTC price in USD from CoinGecko API. + */ + suspend fun fetchBtcPrice(): String { + println("fetchBtcPrice()") + return withContext(Dispatchers.IO) { + try { + val response: CoinGeckoResponse = client.get("https://api.coingecko.com/api/v3/simple/price") { + parameter("ids", "bitcoin") + parameter("vs_currencies", "usd") + }.body() // Updated call to get the deserialized response body directly + println(response.toString()) + "$${response.bitcoin.usd}" + } catch (e: Exception) { + println("Error fetching BTC price: ${e.message}") + e.printStackTrace() + "Error fetching price" + } + } + } + + fun getValue() = "$70,000" +} + +@Serializable +data class CoinGeckoResponse( + val bitcoin: BitcoinPrice +) + +@Serializable +data class BitcoinPrice( + val usd: Double +) diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg deleted file mode 100644 index 76095603..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_easy.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_logo_small.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bisq_logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..9912b281ebc58816a9a78b8cb2ce9f7f6cc4b60a GIT binary patch literal 11567 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 literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg deleted file mode 100644 index 5508d6c7..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bot_image.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt index 5ee95101..75a6a275 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt @@ -1,6 +1,10 @@ package network.bisq.mobile.presentation import co.touchlab.kermit.Logger +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel /** * Presenter for any type of view. @@ -15,6 +19,8 @@ abstract class BasePresenter { * This can be used as initialization method AFTER view gets attached (so view is available) */ open fun onViewAttached() { } + // Coroutine scope for the presenter + protected val presenterScope = CoroutineScope(Dispatchers.Main + Job()) /** * This can be used as cleanup BEFORE unattaching a view @@ -36,6 +42,7 @@ abstract class BasePresenter { open fun onDestroy() { log.i { "Lifecycle: DESTROY" } + presenterScope.cancel() } fun attachView(view: Any) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt new file mode 100644 index 00000000..2f1ee88b --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt @@ -0,0 +1,19 @@ +package network.bisq.mobile.presentation.ui.components.atoms.icons + +import androidx.compose.foundation.Image +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.bell +import bisqapps.shared.presentation.generated.resources.img_bot_image +import org.jetbrains.compose.resources.painterResource + +@Composable +fun BellIcon(modifier: Modifier = Modifier) { + Image(painterResource(Res.drawable.bell), "Bell icon", modifier = modifier) +} + +@Composable +fun UserIcon(modifier: Modifier = Modifier) { + Image(painterResource(Res.drawable.img_bot_image), "User icon", modifier = modifier) +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt index 827c6b73..fcbf0f18 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt @@ -2,11 +2,18 @@ package network.bisq.mobile.presentation.ui.components.atoms.icons import androidx.compose.foundation.Image import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.bisq_logo +import bisqapps.shared.presentation.generated.resources.bisq_logo_small import org.jetbrains.compose.resources.painterResource @Composable -fun BisqLogo() { - Image(painterResource(Res.drawable.bisq_logo), "Bisq Logo") +fun BisqLogo(modifier: Modifier = Modifier) { + Image(painterResource(Res.drawable.bisq_logo), "Bisq Logo", modifier = modifier) } + +@Composable +fun BisqLogoSmall(modifier: Modifier = Modifier) { + Image(painterResource(Res.drawable.bisq_logo_small), "Bisq Logo small", modifier = modifier) +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt similarity index 66% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt index 102b390c..6508fab7 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/TopBar.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt @@ -19,6 +19,9 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import bisqapps.shared.presentation.generated.resources.Res import coil3.compose.AsyncImage +import network.bisq.mobile.presentation.ui.components.atoms.icons.BellIcon +import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogoSmall +import network.bisq.mobile.presentation.ui.components.atoms.icons.UserIcon import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi @@ -33,11 +36,7 @@ fun TopBar(title: String = "",isHome:Boolean = false) { ), title = { if (isHome) { - AsyncImage( - model = Res.getUri("drawable/logo.svg"), - contentDescription = null, - modifier = Modifier.height(34.dp).width(100.dp), - ) + BisqLogoSmall(modifier = Modifier.height(34.dp).width(100.dp),) } else { BisqText.h4Medium( text = title, @@ -48,19 +47,21 @@ fun TopBar(title: String = "",isHome:Boolean = false) { actions = { Row(verticalAlignment = Alignment.CenterVertically) { - AsyncImage( - model = Res.getUri("drawable/bell.svg"), - contentDescription = null, - modifier = Modifier.size(30.dp), - ) +// AsyncImage( +// model = Res.getUri("drawable/bell.svg"), +// contentDescription = null, +// modifier = Modifier.size(30.dp), +// ) + BellIcon(modifier = Modifier.size(30.dp)) Spacer(modifier = Modifier.width(12.dp)) - AsyncImage( - model = Res.getUri("drawable/bot_image.svg"), - contentDescription = null, - modifier = Modifier.size(40.dp), - ) +// AsyncImage( +// model = Res.getUri("drawable/bot_image.svg"), +// contentDescription = null, +// modifier = Modifier.size(40.dp), +// ) + UserIcon(modifier = Modifier.size(30.dp)) } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt index 12c3f9c9..7fcdf59d 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt @@ -2,5 +2,5 @@ package network.bisq.mobile.presentation.ui.model import org.jetbrains.compose.resources.DrawableResource -data class BottomNavigationItem(val title: String, val route: String, val icon: String) +data class BottomNavigationItem(val title: String, val route: String, val icon: DrawableResource) data class OnBoardingPage(val title: String, val image: DrawableResource, val desc: String) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt index 033fa18b..80edfd46 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt @@ -1,24 +1,22 @@ package network.bisq.mobile.presentation.ui.navigation +import androidx.compose.foundation.Image import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.size import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItemColors -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import bisqapps.shared.presentation.generated.resources.Res -import coil3.compose.AsyncImage import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.model.BottomNavigationItem import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource @OptIn(ExperimentalResourceApi::class) @Composable @@ -46,11 +44,10 @@ fun BottomNavigation( selected = currentRoute == navigationItem.route, onClick = { onItemClick(navigationItem) }, icon = { - AsyncImage( - model = Res.getUri(navigationItem.icon), - contentDescription = null, - modifier = Modifier.size(32.dp), - colorFilter = ColorFilter.tint(color = if (navigationItem.route == currentRoute) BisqTheme.colors.primary else Color.White ) + Image( + painterResource(navigationItem.icon), "", + modifier = Modifier.size(24.dp), + colorFilter = ColorFilter.tint(color = if (navigationItem.route == currentRoute) BisqTheme.colors.primary else Color.White) ) }, label = { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt index 94bd2754..011c7ffd 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt @@ -1,10 +1,12 @@ package network.bisq.mobile.presentation.ui.navigation.graph +import PriceRepository import androidx.compose.foundation.layout.PaddingValues import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable import androidx.navigation.navigation +import network.bisq.mobile.domain.data.repository.BisqStatsRepository import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.Graph import network.bisq.mobile.presentation.ui.screens.* @@ -18,7 +20,8 @@ fun NavGraphBuilder.TabNavGraph( route = Graph.MainScreenGraph ) { composable(route = Routes.TabHome.name) { - GettingStartedScreen(rootNavController = rootNavController, innerPadding = innerPadding) + val presenter = GettingStartedPresenter(priceRepository = PriceRepository(), bisqStatsRepository = BisqStatsRepository()) + GettingStartedScreen(presenter = presenter, rootNavController = rootNavController, innerPadding = innerPadding) } composable(route = Routes.TabExchange.name) { ExchangeScreen(rootNavController = rootNavController, innerPadding = innerPadding) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedPresenter.kt new file mode 100644 index 00000000..317dde50 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedPresenter.kt @@ -0,0 +1,38 @@ +package network.bisq.mobile.presentation.ui.screens + +import PriceRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import network.bisq.mobile.domain.data.repository.BisqStatsRepository +import network.bisq.mobile.presentation.BasePresenter + +/** + * Main Presenter as an example of implementation for now. + */ +class GettingStartedPresenter(private val priceRepository: PriceRepository, private val bisqStatsRepository: BisqStatsRepository) : BasePresenter(), IGettingStarted { + private val _btcPrice = MutableStateFlow("Loading...")//("$75,000") + override val btcPrice: StateFlow = _btcPrice + + private val _offersOnline = MutableStateFlow(145) + override val offersOnline: StateFlow = _offersOnline + + private val _publishedProfiles = MutableStateFlow(1145) + override val publishedProfiles: StateFlow = _publishedProfiles + + fun refresh() { + _btcPrice.value = priceRepository.getValue() + _offersOnline.value = bisqStatsRepository.getOffersOnline() + _publishedProfiles.value = bisqStatsRepository.getPublishedProfiles() + +// presenterScope.launch { +// val price = priceRepository.fetchBtcPrice() +// _btcPrice.value = price +// } + } + + override fun onResume() { + super.onResume() + refresh() + } +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt index 0ab86a1b..549b4fca 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -30,6 +31,7 @@ import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.img_fiat_btc import bisqapps.shared.presentation.generated.resources.img_learn_and_discover import coil3.compose.AsyncImage +import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.presentation.ui.components.TopBar import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.theme.* @@ -37,11 +39,21 @@ import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource +interface IGettingStarted { + val btcPrice: StateFlow + val offersOnline: StateFlow + val publishedProfiles: StateFlow +} + @Composable fun GettingStartedScreen( + presenter: IGettingStarted, rootNavController: NavController, innerPadding: PaddingValues, ) { + val btcPrice:String = presenter.btcPrice.collectAsState().value + val offersOnline:Number = presenter.offersOnline.collectAsState().value + val publishedProfiles:Number = presenter.publishedProfiles.collectAsState().value Column( modifier = Modifier .fillMaxSize() @@ -59,21 +71,21 @@ fun GettingStartedScreen( Column { PriceProfileCard( - price = "$ 60,000.00", + price = btcPrice, priceText = "Market price" ) Spacer(modifier = Modifier.height(16.dp)) Row(modifier = Modifier.fillMaxWidth()) { Box(modifier = Modifier.weight(1f)) { PriceProfileCard( - price = "101", + price = offersOnline.toString(), priceText = "Offers online" ) } Spacer(modifier = Modifier.width(16.dp)) Box(modifier = Modifier.weight(1f)) { PriceProfileCard( - price = "4,223", + price = publishedProfiles.toString(), priceText = "Published profiles" ) } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingPresenter.kt new file mode 100644 index 00000000..c066ce20 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingPresenter.kt @@ -0,0 +1,52 @@ +package network.bisq.mobile.presentation.ui.screens + + +import androidx.compose.foundation.pager.PagerState +import androidx.navigation.NavController +import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.img_bisq_Easy +import bisqapps.shared.presentation.generated.resources.img_fiat_btc +import bisqapps.shared.presentation.generated.resources.img_learn_and_discover +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import network.bisq.mobile.presentation.ui.model.OnBoardingPage +import network.bisq.mobile.presentation.ui.navigation.Routes + +val onBoardingPages = listOf( + OnBoardingPage( + title = "Introducing Bisq Easy", + image = Res.drawable.img_bisq_Easy, + desc = "Getting your first Bitcoin privately has never been easier" + ), + OnBoardingPage( + title = "Learn & Discover", + image = Res.drawable.img_learn_and_discover, + desc = "Get a gentle introduction into Bitcoin through our guides and community chat" + ), + OnBoardingPage( + title = "Coming soon", + image = Res.drawable.img_fiat_btc, + desc = "Choose how to trade: Bisq MuSig, Lightning, Submarine Swaps,..." + ) +) + +class OnBoardingPresenter( + private val navController: NavController, + val pagerState: PagerState, + private val coroutineScope: CoroutineScope, +) { + // private val coroutineScope = CoroutineScope(Dispatchers.Main) + + fun onNextButtonClick() { + coroutineScope.launch { + if (pagerState.currentPage == onBoardingPages.lastIndex) { + navController.navigate(Routes.CreateProfile.name) { + popUpTo(Routes.Onboarding.name) { inclusive = true } + } + } else { + pagerState.animateScrollToPage(pagerState.currentPage + 1) + } + } + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt index cc75a067..f3d63128 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -45,28 +46,13 @@ import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource -val list = listOf( - OnBoardingPage( - title = "Introducing Bisq Easy", - image = Res.drawable.img_bisq_Easy, - desc = "Getting your first Bitcoin privately has never been easier" - ), - OnBoardingPage( - title = "Learn & Discover", - image = Res.drawable.img_learn_and_discover, - desc = "Get a gentle introduction into Bitcoin through our guides and community chat" - ), - OnBoardingPage( - title = "Coming soon", - image = Res.drawable.img_fiat_btc, - desc = "Choose how to trade: Bisq MuSig, Lightning, Submarine Swaps,..." - ) -) -private lateinit var pagerState: PagerState - @OptIn(ExperimentalResourceApi::class) @Composable fun OnBoardingScreen(rootNavController: NavController) { + val coroutineScope = rememberCoroutineScope() + val pagerState = rememberPagerState(pageCount = { onBoardingPages.size }) + val presenter = remember { OnBoardingPresenter(rootNavController, pagerState, coroutineScope) } + BisqScrollLayout() { BisqLogo() Spacer(modifier = Modifier.height(24.dp)) @@ -75,8 +61,15 @@ fun OnBoardingScreen(rootNavController: NavController) { color = BisqTheme.colors.grey1, ) Spacer(modifier = Modifier.height(56.dp)) - PagerView() + PagerView(presenter) Spacer(modifier = Modifier.height(56.dp)) + + BisqButton( + text = if (pagerState.currentPage == onBoardingPages.lastIndex) "Create profile" else "Next", + onClick = { presenter.onNextButtonClick() } + ) + + /* Column { val coroutineScope = rememberCoroutineScope() BisqButton( @@ -95,14 +88,13 @@ fun OnBoardingScreen(rootNavController: NavController) { ) } + */ } } @Composable -fun PagerView() { - - pagerState = rememberPagerState(pageCount = { list.size }) +fun PagerView(presenter: OnBoardingPresenter) { CompositionLocalProvider(values = arrayOf()) { Column( @@ -114,10 +106,10 @@ fun PagerView() { contentPadding = PaddingValues(horizontal = 36.dp), pageSize = PageSize.Fill, verticalAlignment = Alignment.CenterVertically, - state = pagerState + state = presenter.pagerState ) { index -> - list.getOrNull( - index % (list.size) + onBoardingPages.getOrNull( + index % (onBoardingPages.size) )?.let { item -> BannerItem( image = item.image, @@ -127,7 +119,7 @@ fun PagerView() { ) } } - LineIndicator(pagerState = pagerState) + LineIndicator(pagerState = presenter.pagerState) } } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt new file mode 100644 index 00000000..1943d68c --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt @@ -0,0 +1,30 @@ +package network.bisq.mobile.presentation.ui.screens + +import androidx.navigation.NavController +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import network.bisq.mobile.domain.data.repository.NetworkRepository +import network.bisq.mobile.presentation.ui.navigation.Routes + +class SplashPresenter( + private val navController: NavController, + private val onProgressUpdate: (Float) -> Unit +) { + private val coroutineScope = CoroutineScope(Dispatchers.Main) + + fun startLoading() { + coroutineScope.launch { + NetworkRepository.initializeNetwork { progress -> + onProgressUpdate(progress) + } + navigateToNextScreen() + } + } + + private fun navigateToNextScreen() { + navController.navigate(Routes.Onboarding.name) { + popUpTo(Routes.Splash.name) { inclusive = true } + } + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index a2499e33..ad7fce23 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -27,46 +27,39 @@ import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout import network.bisq.mobile.presentation.ui.theme.* +// TODO: Remove innerPadding once StaticLayout, ScrollLayout are fully done. @OptIn(ExperimentalResourceApi::class) @Composable -fun SplashScreen(rootNavController: NavController, - innerPadding: PaddingValues) { - BisqStaticLayout() { - BisqLogo() - LoadingProgress(rootNavController) - } -} +fun SplashScreen( + rootNavController: NavController, + innerPadding: PaddingValues +) { -@Composable -fun LoadingProgress(navController: NavController) { var currentProgress by remember { mutableFloatStateOf(0f) } - val scope = rememberCoroutineScope() - Column { - LaunchedEffect(true) { - scope.launch { - loadProgress { progress ->currentProgress = progress } - navController.navigate(Routes.BisqUrl.name) { - popUpTo(Routes.Splash.name) { inclusive = true } - } - } + val presenter = remember { + SplashPresenter(rootNavController) { progress -> + currentProgress = progress } + } - BisqProgressBar(progress = currentProgress) + LaunchedEffect(Unit) { + presenter.startLoading() + } - BisqText.baseRegular( - text = "Connecting to Tor Network...", - color = BisqTheme.colors.secondaryHover, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth(), - ) + // Render the layout + BisqStaticLayout { + BisqLogo() - } -} + Column { + BisqProgressBar(progress = currentProgress) -suspend fun loadProgress(updateProgress: (Float) -> Unit) { - for (i in 1..100) { - updateProgress(i.toFloat() / 100) - delay(25) + BisqText.baseRegular( + text = "Connecting to Tor Network...", + color = BisqTheme.colors.secondaryHover, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth(), + ) + } } -} \ No newline at end of file +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt index ca295f47..967f0b38 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt @@ -8,6 +8,11 @@ import androidx.compose.runtime.remember import androidx.navigation.NavController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController +import bisqapps.shared.presentation.generated.resources.* +import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.home +import bisqapps.shared.presentation.generated.resources.icon_question_mark +import bisqapps.shared.presentation.generated.resources.trades import network.bisq.mobile.presentation.ui.model.BottomNavigationItem import network.bisq.mobile.presentation.ui.navigation.BottomNavigation import network.bisq.mobile.presentation.ui.navigation.Graph @@ -16,10 +21,10 @@ import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph import network.bisq.mobile.presentation.ui.theme.BisqTheme val navigationListItem = listOf( - BottomNavigationItem("Home", Routes.TabHome.name, "drawable/home.svg"), - BottomNavigationItem("Buy/Sell", Routes.TabExchange.name, "drawable/market.svg"), - BottomNavigationItem("My Trades", Routes.TabMyTrades.name, "drawable/trades.svg"), - BottomNavigationItem("Settings", Routes.TabSettings.name, "drawable/settings.svg"), + BottomNavigationItem("Home", Routes.TabHome.name, Res.drawable.home), + BottomNavigationItem("Buy/Sell", Routes.TabExchange.name, Res.drawable.market), + BottomNavigationItem("My Trades", Routes.TabMyTrades.name, Res.drawable.trades), + BottomNavigationItem("Settings", Routes.TabSettings.name, Res.drawable.settings), ) From a27d71aa184376e4928c1c215faf58aa308b8e02 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sun, 10 Nov 2024 20:45:48 +0530 Subject: [PATCH 13/31] i18n - Done in splash screen with lyricist package --- bisqapps/gradle/libs.versions.toml | 2 + bisqapps/shared/presentation/build.gradle.kts | 40 ++++++++----------- .../mobile/presentation/i18n/EnStrings.kt | 8 ++++ .../mobile/presentation/i18n/FrStrings.kt | 8 ++++ .../bisq/mobile/presentation/i18n/Locales.kt | 6 +++ .../bisq/mobile/presentation/i18n/Strings.kt | 7 ++++ .../bisq/mobile/presentation/ui/App.kt | 37 ++++++----------- .../ui/components/layout/StaticLayout.kt | 6 ++- .../presentation/ui/screens/SplashScreen.kt | 6 ++- 9 files changed, 70 insertions(+), 50 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt diff --git a/bisqapps/gradle/libs.versions.toml b/bisqapps/gradle/libs.versions.toml index 5ff8d219..e73376c0 100644 --- a/bisqapps/gradle/libs.versions.toml +++ b/bisqapps/gradle/libs.versions.toml @@ -49,6 +49,7 @@ i2p-lib = { strictly = '1.8.0' } i2p-v2 = { strictly = '2.4.0' } jackson-lib = { strictly = '2.17.2' } ktorClientCore = "3.0.0" +lyricist = "2.0.20-1.0.25" koin = "4.0.0" lombok-lib = { strictly = '1.18.34' } @@ -76,6 +77,7 @@ androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktorClientCore" } logging-kermit = { group = "co.touchlab", name = "kermit", version.ref = "kermit" } +lyricist = { module = "cafe.adriel.lyricist:lyricist", version.ref = "lyricist" } lombok = { module = 'org.projectlombok:lombok', version.ref = 'lombok-lib' } diff --git a/bisqapps/shared/presentation/build.gradle.kts b/bisqapps/shared/presentation/build.gradle.kts index 6b887e92..8f8f6d9c 100644 --- a/bisqapps/shared/presentation/build.gradle.kts +++ b/bisqapps/shared/presentation/build.gradle.kts @@ -9,6 +9,7 @@ plugins { alias(libs.plugins.jetbrainsCompose) alias(libs.plugins.compose.compiler) alias(libs.plugins.buildconfig) + id("com.google.devtools.ksp") version "2.0.20-1.0.25" } dependencies { @@ -94,11 +95,9 @@ kotlin { implementation("io.coil-kt.coil3:coil-svg:3.0.0-rc02") implementation("org.jetbrains.androidx.navigation:navigation-compose:2.7.0-alpha07") - //implementation("androidx.navigation:navigation-compose:2.8.3") - //https://github.com/Kamel-Media/Kamel - //implementation("media.kamel:kamel-image:1.0.0") - //implementation("media.kamel:kamel-decoder-svg-std:1.0.0") - //implementation("io.ktor:ktor-server-netty:3.0.0") + + implementation("cafe.adriel.lyricist:lyricist:1.7.0") + } val commonTest by getting { dependencies { @@ -123,22 +122,17 @@ android { targetCompatibility = JavaVersion.VERSION_1_8 } } - dependencies { - //implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.0-rc02") - //implementation("io.ktor:ktor-client-android:3.0.0") + +dependencies { + add("kspCommonMainMetadata", "cafe.adriel.lyricist:lyricist-processor:1.7.0") +} + +tasks.withType>().all { + if(name != "kspCommonMainKotlinMetadata") { + dependsOn("kspCommonMainKotlinMetadata") } -// dependencies { -// implementation("media.kamel:kamel-fetcher-resources-android:1.0.0") -// } - - -//appleMain { -// dependencies { -// implementation("io.ktor:ktor-client-darwin:3.0.0") -// } -//} -//jvmMain { -// dependencies { -// implementation("io.ktor:ktor-client-java:3.0.0>") -// } -//} +} + +kotlin.sourceSets.commonMain { + kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt new file mode 100644 index 00000000..bd85130c --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt @@ -0,0 +1,8 @@ +package network.bisq.mobile.presentation.i18n + +import cafe.adriel.lyricist.LyricistStrings + +@LyricistStrings(languageTag = Locales.EN, default = true) +public val EnStrings = Strings( + splash_loading_text = "Connecting to Tor Network...", +) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt new file mode 100644 index 00000000..9166d156 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt @@ -0,0 +1,8 @@ +package network.bisq.mobile.presentation.i18n + +import cafe.adriel.lyricist.LyricistStrings + +@LyricistStrings(languageTag = Locales.FR) +public val FrStrings = Strings( + splash_loading_text = "[FR] Connecting to Tor Network...", +) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt new file mode 100644 index 00000000..d9102ceb --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt @@ -0,0 +1,6 @@ +package network.bisq.mobile.presentation.i18n + +object Locales { + const val EN = "en" + const val FR = "fr" +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt new file mode 100644 index 00000000..009b760f --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt @@ -0,0 +1,7 @@ +package network.bisq.mobile.presentation.i18n + +import androidx.compose.ui.text.AnnotatedString + +public data class Strings( + val splash_loading_text: String, +) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index d864123c..be3d0588 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -3,12 +3,15 @@ package network.bisq.mobile.presentation.ui import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.* import androidx.navigation.compose.rememberNavController +import cafe.adriel.lyricist.ProvideStrings +import cafe.adriel.lyricist.rememberStrings import org.jetbrains.compose.ui.tooling.preview.Preview import kotlinx.coroutines.flow.StateFlow import org.koin.compose.koinInject import network.bisq.mobile.presentation.ui.screens.OnBoardingScreen import network.bisq.mobile.presentation.ui.screens.SplashScreen +import network.bisq.mobile.presentation.i18n.Locales import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph @@ -32,33 +35,17 @@ fun App() { val presenter: AppPresenter = koinInject() val navController = rememberNavController() + val lyricist = rememberStrings() + lyricist.languageTag = Locales.FR BisqTheme(darkTheme = true) { - RootNavGraph( - rootNavController = navController, - innerPadding = PaddingValues(), - startDestination = Routes.Splash.name - ) + ProvideStrings(lyricist) { + RootNavGraph( + rootNavController = navController, + innerPadding = PaddingValues(), + startDestination = Routes.Splash.name + ) + } } - //MaterialTheme { - //SplashScreen() - //OnBoardingScreen() - //} - -// Collecting state from presenter -// val showContent by presenter.isContentVisible.collectAsState() -// val greeting by presenter.greetingText.collectAsState() -// Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { -// Button(onClick = { presenter.toggleContentVisibility() }) { -// Text("Click me!") -// } -// AnimatedVisibility(showContent) { -// Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { -// Image(painterResource(Res.drawable.compose_multiplatform), null) -// Text("Compose: $greeting") -// } -// } - - } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt index 792541db..c6b1034d 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt @@ -8,7 +8,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import cafe.adriel.lyricist.Lyricist +import cafe.adriel.lyricist.ProvideStrings +import cafe.adriel.lyricist.rememberStrings import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.i18n.Strings @Composable fun BisqStaticLayout( @@ -26,7 +30,7 @@ fun BisqStaticLayout( .background(color = BisqTheme.colors.backgroundColor) .padding(innerPadding) ) { - content() + content() } } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index ad7fce23..e0ba1c7e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -22,6 +22,8 @@ import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.navigation.Routes import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.bisq_logo +import cafe.adriel.lyricist.LocalStrings +import cafe.adriel.lyricist.rememberStrings import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout @@ -43,6 +45,8 @@ fun SplashScreen( } } + val strings = LocalStrings.current + LaunchedEffect(Unit) { presenter.startLoading() } @@ -55,7 +59,7 @@ fun SplashScreen( BisqProgressBar(progress = currentProgress) BisqText.baseRegular( - text = "Connecting to Tor Network...", + text = strings.splash_loading_text, // "Connecting to Tor Network...", color = BisqTheme.colors.secondaryHover, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth(), From 51e820c654cf0b7e2e5ab358795816dfab0ecec4 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sun, 10 Nov 2024 21:41:01 +0530 Subject: [PATCH 14/31] Resources - Cleanup --- .../composeResources/drawable/bell.svg | 4 - .../drawable/compose-multiplatform.xml | 36 ------- .../composeResources/drawable/copy.svg | 10 -- .../drawable/currency_euro.png | Bin 0 -> 2010 bytes .../drawable/currency_gpb.png | Bin 0 -> 2358 bytes .../drawable/currency_usd.png | Bin 0 -> 1975 bytes .../composeResources/drawable/euro.svg | 9 -- .../composeResources/drawable/fiat_btc.svg | 9 -- .../composeResources/drawable/filter.xml | 9 -- .../drawable/flag_of_india.xml | 96 ------------------ .../composeResources/drawable/gpb.svg | 9 -- .../composeResources/drawable/home.svg | 3 - .../drawable/ic_star_empty.xml | 10 -- .../drawable/ic_start_filled.xml | 10 -- .../composeResources/drawable/icon_bell.png | Bin 0 -> 552 bytes .../composeResources/drawable/icon_copy.png | Bin 0 -> 828 bytes .../composeResources/drawable/icon_copy.svg | 3 - .../composeResources/drawable/icon_home.png | Bin 0 -> 847 bytes .../composeResources/drawable/icon_market.png | Bin 0 -> 924 bytes .../composeResources/drawable/icon_qr.png | Bin 0 -> 440 bytes .../composeResources/drawable/icon_qr.svg | 12 --- .../drawable/icon_question_mark.png | Bin 0 -> 1254 bytes .../drawable/icon_question_mark.svg | 3 - .../drawable/icon_settings.png | Bin 0 -> 1351 bytes .../composeResources/drawable/icon_sort.png | Bin 0 -> 297 bytes .../composeResources/drawable/icon_trades.png | Bin 0 -> 480 bytes .../drawable/learn_and_discover.svg | 9 -- .../composeResources/drawable/logo.svg | 9 -- .../drawable/logo_with_slogan.svg | 9 -- .../drawable/logo_with_slogan_xml.xml | 10 -- .../composeResources/drawable/market.svg | 3 - .../composeResources/drawable/qr.svg | 12 --- .../drawable/question_mark.svg | 3 - .../composeResources/drawable/right_arrow.svg | 3 - .../drawable/rounded_browser.svg | 4 - .../drawable/rounded_chat.svg | 4 - .../drawable/rounded_star.svg | 4 - .../composeResources/drawable/settings.svg | 3 - .../composeResources/drawable/sort.svg | 3 - .../composeResources/drawable/trades.svg | 10 -- .../composeResources/drawable/usd.svg | 9 -- .../ui/components/CurrencyProfileCard.kt | 13 +-- .../ui/components/atoms/icons/Icons.kt | 11 +- .../ui/components/molecules/TopBar.kt | 14 --- .../presentation/ui/screens/ExchangeScreen.kt | 18 ++-- .../ui/screens/TabContainerScreen.kt | 11 +- .../presentation/ui/screens/URLScreen.kt | 10 -- 47 files changed, 27 insertions(+), 368 deletions(-) delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/compose-multiplatform.xml delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/currency_euro.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/currency_gpb.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/currency_usd.png delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_bell.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_copy.png delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_copy.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_home.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_market.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_qr.png delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_qr.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.png delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_settings.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_sort.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_trades.png delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/learn_and_discover.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg delete mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg deleted file mode 100644 index e86007f0..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/bell.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/compose-multiplatform.xml deleted file mode 100644 index c0bcfb28..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/compose-multiplatform.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg deleted file mode 100644 index b63853df..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/copy.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/currency_euro.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/currency_euro.png new file mode 100644 index 0000000000000000000000000000000000000000..31d48fe01e3df012465ff61af7e7faff6127e8d2 GIT binary patch literal 2010 zcmV<02POE4P)C$SSJaXy=-O_~}rDNPqjLpmTWE$XP+QEi>JX__=Tbxa##6G9YJ!K7-{ z;J-;l0-;S4LIorQ5?`f23oWDwrAZoE(k3x=;-q#Or-|bv{(K*t`<#-d^|Kwd;@D4q ze)rsafA`#Te&^f=+@k2Z&eLV}`E;4x;}(TmmNr@~aC;hr>J95f*>*Q)En3S<1ukB+ z7J=iSr4sX6GCH9pW-q9*c#k@Mwg&_M8={U{zBA+pXvIA?)a_Ug$BN&>YTpLlQbSik zx=}a2i=%PuKYdbhaLN$k;m?qoKZ^eUe}O=EG}lzQ0eSY;W7W_0!|L1((N+mf#j=DG z$Ud1r4S9-1&>-+SG(F#-4S!m+kmtAe zLN48H7EKN*g)%vbn!*@1tqK^=reZRVecOo2;yL5`sJ{`Bgan?`(M~!{x27-rFwFKkZ9$b| z9v$Q>^bcS7YS9}k$HmDK^aWjpTUad$We^?rtPEmj^B^{_9l`O7t04&*()*Xe6?EDW zd(AJgcIOKid~ee5A)#g8HeGf;LSb&nh=;(es|_JVzF`qn9C)t-7p|6&H3XzI-k8Sl zZ!PTs(@`7x#;UN!HH~+_aU(&Eqtgy^pW-;1C>0*pe4qFX3-OX=qsm!qCge#SbaeV^ zjO!F#g9Ij;w7^W}QX=}va!(QP-hgYt!LtMkC(0uDdlle>u_QsVug#(jr<^djhOMw~ z+=W;cFxMnbpw66p=9FDaHbYWi9NM)iOLU6}n8VLr(f=dmrwsn8KRUFl0eN zK8b|sSa}ueYbMZKc@=-W`#g;$m}+yfqn5A;%t8`xk?fh&BtgYa&n5h>wI3(`_BtN& z_>fdYLN@PlR4bfn67 ziS^?-%^1tHH&d!k^H5SvC1)uk-K3Ks6Td^m=c&DdqZb;DaF@hXnu+reNmS5zX$7_( z{tX^*5996gO*EsD5xJI#MhH(r=WTk4b|tl)Xd=w$YdE5}h_$z80;G>+IIQH2&2+I_1CW|X^-zT#Gaa3*v9W#}kG7q|bKAef9c5txrI@N05Eysa z4C!{_&l|o)TYbS#&>da1zy5d#Bexoi*d*{GwLs)hHG1%+YnB_Az?cjJR z!t+*qKC}uw3k>XWh0)RIM}ef`_5KAd`zIK>;e_IN4u$*vhV-F+ycqY5wNS69=v`N$dr zQzg(CkbH?;OO9arn@4c*?SUo3-K02n%8!-p5lAIlV9G=4umoYu?cWBCFdVt#`#x^B~`I(U?p4~kA3NkQd_M`NsXST!DdYJ0% z2J`YZPce?tb3RO--;2)YPQv7kNbco38;Y@E{~;7s{tCRc0{Sw6v6l^cB81uCt2p!g zK}=to$)+yk956neFwRYJ$1#c?l};w?HH?EM64UFszIf*re1vE08;6?mBjTm79(fXx zBX8nT|8003bK?S9_tlC;jg6v3*d$n;&3b{ePLK*56k?pJ#Afw)IH1NRy0s*CS_zyu s2k+4keoSFy=cumR0)apQyT>ic_b$onJfJQG@&Et;07*qoM6N<$g503X{Qv*} literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/currency_gpb.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/currency_gpb.png new file mode 100644 index 0000000000000000000000000000000000000000..643fb3b616b4ab6e85eb985ab37b213972d36092 GIT binary patch literal 2358 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 JPDHLkV1fwKvU~sl literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg deleted file mode 100644 index c3edfee1..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/euro.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg deleted file mode 100644 index 64451f40..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/fiat_btc.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml deleted file mode 100644 index 2972f723..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/filter.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml deleted file mode 100644 index fd210361..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/flag_of_india.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg deleted file mode 100644 index 067ea620..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/gpb.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg deleted file mode 100644 index 085646c4..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/home.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml deleted file mode 100644 index be22f749..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_star_empty.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml deleted file mode 100644 index 7d7dc714..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/ic_start_filled.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_bell.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_bell.png new file mode 100644 index 0000000000000000000000000000000000000000..eda31a647dca9e2d7928e4dbef7574ff2a923ad1 GIT binary patch literal 552 zcmV+@0@wYCP)(f z!Y~lVFF`^)(hV{~J3-qC+6@X40`Wwdpk;#6C&V8qbc1$-GC|p(8G&a+l71(J7er$F z5~n=)Cn2KbY=1fX?7I*-9RG_)B?!Z?eK;IOX`0^Q7vNTqJ=%Gmx5d4$BuPGp!(l{1 zL;`2CSPt%?uQ{F~l6meNI|R>-&YIMkVgv+FOI6~SHV2uG zq0)ny_kPI&&1Une+wJa(Y?K~^xJRrln-p9FTxgLbL zSE>n&m7Ba4O|i`*?v&h=D_0;g-ZB0nvJYq16LMHW{AB?(ZfatWDo!+(c%w!({B2;q zB_U#g$c8t%ws@I$5+W9eij4QJNW(Ph_xo!SA{NNyBDRNnDi#@KHeyPBemjENxr5_s qbS$uVed2W3v|6pHs_u0-E}cJ@w4GZ@IRsEN$O08!{HMtU{D4;@o)IpqKp`ZaX%Og zJ}4y>Qe?eeKSKOFX%NqxPA8>yYNWt&x%`74oXW1DCpVYN>0SP;-Ob`LR3=m~kse_2hr@xzw}nej5I?0GAk+i%`P|&^_wRyu7d_v{rgIbG8L04e>nj@!WNj#wVpiFw#? z&yye?4LmfP%|HXF%c8cvAL@$BD1^P>?Js4+Z8RFc`u)D^FAR79z0874p}55!fmlil zuU|TfG5X5gI#6MuDC7DYdc;1St5NiOh_biH% zVe=mzZV+!qwCTzwqzHC?2X!OsB=LZqB(`BfRxbyySG->63TPWboEv!J{b4cpU>D(r z8P}7lDCYxyyxc%4KFLtYLS_%Jc!ba!e;Fdwk9xh{71!)*kjVoaUQ5K=d5LF~Js`^s z@ST&H9_5H?O4*iVWez5>gRns?55zq>Q8EC-qy=yQUI&38#EA%!^LvEGy|9~fJzdd(bPjlV>?G_aT~AkZQ0@aoQyNe-KR=X6Lfq38 zRg#=$XffbgOKOtS45cB2hHqx4Rx*J9s{}^8QjUb3W_$sih-SS=Qd+kF0000 - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_home.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_home.png new file mode 100644 index 0000000000000000000000000000000000000000..8e63f66d919ee47ae0fe20b04a874f56f112b696 GIT binary patch literal 847 zcmV-V1F-ywP)CNUk96z)l5n2WAO5>zRK9N+347 z6saAXK+F#i2rfC?`S&q9yCO|49t_DF~<2{9N9uHgKV%+50hfs@JPii8jmFq_T3=ks}P z`ErEUEBpO^$u=Z_wSeh#`g6P8E=X}6L*=1ZEPlfEGaSBG?bwEG$r7tMFdmQZaOtY$ zaJq+a?gq;+KU@r-e;h`cTd&u9bRicB;7GGxukX;ZHO=E6&1SQ&vonbRkLWGuk_Z)B z07sf!F82%0s}qqcci{YEm_2&!2A4T0Lyki&hE+9ggo-5~BusjU{nbvV^J4p*xM4Q( zB=*CkvC^o{GwdMSu&weac9@MMAP^=i!E)|)jNLDnEKElc{wf`W!|YSkFne|gai~K@ zu3FAv5>C`efYE5whmc#fJW7NL?ST;Ids5CbtyZhc-_+FOo?9!7J>XBYSIr}1n6$+d zX8no%tg|up079kuAr6z(w{o8G7r&}s*9i=-uF1wI02Ap(DLNbDCEz;H;?-ao1bj8U zA2tWd>WAr_&r=Cq*hCY4Rk*aW9O?f6YJLJN~MB-)J-zB!oy0@S3q&t(Ls- zn4D)ggT-%-jP#XlNB|K5XEyRW4oMsL8d+j304-Ugc+MZ;Uh9%2)^h+WHjn$$Jtujk zQmL!%uKXdxslqAC3|pY0V%-CpotdlK8glx~!W7$UvP3+LhV2ccPvw|&AxoN6K+>cF zlIG(GkjPu25+~6!3cxb|9K7elT&WB)3~ngRfr9bW&v>kYl-I?@`utu3G^S(PLl}Di zM}~ZS;!*N=VH+T$0M1(s2e9wS@etTZq~mqY`Tew6?9aI{c>dwPg5Stq`)`o|rlkB& Z`~~dKWp0EZixdC=002ovPDHLkV1geDhCu)T literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_market.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_market.png new file mode 100644 index 0000000000000000000000000000000000000000..ef981d6cf7dc78e6bf890cfad36a1195927528fe GIT binary patch literal 924 zcmV;N17rM&P))DWZ-oKD@OoCU^oE9$v6U*43+~$0SDm-Y)7zi1SSM!V2%`DcTg0 zfG8b!RVp$6?s>0!MhNl56E`6zGK$G$@=_=ihPhm>ie-4aola*&`(@Gr$8oCL?e;JH ztjYDq130tX0O-# z#r4e`1GCu-ZI&O_0OCGAfJX@J{%4|qWV9?0ZfbdnEEXi3tJHR z(6mXBx&vU;5OVrId_doWsJ^iKU*)n%K8REuz#WCu_a;>hqnM!C$0Q#_st$lbLsC_R zL+XX=>&vGmRT<@jNX>!ibXsHbIUZ6CuKzXiL8RsY7{KZs4drB%H2VZd(}B9C=|V=p zR!bzzJ^_qZ37i~ge+7fqaJ?P1+wHY!j32x;T|3N&vEfSPIxrBn$CVEvl7abr?!XPu zfyrB7&|tUQ{S-04=y^rj?LbC;tkAd^iafr zSki*FP!0IQ4ba3wOT?7Vy&*I3iL|lDImZItm*lcZKKFzi#L68Vg6ryh{V4e$WCs+3 zE0v1&LdCHl!F!Z^5TOIGt8M?r=)v>dl-6`CB)QAq12_G>4&MtOH2Ar{z|+J{pOna& yP^ITR(s;y84*1uMv-I%U@Apmd#1l_E6#oHXY0)>)!>nTf0000&JHhyn#3Kg@o|v4fF=SlJKB6;|N>;bc>R(#+LuGEkUziVjSClrCHjw5M?r% z?`9`0bX|8G$MI^0r6B2xqBvJob!YlPn1}3e{)A0rjGh&vmc#qSTrbT-c3=nXMp~y7 z^wKXg_E4`{gs*FLJ)RA9V2TglCd{7sn#ycQI01dqKaP_pRv; iDQa<0jm~5;zs3`6FEf-pWSEfv0000 - - - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.png new file mode 100644 index 0000000000000000000000000000000000000000..98ede35a994f909a147fcaf518eaadd256eb60b3 GIT binary patch literal 1254 zcmV6191Y#3BV@^IRW;9-^%6$m=j>H_*P*~Kym`i32;t;a)Nk8QGD~BGltP< zq?wUb$s&GLD$Ao$_jFJHrX@1Q82>jWq$Hf3ovppTzOLYQ6&HUO)kX9tCMM#yx3?Jg zKPD$9yPKPvT`2)032`fYZ~{I!vJ{;Tm^=J94nKwbcoEDM)~mlaoWq);jI{8#H+Xljsrb=0>{A9mvp1T=wEUc=q96 zOIiLfokeVFYHA;LAL(O0iytO8I{eV-m1f(n5J}n)q5>gqe zGto392RXJpgx3x#vpLkqunV7TyI}PJYTsn+TKs@m{^E%Uw6DYg71?5a47*_U1*-sN zyk~|K2b9A{u6Yc{2+LJ*qiy`J+a{$1U{z@>r0^BiyjlB z{K+*#EJ8_ZDZb_am?b8$JP;2khOv65J3l|)pv}_Wd9Tm4B*hezy?@uoSc;hQQc(!Z zm%%_Ex)Bd3hD(e>rn5afJS>8_gaXR!;=T9XQl_2A{5GnQ@xLblFc(jO%%EUNSXSV@ zp7GwYIVZIPX6#2%6-xn}pPz4_GHoGx*s9J;9~$J1_w}I^E!z$xCWTa(I7QUaLCq501tb(Dp-S0+wO!a*jIV$kV$WpWc1-my6+ zC4ePDIAgXA(Dog(k)Kp0)sbCNCm z+A?us5(uo9i;X05r!*i5dj4xGI5Q9za?A3)da*B@n7O)D;)2wIz@h zM!hP*JZO0!VnUNZmRr-*XmoBw&dEgRX^gwvoVYw`!wA`Z$x8 zYw^UicmQ?zSJWlf=24K&hUiocZHp`as^Ye8o<9gGj68j41+~{R%xQ?eIzO`%VRt#v zURQX2aAoAMcBcf2ZyU-^l<#bK)Xpi`STA!PnYZf{Ejr5UE6ND9O zBw=8JYoq1TDtc@sO8d;prjz=7vps}-N7d)TVXcF7-NLvH|Gpt%d+&C Q0ssI207*qoM6N<$g8wQ*VgLXD literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg deleted file mode 100644 index e68697a1..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_question_mark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_settings.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..5f87423e7ac1603549f7867da00b5425a699d687 GIT binary patch literal 1351 zcmV-N1-SZ&P)}tAbz=4ArXv5pczO8(;3L8yK@e{#@Cm(wAg+P zr>YBh{g%5g50Np(_`fkBCF1=2eC_4srG>8*&y*BTV{2>cQcA+4ln4;t6hHAqf~PGd zqBI81&d!$Poxm6>M@L6XQWB;=Gr8SvSDv4rci-OLRwgDUF7dsyv$K=(9mdv*?lUzt zwStcud(YR`*BbV`nVFes)a&(L(Y*@$01tY4db$Ro3)XNtIXQVjM(}wpmIgpj70li6 zJ0))3XXwq&&i*un?}=r0V4@2qszsS7#DIr*8$HR}ehNqZX-_ygIk{7F^qLQ%KEXuP z2MQ1`nh=_To`Ch8&>A&&foJk;i6F>;k9bN*-b11bJw&5@877M1)hE%O-mfSVK?bnF zfs1&m*O*AdKA4h+T~{;5w!tyj`=VifKsd(s=?{4HyFL?-kB@s2K+p$Zw|^xc8dDym zZ4*wKWJF2G z2-4PeTZyUkD}W|zqBM@@BD5x`0V9z^$!lR3Pt&)?WaMQ?ZY3ke*mjrB9nuzZg?$dC z--&5Ang?i?kUD)~pjtW|m`fe=NI*3TiY6GAodjQLe+3Pe&!T$8Ffd%7xxkJQDVAQRJTNQ{BR zG1h|`4_!71sr*)R`?-RJTxKF{U^u3UGgavTCfQZxJ$$DQI)(%rEvN0O(gSVx&T^Pz zka*p$N?|U`qO@lORO5F?6+47zF&80TwBv@_#rgU9t{O_@3uhChwviL!Ti&KFfM%&DO${BYLx=T+{42|)Ak1!DEYa$xn_}K&YTmBT+t{5hguVL{(7J?cu z(od|R^t*^BM(F^94Dbrk{tfB(T$vVQNs&7oYkq}mJg>F1gIAWZTZyLRRXT_u{I0JC z`3@0d)z?MQBoQjxR?Sb}*r!$lcTg92UzbrB2!zMf5bct>vlVptlf56c>$`&**$23g z8#q#aBL0L^fs}{r*7OaDXH7B+@kBI?2AHssJH&O>?r0Uggq3=^O9Yr0Tn#FMa(`kt z{`}~h8P|#`TfXIbJ%dU240XSFXM+Z%l^t|^eB6py7jNEW(>Zu<&xHor zHL?*5;?}o?G8mN9X072kDIkn(6d(UH=bWd-R zN|yV5+;VQ$>GekUKIuRI-u~Apoy|Sw-{GbF_UtVJ>prGW{;VxOWZm9{{m{k_PSm>6L3K11I>i8eMq zn_cLEs;a)buKU+t+bqkDd7hsM2<5vu1Yhf~d;R$uM4)gA7{Qyg1jeL*BY5ij{*S6H`2t^7o~$gQd*+w3#ZXNrDt`0QTjdq zrL?p$_2qhq%d$KurB3!u{cax6dLNrd8kH(BDr6ERo>~cM5|i_QB#Fsxl&ddSVf(tM zdB7ndV;;C;NHi3guU|!QCVn?dXK+Pe487TX2CrGj_dJ{cS-n|E0#0D6H}grrodIS^ z9fA~K=1RZ{FmoiJ1(=Y;Y5^l(C!6S4Vs#cW@^v!!2aHLh5VQ1ZfgxWvlo0OC;16+V z=>{z@XJZH}Fn8SvDX?T$i#iX~_I1~y8Fd~Q;oFkK&jX - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg deleted file mode 100644 index ca281a8f..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg deleted file mode 100644 index 239aa1bb..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml deleted file mode 100644 index ac2a8116..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/logo_with_slogan_xml.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg deleted file mode 100644 index 036bda12..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/market.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg deleted file mode 100644 index 68ee9ad9..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/qr.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg deleted file mode 100644 index aa6deb35..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/question_mark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg deleted file mode 100644 index 3d7c66ce..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/right_arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg deleted file mode 100644 index d96a3994..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_browser.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg deleted file mode 100644 index 9b00c9d3..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_chat.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg deleted file mode 100644 index ac06d522..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/rounded_star.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg deleted file mode 100644 index 3aea4047..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/settings.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg deleted file mode 100644 index fe6c3cc0..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/sort.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg deleted file mode 100644 index 915bf9e4..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/trades.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg deleted file mode 100644 index f59ccaec..00000000 --- a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/usd.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt index 3c49480e..d892d340 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt @@ -1,5 +1,6 @@ package network.bisq.mobile.presentation.ui.components +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -15,15 +16,15 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import bisqapps.shared.presentation.generated.resources.Res -import coil3.compose.AsyncImage import network.bisq.mobile.presentation.ui.components.foundation.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme +import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource @OptIn(ExperimentalResourceApi::class) @Composable -fun CurrencyProfileCard(currencyName: String, currencyShort: String, imagePath: String) { +fun CurrencyProfileCard(currencyName: String, currencyShort: String, image: DrawableResource) { Row( modifier = Modifier.fillMaxWidth().padding(horizontal = 14.dp, vertical = 16.dp), verticalAlignment = Alignment.CenterVertically, @@ -32,11 +33,7 @@ fun CurrencyProfileCard(currencyName: String, currencyShort: String, imagePath: Row( verticalAlignment = Alignment.CenterVertically, ) { - AsyncImage( - model = Res.getUri(imagePath), - contentDescription = null, - modifier = Modifier.size(36.dp), - ) + Image(painterResource(image), null, modifier = Modifier.size(36.dp)) Spacer(modifier = Modifier.width(8.dp)) Column { BisqText.baseRegular( diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt index 2f1ee88b..4b0551ef 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt @@ -4,16 +4,21 @@ import androidx.compose.foundation.Image import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.bell -import bisqapps.shared.presentation.generated.resources.img_bot_image +import bisqapps.shared.presentation.generated.resources.* import org.jetbrains.compose.resources.painterResource @Composable fun BellIcon(modifier: Modifier = Modifier) { - Image(painterResource(Res.drawable.bell), "Bell icon", modifier = modifier) + Image(painterResource(Res.drawable.icon_bell), "Bell icon", modifier = modifier) } @Composable fun UserIcon(modifier: Modifier = Modifier) { Image(painterResource(Res.drawable.img_bot_image), "User icon", modifier = modifier) +} + + +@Composable +fun SortIcon(modifier: Modifier = Modifier) { + Image(painterResource(Res.drawable.icon_sort), "Sort icon", modifier = modifier) } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt index 6508fab7..53aa1943 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt @@ -46,23 +46,9 @@ fun TopBar(title: String = "",isHome:Boolean = false) { }, actions = { Row(verticalAlignment = Alignment.CenterVertically) { - -// AsyncImage( -// model = Res.getUri("drawable/bell.svg"), -// contentDescription = null, -// modifier = Modifier.size(30.dp), -// ) BellIcon(modifier = Modifier.size(30.dp)) - Spacer(modifier = Modifier.width(12.dp)) - -// AsyncImage( -// model = Res.getUri("drawable/bot_image.svg"), -// contentDescription = null, -// modifier = Modifier.size(40.dp), -// ) UserIcon(modifier = Modifier.size(30.dp)) - } }, diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt index 8128712a..d806f420 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt @@ -20,11 +20,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.currency_euro +import bisqapps.shared.presentation.generated.resources.currency_gpb +import bisqapps.shared.presentation.generated.resources.currency_usd import coil3.compose.AsyncImage import network.bisq.mobile.presentation.ui.components.CurrencyProfileCard import network.bisq.mobile.components.MaterialTextField import network.bisq.mobile.presentation.ui.components.TopBar +import network.bisq.mobile.presentation.ui.components.atoms.icons.SortIcon +import network.bisq.mobile.presentation.ui.components.atoms.icons.UserIcon import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @@ -51,17 +57,13 @@ fun ExchangeScreen( Box(modifier = Modifier.width(250.dp)) { MaterialTextField(text = "Search", onValueChanged = {}) } - AsyncImage( - model = Res.getUri("drawable/sort.svg"), - contentDescription = null, - modifier = Modifier.size(24.dp), - ) + SortIcon(modifier = Modifier.size(24.dp)) } Spacer(modifier = Modifier.height(12.dp)) Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { - CurrencyProfileCard("US Dollars", "USD", "drawable/usd.svg") - CurrencyProfileCard("Euro", "EUR", "drawable/euro.svg") - CurrencyProfileCard("British Pounds", "GPB", "drawable/gpb.svg") + CurrencyProfileCard("US Dollars", "USD", Res.drawable.currency_usd) + CurrencyProfileCard("Euro", "EUR", Res.drawable.currency_euro) + CurrencyProfileCard("British Pounds", "GPB", Res.drawable.currency_gpb) } } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt index 967f0b38..a624a254 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt @@ -10,9 +10,6 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.home -import bisqapps.shared.presentation.generated.resources.icon_question_mark -import bisqapps.shared.presentation.generated.resources.trades import network.bisq.mobile.presentation.ui.model.BottomNavigationItem import network.bisq.mobile.presentation.ui.navigation.BottomNavigation import network.bisq.mobile.presentation.ui.navigation.Graph @@ -21,10 +18,10 @@ import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph import network.bisq.mobile.presentation.ui.theme.BisqTheme val navigationListItem = listOf( - BottomNavigationItem("Home", Routes.TabHome.name, Res.drawable.home), - BottomNavigationItem("Buy/Sell", Routes.TabExchange.name, Res.drawable.market), - BottomNavigationItem("My Trades", Routes.TabMyTrades.name, Res.drawable.trades), - BottomNavigationItem("Settings", Routes.TabSettings.name, Res.drawable.settings), + BottomNavigationItem("Home", Routes.TabHome.name, Res.drawable.icon_home), + BottomNavigationItem("Buy/Sell", Routes.TabExchange.name, Res.drawable.icon_market), + BottomNavigationItem("My Trades", Routes.TabMyTrades.name, Res.drawable.icon_trades), + BottomNavigationItem("Settings", Routes.TabSettings.name, Res.drawable.icon_settings), ) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt index 53484551..ed68b82e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt @@ -6,12 +6,8 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.slideInHorizontally import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue @@ -21,16 +17,10 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.icon_copy import bisqapps.shared.presentation.generated.resources.icon_question_mark -import coil3.compose.AsyncImage import network.bisq.mobile.components.MaterialTextField import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo import network.bisq.mobile.presentation.ui.components.foundation.BisqButton From 94eb3462b3fb5e785af78027963ee5e9df70a359 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sun, 10 Nov 2024 23:19:51 +0530 Subject: [PATCH 15/31] All images converted to PNG, tested in both iOS, Android and removed coil3 lib dependency --- bisqapps/shared/presentation/build.gradle.kts | 1 - .../drawable/icon_chat_outlined.png | Bin 0 -> 3146 bytes .../drawable/icon_star_outlined.png | Bin 0 -> 3226 bytes .../drawable/icon_tag_outlined.png | Bin 0 -> 3234 bytes .../ui/components/CurrencyProfileCard.kt | 2 +- .../ui/components/MaterialTextField.kt | 5 +--- .../ui/components/atoms/Button.kt | 5 +--- .../ui/components/atoms/ProgressBar.kt | 2 ++ .../presentation/ui/components/atoms/Text.kt | 2 +- .../ui/components/molecules/TopBar.kt | 11 ++------ .../ui/navigation/BottomNavigation.kt | 2 +- .../ui/screens/CreateProfileScreen.kt | 4 +-- .../presentation/ui/screens/ExchangeScreen.kt | 5 +--- .../ui/screens/GettingStartedScreen.kt | 26 ++++++++++-------- .../presentation/ui/screens/MyTrades.kt | 2 +- .../ui/screens/OnBoardingScreen.kt | 4 +-- .../presentation/ui/screens/SettingsScreen.kt | 5 +--- .../presentation/ui/screens/SplashScreen.kt | 15 ++-------- .../presentation/ui/screens/URLScreen.kt | 4 +-- 19 files changed, 34 insertions(+), 61 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_chat_outlined.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_star_outlined.png create mode 100644 bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_tag_outlined.png diff --git a/bisqapps/shared/presentation/build.gradle.kts b/bisqapps/shared/presentation/build.gradle.kts index 8f8f6d9c..16f89060 100644 --- a/bisqapps/shared/presentation/build.gradle.kts +++ b/bisqapps/shared/presentation/build.gradle.kts @@ -95,7 +95,6 @@ kotlin { implementation("io.coil-kt.coil3:coil-svg:3.0.0-rc02") implementation("org.jetbrains.androidx.navigation:navigation-compose:2.7.0-alpha07") - implementation("cafe.adriel.lyricist:lyricist:1.7.0") } diff --git a/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_chat_outlined.png b/bisqapps/shared/presentation/src/commonMain/composeResources/drawable/icon_chat_outlined.png new file mode 100644 index 0000000000000000000000000000000000000000..e6097f7f898b770475f30d22246ac4ede5905e2f GIT binary patch literal 3146 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 UhHiGlP5=M^07*qoM6N<$g3v(<8UO$Q literal 0 HcmV?d00001 diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt index d892d340..3bfdcca4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt @@ -16,7 +16,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt index 8ee962d0..c14406c0 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt @@ -21,13 +21,10 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import bisqapps.shared.presentation.generated.resources.Res -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.* -import org.jetbrains.compose.resources.Font @Composable fun MaterialTextField(text: String,onValueChanged: (String) -> Unit) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt index 2f0b6da8..4aa6527e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt @@ -1,15 +1,12 @@ -package network.bisq.mobile.presentation.ui.components.foundation +package network.bisq.mobile.presentation.ui.components.atoms import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ButtonColors import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import coil3.Image import network.bisq.mobile.presentation.ui.theme.BisqTheme // TODO: diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt index 050ec883..fff981cc 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProgressBar.kt @@ -1,3 +1,5 @@ +package network.bisq.mobile.presentation.ui.components.atoms + import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt index 0f0519c2..2d77c639 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.components.foundation +package network.bisq.mobile.presentation.ui.components.atoms import androidx.compose.runtime.Composable import androidx.compose.material3.Text diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt index 53aa1943..9f0b2d01 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/TopBar.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.components +package network.bisq.mobile.presentation.ui.components.molecules import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -7,22 +7,16 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import bisqapps.shared.presentation.generated.resources.Res -import coil3.compose.AsyncImage import network.bisq.mobile.presentation.ui.components.atoms.icons.BellIcon import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogoSmall import network.bisq.mobile.presentation.ui.components.atoms.icons.UserIcon -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi @@ -50,7 +44,6 @@ fun TopBar(title: String = "",isHome:Boolean = false) { Spacer(modifier = Modifier.width(12.dp)) UserIcon(modifier = Modifier.size(30.dp)) } - }, ) } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt index 80edfd46..ad95c5bf 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.unit.dp -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.model.BottomNavigationItem import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt index 9cc4ab5b..2d281532 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt @@ -14,8 +14,8 @@ import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.img_bot_image import network.bisq.mobile.components.MaterialTextField import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo -import network.bisq.mobile.presentation.ui.components.foundation.BisqButton -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqScrollLayout import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt index d806f420..78c77a7f 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt @@ -20,17 +20,14 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.dp import androidx.navigation.NavController -import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.currency_euro import bisqapps.shared.presentation.generated.resources.currency_gpb import bisqapps.shared.presentation.generated.resources.currency_usd -import coil3.compose.AsyncImage import network.bisq.mobile.presentation.ui.components.CurrencyProfileCard import network.bisq.mobile.components.MaterialTextField -import network.bisq.mobile.presentation.ui.components.TopBar +import network.bisq.mobile.presentation.ui.components.molecules.TopBar import network.bisq.mobile.presentation.ui.components.atoms.icons.SortIcon -import network.bisq.mobile.presentation.ui.components.atoms.icons.UserIcon import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt index 549b4fca..0f615042 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt @@ -27,13 +27,14 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.icon_tag_outlined import bisqapps.shared.presentation.generated.resources.img_fiat_btc import bisqapps.shared.presentation.generated.resources.img_learn_and_discover -import coil3.compose.AsyncImage import kotlinx.coroutines.flow.StateFlow -import network.bisq.mobile.presentation.ui.components.TopBar -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.molecules.TopBar +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi @@ -133,15 +134,15 @@ fun WelcomeCard(title: String, buttonText: String) { ) Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { FeatureCard( - imagePath = "drawable/rounded_browser.svg", + image = Res.drawable.icon_tag_outlined, title = "Start trading or browser open offers in the offerbook" ) FeatureCard( - imagePath = "drawable/rounded_chat.svg", + image = Res.drawable.icon_chat_outlined, title = "Chat based and guided user interface for trading" ) FeatureCard( - imagePath = "drawable/rounded_star.svg", + image = Res.drawable.icon_star_outlined, title = "Security is based on seller’s reputation" ) } @@ -187,13 +188,14 @@ fun PriceProfileCard(price: String, priceText: String) { @OptIn(ExperimentalResourceApi::class) @Composable -fun FeatureCard(imagePath: String, title: String) { +fun FeatureCard(image: DrawableResource, title: String) { Row(verticalAlignment = Alignment.CenterVertically) { - AsyncImage( - model = Res.getUri(imagePath), - contentDescription = null, - modifier = Modifier.size(20.dp) - ) +// AsyncImage( +// model = Res.getUri(imagePath), +// contentDescription = null, +// modifier = Modifier.size(20.dp) +// ) + Image(painterResource(image), null, Modifier.size(20.dp)) Spacer(modifier = Modifier.width(9.dp)) BisqText.smallRegular( text = title, diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt index c6230eb8..935509ca 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.sp import androidx.navigation.NavController -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt index f3d63128..1eb2c024 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -36,8 +36,8 @@ import bisqapps.shared.presentation.generated.resources.img_learn_and_discover import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo -import network.bisq.mobile.presentation.ui.components.foundation.BisqButton -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqScrollLayout import network.bisq.mobile.presentation.ui.model.OnBoardingPage import network.bisq.mobile.presentation.ui.navigation.Routes diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt index cb570319..72ee31b4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt @@ -5,14 +5,11 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.sp import androidx.navigation.NavController -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index e0ba1c7e..0d2a22c1 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -1,36 +1,25 @@ package network.bisq.mobile.presentation.ui.screens -import BisqProgressBar -import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.navigation.NavController -import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.ExperimentalResourceApi -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch - -import network.bisq.mobile.presentation.ui.navigation.Routes -import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.bisq_logo import cafe.adriel.lyricist.LocalStrings -import cafe.adriel.lyricist.rememberStrings +import network.bisq.mobile.presentation.ui.components.atoms.BisqProgressBar import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout import network.bisq.mobile.presentation.ui.theme.* // TODO: Remove innerPadding once StaticLayout, ScrollLayout are fully done. -@OptIn(ExperimentalResourceApi::class) @Composable fun SplashScreen( rootNavController: NavController, diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt index ed68b82e..52ea8e77 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt @@ -23,8 +23,8 @@ import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.icon_question_mark import network.bisq.mobile.components.MaterialTextField import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo -import network.bisq.mobile.presentation.ui.components.foundation.BisqButton -import network.bisq.mobile.presentation.ui.components.foundation.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqScrollLayout import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* From 5b646f8b3ab826705bfa98f299523596a5bd8895 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 13 Nov 2024 18:17:55 +0530 Subject: [PATCH 16/31] First code review corrections 1/2 --- bisqapps/gradle/libs.versions.toml | 14 +- bisqapps/gradle/wrapper/gradle-wrapper.jar | Bin 56921 -> 43583 bytes bisqapps/gradlew | 306 +++++++++++------- bisqapps/gradlew.bat | 78 +++-- bisqapps/shared/domain/build.gradle.kts | 8 - .../domain/data/repository/PriceRepository.kt | 32 +- bisqapps/shared/presentation/build.gradle.kts | 9 +- .../bisq/mobile/presentation/i18n/Locales.kt | 39 ++- 8 files changed, 294 insertions(+), 192 deletions(-) diff --git a/bisqapps/gradle/libs.versions.toml b/bisqapps/gradle/libs.versions.toml index e73376c0..9ed6fea2 100644 --- a/bisqapps/gradle/libs.versions.toml +++ b/bisqapps/gradle/libs.versions.toml @@ -2,7 +2,7 @@ agp = "8.5.0" android-compileSdk = "34" android-targetSdk = "34" -android-minSdk = "28" +android-minSdk = "24" android-node-minSdk = "31" androidx-activityCompose = "1.9.2" androidx-appcompat = "1.7.0" @@ -23,8 +23,11 @@ kotlinTestJunit = "2.0.20" kotlinx = "1.9.0" kermit = "2.0.4" buildconfig = "5.5.0" +navigationCompose = "2.7.0-alpha07" protobuf = "0.9.4" protob = "4.28.2" +protoblite = "4.28.2" +ksp = "2.0.20-1.0.25" chimp-jsocks-lib = { strictly = '567e1cd6' } chimp-jtorctl-lib = { strictly = '9b5ba203' } @@ -48,8 +51,7 @@ grpc = { strictly = '1.61.0' } i2p-lib = { strictly = '1.8.0' } i2p-v2 = { strictly = '2.4.0' } jackson-lib = { strictly = '2.17.2' } -ktorClientCore = "3.0.0" -lyricist = "2.0.20-1.0.25" +lyricist = "1.7.0" koin = "4.0.0" lombok-lib = { strictly = '1.18.34' } @@ -75,9 +77,7 @@ androidx-activity-compose = { module = "androidx.activity:activity-compose", ver androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" } androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } -ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktorClientCore" } logging-kermit = { group = "co.touchlab", name = "kermit", version.ref = "kermit" } -lyricist = { module = "cafe.adriel.lyricist:lyricist", version.ref = "lyricist" } lombok = { module = 'org.projectlombok:lombok', version.ref = 'lombok-lib' } @@ -87,6 +87,9 @@ bouncycastle = { module = 'org.bouncycastle:bcprov-jdk18on', version.ref = 'boun bouncycastle-pg = { module = 'org.bouncycastle:bcpg-jdk18on', version.ref = 'bouncycastle-lib' } #protobuf-lite = { group ="com.google.protobuf", name = "protobuf-javalite", version.ref = "protoblite"} +lyricist = { module = "cafe.adriel.lyricist:lyricist", version.ref = "lyricist" } +navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +protobuf-lite = { group ="com.google.protobuf", name = "protobuf-javalite", version.ref = "protoblite"} protobuf-gradle-plugin = { module = 'com.google.protobuf:protobuf-gradle-plugin', version.ref = 'protobuf' } protoc = { module = "com.google.protobuf:protoc", version.ref = "protob" } @@ -166,3 +169,4 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } buildconfig = { id = "com.github.gmazzo.buildconfig", version.ref = "buildconfig" } protobuf = { id = "com.google.protobuf", version.ref = "protobuf" } +ksp = { id = "com.google.devtools.ksp", version.ref="ksp" } diff --git a/bisqapps/gradle/wrapper/gradle-wrapper.jar b/bisqapps/gradle/wrapper/gradle-wrapper.jar index b498d2444600d918cbd5949508e2ade6fbef0301..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 56921 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 diff --git a/bisqapps/gradlew b/bisqapps/gradlew index 17a91706..f5feea6d 100755 --- a/bisqapps/gradlew +++ b/bisqapps/gradlew @@ -1,78 +1,130 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,96 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") -# Collect all arguments for the java command, following the shell quoting and substitution rules -if $JAVACMD --add-opens java.base/java.lang=ALL-UNNAMED -version ; then - DEFAULT_JVM_OPTS="--add-opens java.base/java.lang=ALL-UNNAMED $DEFAULT_JVM_OPTS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/bisqapps/gradlew.bat b/bisqapps/gradlew.bat index e95643d6..9b42019c 100644 --- a/bisqapps/gradlew.bat +++ b/bisqapps/gradlew.bat @@ -1,4 +1,22 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -9,25 +27,29 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -35,48 +57,36 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/bisqapps/shared/domain/build.gradle.kts b/bisqapps/shared/domain/build.gradle.kts index 12c50ae3..53d222bb 100644 --- a/bisqapps/shared/domain/build.gradle.kts +++ b/bisqapps/shared/domain/build.gradle.kts @@ -36,14 +36,6 @@ kotlin { implementation(libs.koin.core) implementation(libs.kotlinx.coroutines) - // Coroutines - // implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0") - - // Ktor client for HTTP requests - implementation("io.ktor:ktor-client-core:3.0.0") - implementation("io.ktor:ktor-client-cio:3.0.0") // Replace with the appropriate engine for your platform - implementation("io.ktor:ktor-client-content-negotiation:3.0.0") - implementation("io.ktor:ktor-serialization-kotlinx-json:3.0.0") } commonTest.dependencies { implementation(libs.kotlin.test) diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt index e41787df..e10c2b0b 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt @@ -1,27 +1,23 @@ -import io.ktor.client.* -import io.ktor.client.call.* -import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.client.plugins.contentnegotiation.* -import io.ktor.serialization.kotlinx.json.* -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.IO -import kotlinx.coroutines.withContext -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json + class PriceRepository { + suspend fun fetchBtcPrice(): String = "$70,000" + fun getValue() = "$70,000" + + /* // Ktor client setup with ContentNegotiation plugin private val client = HttpClient { install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) // Configures JSON serialization } } + */ /** * Fetches the current BTC price in USD from CoinGecko API. */ + /* suspend fun fetchBtcPrice(): String { println("fetchBtcPrice()") return withContext(Dispatchers.IO) { @@ -39,16 +35,6 @@ class PriceRepository { } } } + */ - fun getValue() = "$70,000" -} - -@Serializable -data class CoinGeckoResponse( - val bitcoin: BitcoinPrice -) - -@Serializable -data class BitcoinPrice( - val usd: Double -) +} \ No newline at end of file diff --git a/bisqapps/shared/presentation/build.gradle.kts b/bisqapps/shared/presentation/build.gradle.kts index 16f89060..02b64446 100644 --- a/bisqapps/shared/presentation/build.gradle.kts +++ b/bisqapps/shared/presentation/build.gradle.kts @@ -9,7 +9,7 @@ plugins { alias(libs.plugins.jetbrainsCompose) alias(libs.plugins.compose.compiler) alias(libs.plugins.buildconfig) - id("com.google.devtools.ksp") version "2.0.20-1.0.25" + alias(libs.plugins.ksp) } dependencies { @@ -91,11 +91,8 @@ kotlin { implementation(libs.koin.core) implementation(libs.koin.compose) - implementation("io.coil-kt.coil3:coil-compose:3.0.0-rc02") - implementation("io.coil-kt.coil3:coil-svg:3.0.0-rc02") - - implementation("org.jetbrains.androidx.navigation:navigation-compose:2.7.0-alpha07") - implementation("cafe.adriel.lyricist:lyricist:1.7.0") + implementation(libs.navigation.compose) + implementation(libs.lyricist) } val commonTest by getting { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt index d9102ceb..002203eb 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt @@ -1,6 +1,43 @@ package network.bisq.mobile.presentation.i18n +/** + * An object that holds locale codes used for the application’s supported languages. + * + * Currently, this object supports English (`EN`) as the default language and French ('FR') only for testing. + * Additional languages can be added in the future. + * + * ## Usage + * ### Locales.kt + * Defines all the supported languages + * + * ### Strigs.kt + * A class that defines variable for all text resources used in the app. + * TODO: This is going to be an insanely huge file. Look for ways to modularize it (for later) + * + * ### {Lang}Strings.kt + * One file for each language. Assigns actual text for each variable in that specific language. + * + * ### Actual usage: + * 1. Each view should be enclosed by `ProviderStrings`. This is now done at top level in App.kt + * + * val lyricist = rememberStrings() + * ProvideStrings(lyricist) {} + * + * 2. And current language can be changed anytime by doing + * + * lyricist.languageTag = Locales.FR + * + * 3. In the views, string resources can be accessed by + * + * LocalStrings.current.{stringResourceName} + * + * + * ## References: + * For more detailed usage, please refer lyricist documentation @ + * https://github.com/adrielcafe/lyricist/ + * https://github.com/adrielcafe/lyricist/tree/main/sample-multiplatform/src/commonMain/kotlin/cafe/adriel/lyricist/sample/multiplatform (sample project) + */ object Locales { const val EN = "en" const val FR = "fr" -} \ No newline at end of file +} From 85c73cae3cdfac83820dac7d691bea9aabdd21ae Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Thu, 14 Nov 2024 15:21:01 +0530 Subject: [PATCH 17/31] i18n Improvements - Script to convert translation keys, values from bisq2 app to mobile app lyricist structure - Translation strings in onboarding screens - Key, Values updated for all strings used in bisq2's application module. --- .../network/bisq/mobile/i18n/EnStrings.kt | 149 +++++++++++++++++ .../network/bisq/mobile/i18n/FrStrings.kt | 151 ++++++++++++++++++ .../network/bisq/mobile/i18n/Locales.kt | 43 +++++ .../network/bisq/mobile/i18n/Strings.kt | 147 +++++++++++++++++ .../mobile/presentation/i18n/EnStrings.kt | 8 - .../mobile/presentation/i18n/FrStrings.kt | 8 - .../bisq/mobile/presentation/i18n/Strings.kt | 7 - .../bisq/mobile/presentation/ui/App.kt | 4 +- .../ui/components/layout/ScrollLayout.kt | 1 - .../ui/components/layout/StaticLayout.kt | 5 - .../ui/screens/OnBoardingScreen.kt | 26 +-- .../ui/screens/SplashPresenter.kt | 3 + .../presentation/ui/screens/SplashScreen.kt | 10 +- bisqapps/tools/convert-i18n.js | 114 +++++++++++++ 14 files changed, 618 insertions(+), 58 deletions(-) create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/EnStrings.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/FrStrings.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Locales.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Strings.kt delete mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt delete mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt delete mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt create mode 100644 bisqapps/tools/convert-i18n.js diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/EnStrings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/EnStrings.kt new file mode 100644 index 00000000..5e432979 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/EnStrings.kt @@ -0,0 +1,149 @@ +package network.bisq.mobile.i18n + +import cafe.adriel.lyricist.LyricistStrings + +@LyricistStrings(languageTag = Locales.EN, default = true) +val EnStrings = Strings( + splash_details_tooltip = "Click to toggle details", + splash_applicationServiceState_INITIALIZE_APP = "Starting Bisq", + splash_applicationServiceState_INITIALIZE_NETWORK = "Initialize P2P network", + splash_applicationServiceState_INITIALIZE_WALLET = "Initialize wallet", + splash_applicationServiceState_INITIALIZE_SERVICES = "Initialize services", + splash_applicationServiceState_APP_INITIALIZED = "Bisq started", + splash_applicationServiceState_FAILED = "Startup failed", + splash_bootstrapState_service_CLEAR = "Server", + splash_bootstrapState_service_TOR = "Onion Service", + splash_bootstrapState_service_I2P = "I2P Service", + splash_bootstrapState_network_CLEAR = "Clear net", + splash_bootstrapState_network_TOR = "Tor", + splash_bootstrapState_network_I2P = "I2P", + splash_bootstrapState_BOOTSTRAP_TO_NETWORK = { networkType -> "Bootstrap to $networkType network" }, + splash_bootstrapState_START_PUBLISH_SERVICE = "Start publishing {0}", + splash_bootstrapState_SERVICE_PUBLISHED = "{0} published", + splash_bootstrapState_CONNECTED_TO_PEERS = "Connecting to peers", + tac_headline = "User Agreement", + tac_confirm = "I have read and understood", + tac_accept = "Accept user Agreement", + tac_reject = "Reject and quit application", + unlock_headline = "Enter password to unlock", + unlock_button = "Unlock", + unlock_failed = "Could not unlock with the provided password.\n\n Try again and be sure to have the caps lock disabled.", + updater_headline = "A new Bisq update is available", + updater_headline_isLauncherUpdate = "A new Bisq installer is available", + updater_releaseNotesHeadline = "Release notes for version {0}:", + updater_furtherInfo = "This update will be loaded after restart and does not require a new installation.\n More details can be found at the release page at:", + updater_furtherInfo_isLauncherUpdate = "This update requires a new Bisq installation.\n If you have problems when installing Bisq on macOS, please read the instructions at:", + updater_download = "Download and verify", + updater_downloadLater = "Download later", + updater_ignore = "Ignore this version", + updater_shutDown = "Shut down", + updater_shutDown_isLauncherUpdate = "Open download directory and shut down", + updater_downloadAndVerify_headline = "Download and verify new version", + updater_downloadAndVerify_info = "Once all files are downloaded, the signing key is compared with the keys provided in the application and those available on the Bisq website. This key is then used to verify the downloaded new version ('desktop.jar').", + updater_downloadAndVerify_info_isLauncherUpdate = "Once all files are downloaded, the signing key is compared with the keys provided in the application and those available on the Bisq website. This key is then used to verify the downloaded new Bisq installer. After download and verification are complete, navigate to the download directory to install the new Bisq version.", + updater_table_file = "File", + updater_table_progress = "Download progress", + updater_table_progress_completed = "Completed", + updater_table_verified = "Signature verified", + notificationPanel_trades_headline_single = "New trade message for trade ''{0}''", + notificationPanel_trades_headline_multiple = "New trade messages", + notificationPanel_trades_button = "Go to 'Open Trades'", + notificationPanel_mediationCases_headline_single = "New message for mediation case with trade ID ''{0}''", + notificationPanel_mediationCases_headline_multiple = "New messages for mediation", + notificationPanel_mediationCases_button = "Go to 'Mediator'", + onboarding_bisq2_headline = "Welcome to Bisq 2", + onboarding_bisq2_teaserHeadline1 = "Introducing Bisq Easy", + onboarding_bisq2_line1 = "Getting your first Bitcoin privately\n has never been easier.", + onboarding_bisq2_teaserHeadline2 = "Learn & discover", + onboarding_bisq2_line2 = "Get a gentle introduction into Bitcoin\n through our guides and community chat.", + onboarding_bisq2_teaserHeadline3 = "Coming soon", + onboarding_bisq2_line3 = "Choose how to trade: Bisq MuSig, Lightning, Submarine Swaps,...", + onboarding_button_create_profile = "Create profile", + onboarding_createProfile_headline = "Create your profile", + onboarding_createProfile_subTitle = "Your public profile consists of a nickname (picked by you) and a bot icon (generated cryptographically)", + onboarding_createProfile_nym = "Bot ID:", + onboarding_createProfile_regenerate = "Generate new bot icon", + onboarding_createProfile_nym_generating = "Calculating proof of work...", + onboarding_createProfile_createProfile = "Next", + onboarding_createProfile_createProfile_busy = "Initializing network node...", + onboarding_createProfile_nickName_prompt = "Choose your nickname", + onboarding_createProfile_nickName = "Profile nickname", + onboarding_createProfile_nickName_tooLong = "Nickname must not be longer than {0} characters", + onboarding_password_button_skip = "Skip", + onboarding_password_subTitle = "Set up password protection now or skip and do it later in 'User options/Password'.", + onboarding_password_headline_setPassword = "Set password protection", + onboarding_password_button_savePassword = "Save password", + onboarding_password_enterPassword = "Enter password (min. 8 characters)", + onboarding_password_confirmPassword = "Confirm password", + onboarding_password_savePassword_success = "Password protection enabled.", + navigation_dashboard = "Dashboard", + navigation_bisqEasy = "Bisq Easy", + navigation_reputation = "Reputation", + navigation_tradeApps = "Trade protocols", + navigation_wallet = "Wallet", + navigation_academy = "Learn", + navigation_chat = "Chat", + navigation_support = "Support", + navigation_userOptions = "User options", + navigation_settings = "Settings", + navigation_network = "Network", + navigation_authorizedRole = "Authorized role", + navigation_expandIcon_tooltip = "Expand menu", + navigation_collapseIcon_tooltip = "Minimize menu", + navigation_vertical_expandIcon_tooltip = "Expand sub menu", + navigation_vertical_collapseIcon_tooltip = "Collapse sub menu", + navigation_network_info_clearNet = "Clear-net", + navigation_network_info_tor = "Tor", + navigation_network_info_i2p = "I2P", + navigation_network_info_tooltip = "{0} network\n Number of connections: {1}\n Target connections: {2}", + navigation_network_info_inventoryRequest_requesting = "Requesting network data", + navigation_network_info_inventoryRequest_completed = "Network data received", + navigation_network_info_inventoryRequests_tooltip = "Network data request state:\n Number of pending requests: {0}\n Max. requests: {1}\n All data received: {2}", + topPanel_wallet_balance = "Balance", + dashboard_marketPrice = "Latest market price", + dashboard_offersOnline = "Offers online", + dashboard_activeUsers = "Published user profiles", + dashboard_activeUsers_tooltip = "Profiles stay published on the network\nif the user was online in the last 15 days.", + dashboard_main_headline = "Get your first BTC", + dashboard_main_content1 = "Start trading or browse open offers in the offerbook", + dashboard_main_content2 = "Chat based and guided user interface for trading", + dashboard_main_content3 = "Security is based on seller's reputation", + dashboard_main_button = "Enter Bisq Easy", + dashboard_second_headline = "Multiple trade protocols", + dashboard_second_content = "Check out the roadmap for upcoming trade protocols. Get an overview about the features of the different protocols.", + dashboard_second_button = "Explore trade protocols", + dashboard_third_headline = "Build up reputation", + dashboard_third_content = "You want to sell Bitcoin on Bisq Easy? Learn how the Reputation system works and why it is important.", + dashboard_third_button = "Build Reputation", + popup_headline_instruction = "Please note:", + popup_headline_attention = "Attention", + popup_headline_backgroundInfo = "Background information", + popup_headline_feedback = "Completed", + popup_headline_confirmation = "Confirmation", + popup_headline_information = "Information", + popup_headline_warning = "Warning", + popup_headline_invalid = "Invalid input", + popup_headline_error = "Error", + popup_reportBug = "Report bug to Bisq developers", + popup_reportError = "To help us to improve the software please report this bug by opening a new issue at: 'https://github.com/bisq-network/bisq2/issues'.\n The error message will be copied to the clipboard when you click the 'report' button below.\n\n It will make debugging easier if you include log files in your bug report. Log files do not contain sensitive data.", + popup_reportBug_report = "Bisq version: {0}\n Operating system: {1}\n Error message:\n {2}", + popup_reportError_log = "Open log file", + popup_reportError_zipLogs = "Zip log files", + popup_reportError_gitHub = "Report to Bisq GitHub repository", + popup_startup_error = "An error occurred at initializing Bisq: {0}.", + popup_shutdown = "Shut down is in process.\n\n It might take up to {0} seconds until shut down is completed.", + popup_shutdown_error = "An error occurred at shut down: {0}.", + popup_hyperlink_openInBrowser_tooltip = "Open link in browser: {0}.", + popup_hyperlink_copy_tooltip = "Copy link: {0}.", + hyperlinks_openInBrowser_attention_headline = "Open web link", + hyperlinks_openInBrowser_attention = "Do you want to open the link to `{0}` in your default web browser?", + hyperlinks_openInBrowser_no = "No, copy link", + hyperlinks_copiedToClipboard = "Link was copied to clipboard", + video_mp4NotSupported_warning_headline = "Embedded video cannot be played", + video_mp4NotSupported_warning = "You can watch the video in your browser at: [HYPERLINK:{0}]", + version_versionAndCommitHash = "Version: v{0} / Commit hash: {1}", + + buttons_next = "Next", + buttons_submit = "Submit", + buttons_cancel = "Cancel", +) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/FrStrings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/FrStrings.kt new file mode 100644 index 00000000..c4d5d745 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/FrStrings.kt @@ -0,0 +1,151 @@ +package network.bisq.mobile.i18n + +import cafe.adriel.lyricist.LyricistStrings + + +// Generated Locales.FR strings +@LyricistStrings(languageTag = Locales.FR) +val FRStrings = Strings( + splash_details_tooltip = "[FR] Click to toggle details", + splash_applicationServiceState_INITIALIZE_APP = "[FR] Starting Bisq", + splash_applicationServiceState_INITIALIZE_NETWORK = "[FR] Initialize P2P network", + splash_applicationServiceState_INITIALIZE_WALLET = "[FR] Initialize wallet", + splash_applicationServiceState_INITIALIZE_SERVICES = "[FR] Initialize services", + splash_applicationServiceState_APP_INITIALIZED = "[FR] Bisq started", + splash_applicationServiceState_FAILED = "[FR] Startup failed", + splash_bootstrapState_service_CLEAR = "[FR] Server", + splash_bootstrapState_service_TOR = "[FR] Onion Service", + splash_bootstrapState_service_I2P = "[FR] I2P Service", + splash_bootstrapState_network_CLEAR = "[FR] Clear net", + splash_bootstrapState_network_TOR = "[FR] Tor", + splash_bootstrapState_network_I2P = "[FR] I2P", + splash_bootstrapState_BOOTSTRAP_TO_NETWORK = { networkType -> "[FR] Bootstrap to $networkType network" }, + splash_bootstrapState_START_PUBLISH_SERVICE = "[FR] Start publishing {0}", + splash_bootstrapState_SERVICE_PUBLISHED = "[FR] {0} published", + splash_bootstrapState_CONNECTED_TO_PEERS = "[FR] Connecting to peers", + tac_headline = "[FR] User Agreement", + tac_confirm = "[FR] I have read and understood", + tac_accept = "[FR] Accept user Agreement", + tac_reject = "[FR] Reject and quit application", + unlock_headline = "[FR] Enter password to unlock", + unlock_button = "[FR] Unlock", + unlock_failed = "[FR] Could not unlock with the provided password.\n\n Try again and be sure to have the caps lock disabled.", + updater_headline = "[FR] A new Bisq update is available", + updater_headline_isLauncherUpdate = "[FR] A new Bisq installer is available", + updater_releaseNotesHeadline = "[FR] Release notes for version {0}:", + updater_furtherInfo = "[FR] This update will be loaded after restart and does not require a new installation.\n More details can be found at the release page at:", + updater_furtherInfo_isLauncherUpdate = "[FR] This update requires a new Bisq installation.\n If you have problems when installing Bisq on macOS, please read the instructions at:", + updater_download = "[FR] Download and verify", + updater_downloadLater = "[FR] Download later", + updater_ignore = "[FR] Ignore this version", + updater_shutDown = "[FR] Shut down", + updater_shutDown_isLauncherUpdate = "[FR] Open download directory and shut down", + updater_downloadAndVerify_headline = "[FR] Download and verify new version", + updater_downloadAndVerify_info = "[FR] Once all files are downloaded, the signing key is compared with the keys provided in the application and those available on the Bisq website. This key is then used to verify the downloaded new version ('desktop.jar').", + updater_downloadAndVerify_info_isLauncherUpdate = "[FR] Once all files are downloaded, the signing key is compared with the keys provided in the application and those available on the Bisq website. This key is then used to verify the downloaded new Bisq installer. After download and verification are complete, navigate to the download directory to install the new Bisq version.", + updater_table_file = "[FR] File", + updater_table_progress = "[FR] Download progress", + updater_table_progress_completed = "[FR] Completed", + updater_table_verified = "[FR] Signature verified", + notificationPanel_trades_headline_single = "[FR] New trade message for trade ''{0}''", + notificationPanel_trades_headline_multiple = "[FR] New trade messages", + notificationPanel_trades_button = "[FR] Go to 'Open Trades'", + notificationPanel_mediationCases_headline_single = "[FR] New message for mediation case with trade ID ''{0}''", + notificationPanel_mediationCases_headline_multiple = "[FR] New messages for mediation", + notificationPanel_mediationCases_button = "[FR] Go to 'Mediator'", + onboarding_bisq2_headline = "[FR] Welcome to Bisq 2", + onboarding_bisq2_teaserHeadline1 = "[FR] Introducing Bisq Easy", + onboarding_bisq2_line1 = "[FR] Getting your first Bitcoin privately\n has never been easier.", + onboarding_bisq2_teaserHeadline2 = "[FR] Learn & discover", + onboarding_bisq2_line2 = "[FR] Get a gentle introduction into Bitcoin\n through our guides and community chat.", + onboarding_bisq2_teaserHeadline3 = "[FR] Coming soon", + onboarding_bisq2_line3 = "[FR] Choose how to trade: Bisq MuSig, Lightning, Submarine Swaps,...", + onboarding_button_create_profile = "[FR] Create profile", + onboarding_createProfile_headline = "[FR] Create your profile", + onboarding_createProfile_subTitle = "[FR] Your public profile consists of a nickname (picked by you) and a bot icon (generated cryptographically)", + onboarding_createProfile_nym = "[FR] Bot ID:", + onboarding_createProfile_regenerate = "[FR] Generate new bot icon", + onboarding_createProfile_nym_generating = "[FR] Calculating proof of work...", + onboarding_createProfile_createProfile = "[FR] Next", + onboarding_createProfile_createProfile_busy = "[FR] Initializing network node...", + onboarding_createProfile_nickName_prompt = "[FR] Choose your nickname", + onboarding_createProfile_nickName = "[FR] Profile nickname", + onboarding_createProfile_nickName_tooLong = "[FR] Nickname must not be longer than {0} characters", + onboarding_password_button_skip = "[FR] Skip", + onboarding_password_subTitle = "[FR] Set up password protection now or skip and do it later in 'User options/Password'.", + onboarding_password_headline_setPassword = "[FR] Set password protection", + onboarding_password_button_savePassword = "[FR] Save password", + onboarding_password_enterPassword = "[FR] Enter password (min. 8 characters)", + onboarding_password_confirmPassword = "[FR] Confirm password", + onboarding_password_savePassword_success = "[FR] Password protection enabled.", + navigation_dashboard = "[FR] Dashboard", + navigation_bisqEasy = "[FR] Bisq Easy", + navigation_reputation = "[FR] Reputation", + navigation_tradeApps = "[FR] Trade protocols", + navigation_wallet = "[FR] Wallet", + navigation_academy = "[FR] Learn", + navigation_chat = "[FR] Chat", + navigation_support = "[FR] Support", + navigation_userOptions = "[FR] User options", + navigation_settings = "[FR] Settings", + navigation_network = "[FR] Network", + navigation_authorizedRole = "[FR] Authorized role", + navigation_expandIcon_tooltip = "[FR] Expand menu", + navigation_collapseIcon_tooltip = "[FR] Minimize menu", + navigation_vertical_expandIcon_tooltip = "[FR] Expand sub menu", + navigation_vertical_collapseIcon_tooltip = "[FR] Collapse sub menu", + navigation_network_info_clearNet = "[FR] Clear-net", + navigation_network_info_tor = "[FR] Tor", + navigation_network_info_i2p = "[FR] I2P", + navigation_network_info_tooltip = "[FR] {0} network\n Number of connections: {1}\n Target connections: {2}", + navigation_network_info_inventoryRequest_requesting = "[FR] Requesting network data", + navigation_network_info_inventoryRequest_completed = "[FR] Network data received", + navigation_network_info_inventoryRequests_tooltip = "[FR] Network data request state:\n Number of pending requests: {0}\n Max. requests: {1}\n All data received: {2}", + topPanel_wallet_balance = "[FR] Balance", + dashboard_marketPrice = "[FR] Latest market price", + dashboard_offersOnline = "[FR] Offers online", + dashboard_activeUsers = "[FR] Published user profiles", + dashboard_activeUsers_tooltip = "[FR] Profiles stay published on the network\nif the user was online in the last 15 days.", + dashboard_main_headline = "[FR] Get your first BTC", + dashboard_main_content1 = "[FR] Start trading or browse open offers in the offerbook", + dashboard_main_content2 = "[FR] Chat based and guided user interface for trading", + dashboard_main_content3 = "[FR] Security is based on seller's reputation", + dashboard_main_button = "[FR] Enter Bisq Easy", + dashboard_second_headline = "[FR] Multiple trade protocols", + dashboard_second_content = "[FR] Check out the roadmap for upcoming trade protocols. Get an overview about the features of the different protocols.", + dashboard_second_button = "[FR] Explore trade protocols", + dashboard_third_headline = "[FR] Build up reputation", + dashboard_third_content = "[FR] You want to sell Bitcoin on Bisq Easy? Learn how the Reputation system works and why it is important.", + dashboard_third_button = "[FR] Build Reputation", + popup_headline_instruction = "[FR] Please note:", + popup_headline_attention = "[FR] Attention", + popup_headline_backgroundInfo = "[FR] Background information", + popup_headline_feedback = "[FR] Completed", + popup_headline_confirmation = "[FR] Confirmation", + popup_headline_information = "[FR] Information", + popup_headline_warning = "[FR] Warning", + popup_headline_invalid = "[FR] Invalid input", + popup_headline_error = "[FR] Error", + popup_reportBug = "[FR] Report bug to Bisq developers", + popup_reportError = "[FR] To help us to improve the software please report this bug by opening a new issue at: 'https://github.com/bisq-network/bisq2/issues'.\n The error message will be copied to the clipboard when you click the 'report' button below.\n\n It will make debugging easier if you include log files in your bug report. Log files do not contain sensitive data.", + popup_reportBug_report = "[FR] Bisq version: {0}\n Operating system: {1}\n Error message:\n {2}", + popup_reportError_log = "[FR] Open log file", + popup_reportError_zipLogs = "[FR] Zip log files", + popup_reportError_gitHub = "[FR] Report to Bisq GitHub repository", + popup_startup_error = "[FR] An error occurred at initializing Bisq: {0}.", + popup_shutdown = "[FR] Shut down is in process.\n\n It might take up to {0} seconds until shut down is completed.", + popup_shutdown_error = "[FR] An error occurred at shut down: {0}.", + popup_hyperlink_openInBrowser_tooltip = "[FR] Open link in browser: {0}.", + popup_hyperlink_copy_tooltip = "[FR] Copy link: {0}.", + hyperlinks_openInBrowser_attention_headline = "[FR] Open web link", + hyperlinks_openInBrowser_attention = "[FR] Do you want to open the link to `{0}` in your default web browser?", + hyperlinks_openInBrowser_no = "[FR] No, copy link", + hyperlinks_copiedToClipboard = "[FR] Link was copied to clipboard", + video_mp4NotSupported_warning_headline = "[FR] Embedded video cannot be played", + video_mp4NotSupported_warning = "[FR] You can watch the video in your browser at: [HYPERLINK:{0}]", + version_versionAndCommitHash = "[FR] Version: v{0} / Commit hash: {1}", + + buttons_next = "[FR] Next", + buttons_submit = "[FR] Submit", + buttons_cancel = "[FR] Cancel", +) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Locales.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Locales.kt new file mode 100644 index 00000000..635e3f11 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Locales.kt @@ -0,0 +1,43 @@ +package network.bisq.mobile.i18n + +/** + * An object that holds locale codes used for the application’s supported languages. + * + * Currently, this object supports English (`EN`) as the default language and French ('FR') only for testing. + * Additional languages can be added in the future. + * + * ## Usage + * ### Locales.kt + * Defines all the supported languages + * + * ### Strigs.kt + * A class that defines variable for all text resources used in the app. + * TODO: This is going to be an insanely huge file. Look for ways to modularize it (for later) + * + * ### {Lang}Strings.kt + * One file for each language. Assigns actual text for each variable in that specific language. + * + * ### Actual usage: + * 1. Each view should be enclosed by `ProviderStrings`. This is now done at top level in App.kt + * + * val lyricist = rememberStrings() + * ProvideStrings(lyricist) {} + * + * 2. And current language can be changed anytime by doing + * + * lyricist.languageTag = Locales.FR + * + * 3. In the views, string resources can be accessed by + * + * LocalStrings.current.{stringResourceName} + * + * + * ## References: + * For more detailed usage, please refer lyricist documentation @ + * https://github.com/adrielcafe/lyricist/ + * https://github.com/adrielcafe/lyricist/tree/main/sample-multiplatform/src/commonMain/kotlin/cafe/adriel/lyricist/sample/multiplatform (sample project) + */ +object Locales { + const val EN = "en" + const val FR = "fr" +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Strings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Strings.kt new file mode 100644 index 00000000..b23042f6 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/Strings.kt @@ -0,0 +1,147 @@ +package network.bisq.mobile.i18n + +// TODO: Breakdown this later +data class Strings( + val splash_details_tooltip: String, + val splash_applicationServiceState_INITIALIZE_APP: String, + val splash_applicationServiceState_INITIALIZE_NETWORK: String, + val splash_applicationServiceState_INITIALIZE_WALLET: String, + val splash_applicationServiceState_INITIALIZE_SERVICES: String, + val splash_applicationServiceState_APP_INITIALIZED: String, + val splash_applicationServiceState_FAILED: String, + val splash_bootstrapState_service_CLEAR: String, + val splash_bootstrapState_service_TOR: String, + val splash_bootstrapState_service_I2P: String, + val splash_bootstrapState_network_CLEAR: String, + val splash_bootstrapState_network_TOR: String, + val splash_bootstrapState_network_I2P: String, + val splash_bootstrapState_BOOTSTRAP_TO_NETWORK: (String) -> String, + val splash_bootstrapState_START_PUBLISH_SERVICE: String, + val splash_bootstrapState_SERVICE_PUBLISHED: String, + val splash_bootstrapState_CONNECTED_TO_PEERS: String, + val tac_headline: String, + val tac_confirm: String, + val tac_accept: String, + val tac_reject: String, + val unlock_headline: String, + val unlock_button: String, + val unlock_failed: String, + val updater_headline: String, + val updater_headline_isLauncherUpdate: String, + val updater_releaseNotesHeadline: String, + val updater_furtherInfo: String, + val updater_furtherInfo_isLauncherUpdate: String, + val updater_download: String, + val updater_downloadLater: String, + val updater_ignore: String, + val updater_shutDown: String, + val updater_shutDown_isLauncherUpdate: String, + val updater_downloadAndVerify_headline: String, + val updater_downloadAndVerify_info: String, + val updater_downloadAndVerify_info_isLauncherUpdate: String, + val updater_table_file: String, + val updater_table_progress: String, + val updater_table_progress_completed: String, + val updater_table_verified: String, + val notificationPanel_trades_headline_single: String, + val notificationPanel_trades_headline_multiple: String, + val notificationPanel_trades_button: String, + val notificationPanel_mediationCases_headline_single: String, + val notificationPanel_mediationCases_headline_multiple: String, + val notificationPanel_mediationCases_button: String, + val onboarding_bisq2_headline: String, + val onboarding_bisq2_teaserHeadline1: String, + val onboarding_bisq2_line1: String, + val onboarding_bisq2_teaserHeadline2: String, + val onboarding_bisq2_line2: String, + val onboarding_bisq2_teaserHeadline3: String, + val onboarding_bisq2_line3: String, + val onboarding_button_create_profile: String, + val onboarding_createProfile_headline: String, + val onboarding_createProfile_subTitle: String, + val onboarding_createProfile_nym: String, + val onboarding_createProfile_regenerate: String, + val onboarding_createProfile_nym_generating: String, + val onboarding_createProfile_createProfile: String, + val onboarding_createProfile_createProfile_busy: String, + val onboarding_createProfile_nickName_prompt: String, + val onboarding_createProfile_nickName: String, + val onboarding_createProfile_nickName_tooLong: String, + val onboarding_password_button_skip: String, + val onboarding_password_subTitle: String, + val onboarding_password_headline_setPassword: String, + val onboarding_password_button_savePassword: String, + val onboarding_password_enterPassword: String, + val onboarding_password_confirmPassword: String, + val onboarding_password_savePassword_success: String, + val navigation_dashboard: String, + val navigation_bisqEasy: String, + val navigation_reputation: String, + val navigation_tradeApps: String, + val navigation_wallet: String, + val navigation_academy: String, + val navigation_chat: String, + val navigation_support: String, + val navigation_userOptions: String, + val navigation_settings: String, + val navigation_network: String, + val navigation_authorizedRole: String, + val navigation_expandIcon_tooltip: String, + val navigation_collapseIcon_tooltip: String, + val navigation_vertical_expandIcon_tooltip: String, + val navigation_vertical_collapseIcon_tooltip: String, + val navigation_network_info_clearNet: String, + val navigation_network_info_tor: String, + val navigation_network_info_i2p: String, + val navigation_network_info_tooltip: String, + val navigation_network_info_inventoryRequest_requesting: String, + val navigation_network_info_inventoryRequest_completed: String, + val navigation_network_info_inventoryRequests_tooltip: String, + val topPanel_wallet_balance: String, + val dashboard_marketPrice: String, + val dashboard_offersOnline: String, + val dashboard_activeUsers: String, + val dashboard_activeUsers_tooltip: String, + val dashboard_main_headline: String, + val dashboard_main_content1: String, + val dashboard_main_content2: String, + val dashboard_main_content3: String, + val dashboard_main_button: String, + val dashboard_second_headline: String, + val dashboard_second_content: String, + val dashboard_second_button: String, + val dashboard_third_headline: String, + val dashboard_third_content: String, + val dashboard_third_button: String, + val popup_headline_instruction: String, + val popup_headline_attention: String, + val popup_headline_backgroundInfo: String, + val popup_headline_feedback: String, + val popup_headline_confirmation: String, + val popup_headline_information: String, + val popup_headline_warning: String, + val popup_headline_invalid: String, + val popup_headline_error: String, + val popup_reportBug: String, + val popup_reportError: String, + val popup_reportBug_report: String, + val popup_reportError_log: String, + val popup_reportError_zipLogs: String, + val popup_reportError_gitHub: String, + val popup_startup_error: String, + val popup_shutdown: String, + val popup_shutdown_error: String, + val popup_hyperlink_openInBrowser_tooltip: String, + val popup_hyperlink_copy_tooltip: String, + val hyperlinks_openInBrowser_attention_headline: String, + val hyperlinks_openInBrowser_attention: String, + val hyperlinks_openInBrowser_no: String, + val hyperlinks_copiedToClipboard: String, + val video_mp4NotSupported_warning_headline: String, + val video_mp4NotSupported_warning: String, + val version_versionAndCommitHash: String, + + val buttons_next: String, + val buttons_submit: String, + val buttons_cancel: String, +) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt deleted file mode 100644 index bd85130c..00000000 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/EnStrings.kt +++ /dev/null @@ -1,8 +0,0 @@ -package network.bisq.mobile.presentation.i18n - -import cafe.adriel.lyricist.LyricistStrings - -@LyricistStrings(languageTag = Locales.EN, default = true) -public val EnStrings = Strings( - splash_loading_text = "Connecting to Tor Network...", -) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt deleted file mode 100644 index 9166d156..00000000 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/FrStrings.kt +++ /dev/null @@ -1,8 +0,0 @@ -package network.bisq.mobile.presentation.i18n - -import cafe.adriel.lyricist.LyricistStrings - -@LyricistStrings(languageTag = Locales.FR) -public val FrStrings = Strings( - splash_loading_text = "[FR] Connecting to Tor Network...", -) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt deleted file mode 100644 index 009b760f..00000000 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Strings.kt +++ /dev/null @@ -1,7 +0,0 @@ -package network.bisq.mobile.presentation.i18n - -import androidx.compose.ui.text.AnnotatedString - -public data class Strings( - val splash_loading_text: String, -) \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index be3d0588..18484b7e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -8,10 +8,8 @@ import cafe.adriel.lyricist.rememberStrings import org.jetbrains.compose.ui.tooling.preview.Preview import kotlinx.coroutines.flow.StateFlow +import network.bisq.mobile.i18n.Locales import org.koin.compose.koinInject -import network.bisq.mobile.presentation.ui.screens.OnBoardingScreen -import network.bisq.mobile.presentation.ui.screens.SplashScreen -import network.bisq.mobile.presentation.i18n.Locales import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt index cdb89770..e276d6be 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/ScrollLayout.kt @@ -8,7 +8,6 @@ import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import network.bisq.mobile.presentation.ui.theme.BisqTheme diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt index c6b1034d..3e2b6643 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/layout/StaticLayout.kt @@ -6,13 +6,8 @@ import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import cafe.adriel.lyricist.Lyricist -import cafe.adriel.lyricist.ProvideStrings -import cafe.adriel.lyricist.rememberStrings import network.bisq.mobile.presentation.ui.theme.BisqTheme -import network.bisq.mobile.presentation.i18n.Strings @Composable fun BisqStaticLayout( diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt index 1eb2c024..9a6498d4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt @@ -33,6 +33,7 @@ import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.img_bisq_Easy import bisqapps.shared.presentation.generated.resources.img_learn_and_discover +import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo @@ -49,6 +50,7 @@ import org.jetbrains.compose.resources.painterResource @OptIn(ExperimentalResourceApi::class) @Composable fun OnBoardingScreen(rootNavController: NavController) { + val strings = LocalStrings.current val coroutineScope = rememberCoroutineScope() val pagerState = rememberPagerState(pageCount = { onBoardingPages.size }) val presenter = remember { OnBoardingPresenter(rootNavController, pagerState, coroutineScope) } @@ -57,7 +59,7 @@ fun OnBoardingScreen(rootNavController: NavController) { BisqLogo() Spacer(modifier = Modifier.height(24.dp)) BisqText.h1Light( - text = "Welcome to Bisq", + text = strings.onboarding_bisq2_headline, color = BisqTheme.colors.grey1, ) Spacer(modifier = Modifier.height(56.dp)) @@ -65,30 +67,10 @@ fun OnBoardingScreen(rootNavController: NavController) { Spacer(modifier = Modifier.height(56.dp)) BisqButton( - text = if (pagerState.currentPage == onBoardingPages.lastIndex) "Create profile" else "Next", + text = if (pagerState.currentPage == onBoardingPages.lastIndex) strings.onboarding_button_create_profile else strings.buttons_next, onClick = { presenter.onNextButtonClick() } ) - /* - Column { - val coroutineScope = rememberCoroutineScope() - BisqButton( - text = if (pagerState.currentPage == 2) "Create profile" else "Next", - onClick = { - if (pagerState.currentPage == 2) { - rootNavController.navigate(Routes.CreateProfile.name) { - popUpTo(Routes.Onboarding.name) { inclusive = true } - } - } else { - coroutineScope.launch { - pagerState.animateScrollToPage(pagerState.currentPage + 1) - } - } - } - ) - - } - */ } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt index 1943d68c..89d22219 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt @@ -23,6 +23,9 @@ class SplashPresenter( } private fun navigateToNextScreen() { + // TODO: Conditional nav + // If firstTimeApp launch, goto Onboarding[clientMode] (androidNode / xClient) + // If not, goto TabContainerScreen navController.navigate(Routes.Onboarding.name) { popUpTo(Routes.Splash.name) { inclusive = true } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt index 0d2a22c1..4d77776e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt @@ -10,7 +10,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.navigation.NavController -import org.jetbrains.compose.resources.ExperimentalResourceApi import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.presentation.ui.components.atoms.BisqProgressBar @@ -20,12 +19,14 @@ import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout import network.bisq.mobile.presentation.ui.theme.* // TODO: Remove innerPadding once StaticLayout, ScrollLayout are fully done. +// (or) innerPadding as a param is how it's done / best practice in Compose @Composable fun SplashScreen( rootNavController: NavController, innerPadding: PaddingValues ) { + val strings = LocalStrings.current var currentProgress by remember { mutableFloatStateOf(0f) } val presenter = remember { @@ -34,8 +35,6 @@ fun SplashScreen( } } - val strings = LocalStrings.current - LaunchedEffect(Unit) { presenter.startLoading() } @@ -47,8 +46,11 @@ fun SplashScreen( Column { BisqProgressBar(progress = currentProgress) + // TODO: Get this from presenter + val networkType = strings.splash_bootstrapState_network_TOR + BisqText.baseRegular( - text = strings.splash_loading_text, // "Connecting to Tor Network...", + text = strings.splash_bootstrapState_BOOTSTRAP_TO_NETWORK(networkType), color = BisqTheme.colors.secondaryHover, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth(), diff --git a/bisqapps/tools/convert-i18n.js b/bisqapps/tools/convert-i18n.js new file mode 100644 index 00000000..9ba840ed --- /dev/null +++ b/bisqapps/tools/convert-i18n.js @@ -0,0 +1,114 @@ +// This JS script is to convert translation key, values from +// bisq2 repo (*.properties) to bisq-mobile repo (lyricist library structure) +// It's not fully automated yet, but with some configuration it works now. + +const fs = require('fs'); +const path = require('path'); + +// Define the output paths for English and French files +const outputEnFilePath = path.join(__dirname, 'GeneratedEnStrings.kt'); +const outputFrFilePath = path.join(__dirname, 'GeneratedFrStrings.kt'); + +// Function to convert the translation key to Kotlin variable name +function convertKeyToKotlinVariable(key) { + return key.replace(/\./g, '_').replace(/[{}]/g, ''); +} + +// Function to parse the .properties file with proper multi-line handling +function parsePropertiesFile(filePath) { + const content = fs.readFileSync(filePath, 'utf-8'); + const lines = content.split('\n'); + + const translations = {}; + let currentKey = null; + let currentValue = ''; + + lines.forEach(line => { + line = line.trim(); + + // Skip empty lines and comments + if (!line || line.startsWith('#')) return; + + // If line ends with "\", it's a continuation + if (line.endsWith('\\')) { + // If this is the start of a new entry, initialize currentKey and currentValue + if (line.includes('=') && !currentKey) { + const [key, ...valueParts] = line.split('='); + currentKey = key.trim(); + currentValue = valueParts.join('=').trim().slice(0, -1); // Remove the trailing "\" + } else { + // Append to the current value without the trailing "\" + currentValue += ' ' + line.slice(0, -1); + } + } else { + // Process the last line of a multi-line or a single line entry + if (line.includes('=') && !currentKey) { + // Single line entry + const [key, ...valueParts] = line.split('='); + translations[key.trim()] = valueParts.join('=').trim(); + } else if (currentKey) { + // Final line of a multi-line entry + currentValue += ' ' + line; + translations[currentKey] = currentValue; + currentKey = null; + currentValue = ''; + } + } + }); + + return translations; +} + +// Function to generate Kotlin code for English and French files +function generateKotlinCode(translations, languageTag, prefix = '') { + let stringsClass = 'data class Strings(\n'; + let stringsObject = `@LyricistStrings(languageTag = ${languageTag}, default = ${languageTag === "Locales.EN"})\nval ${languageTag}Strings = Strings(\n`; + + for (const [key, value] of Object.entries(translations)) { + const variableName = convertKeyToKotlinVariable(key); + stringsClass += ` val ${variableName}: String,\n`; + stringsObject += ` ${variableName} = "${prefix}${value.replace(/"/g, '\\"')}",\n`; + } + + stringsClass = stringsClass.trimEnd().slice(0, -1) + '\n)\n'; + stringsObject = stringsObject.trimEnd().slice(0, -1) + '\n)\n'; + + return ` +package network.bisq.mobile.presentation.i18n + +import cafe.adriel.lyricist.LyricistStrings + +// Generated Strings data class +${stringsClass} + +// Generated ${languageTag} strings +${stringsObject} +`; +} + +// Main function to run the conversion and create both files +function convertPropertiesToKotlin(propertiesFilePath) { + if (!fs.existsSync(propertiesFilePath)) { + console.error('Properties file not found:', propertiesFilePath); + return; + } + + const translations = parsePropertiesFile(propertiesFilePath); + const enKotlinCode = generateKotlinCode(translations, "Locales.EN"); + const frKotlinCode = generateKotlinCode(translations, "Locales.FR", "[FR] "); + + // Write the generated code to the output files + fs.writeFileSync(outputEnFilePath, enKotlinCode, 'utf-8'); + fs.writeFileSync(outputFrFilePath, frKotlinCode, 'utf-8'); + console.log('Kotlin strings files generated at:', outputEnFilePath, 'and', outputFrFilePath); +} + +// Run the conversion with the provided file path +const propertiesFilePath = process.argv[2]; +if (!propertiesFilePath) { + console.error('Please provide the path to the .properties file as an argument.'); + process.exit(1); +} + +convertPropertiesToKotlin(propertiesFilePath); + From 8188faeb7b02490addd557917647c6db3f0bc3f0 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Fri, 15 Nov 2024 01:08:30 +0530 Subject: [PATCH 18/31] Code review corrections 2/2 - Made use of Koin DI in SplashScreen, OnboardingScreen, GettingStartedScreen - /screens to /uicases/* --- .../data/repository/NetworkRepository.kt | 26 ++-- .../domain/data/repository/PriceRepository.kt | 34 +---- .../domain/data/repository/Repositories.kt | 1 + .../bisq/mobile/domain/di/DomainModule.kt | 4 + .../presentation/di/PresentationModule.kt | 20 +++ .../ui/navigation/graph/RootNavGraph.kt | 120 +++++++++--------- .../ui/navigation/graph/TabNavGraph.kt | 72 +++++------ .../GettingStartedPresenter.kt | 11 +- .../GettingStartedScreen.kt | 5 +- .../TabContainerScreen.kt | 2 +- .../exchange}/ExchangeScreen.kt | 2 +- .../settings}/SettingsScreen.kt | 2 +- .../startup}/CreateProfileScreen.kt | 2 +- .../startup}/OnBoardingPresenter.kt | 34 +++-- .../startup}/OnBoardingScreen.kt | 82 +++++++----- .../startup}/SplashPresenter.kt | 11 +- .../startup}/SplashScreen.kt | 18 ++- .../{screens => uicases/startup}/URLScreen.kt | 3 +- .../{screens => uicases/trades}/MyTrades.kt | 5 +- 19 files changed, 234 insertions(+), 220 deletions(-) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases}/GettingStartedPresenter.kt (81%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases}/GettingStartedScreen.kt (98%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases}/TabContainerScreen.kt (95%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/exchange}/ExchangeScreen.kt (98%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/settings}/SettingsScreen.kt (94%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/startup}/CreateProfileScreen.kt (96%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/startup}/OnBoardingPresenter.kt (56%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/startup}/OnBoardingScreen.kt (71%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/startup}/SplashPresenter.kt (68%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/startup}/SplashScreen.kt (80%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/startup}/URLScreen.kt (96%) rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{screens => uicases/trades}/MyTrades.kt (86%) diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt index bbf115b3..3143879f 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt @@ -1,15 +1,15 @@ -package network.bisq.mobile.domain.data.repository - -import kotlinx.coroutines.delay - -object NetworkRepository { - suspend fun initializeNetwork(updateProgress: (Float) -> Unit) { - //1. Initialize Tor here - //2. Connect to peers (for androidNode), to Bisq instance (for xClients) - //3. Do any other app initialization - for (i in 1..100) { - updateProgress(i.toFloat() / 100) - delay(25) + package network.bisq.mobile.domain.data.repository + + import kotlinx.coroutines.delay + + object NetworkRepository { + suspend fun initializeNetwork(updateProgress: (Float) -> Unit) { + //1. Initialize Tor here + //2. Connect to peers (for androidNode), to Bisq instance (for xClients) + //3. Do any other app initialization + for (i in 1..100) { + updateProgress(i.toFloat() / 100) + delay(25) + } } } -} diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt index e10c2b0b..f247f463 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt @@ -1,40 +1,8 @@ - +package network.bisq.mobile.domain.data.repository class PriceRepository { suspend fun fetchBtcPrice(): String = "$70,000" fun getValue() = "$70,000" - - /* - // Ktor client setup with ContentNegotiation plugin - private val client = HttpClient { - install(ContentNegotiation) { - json(Json { ignoreUnknownKeys = true }) // Configures JSON serialization - } - } - */ - - /** - * Fetches the current BTC price in USD from CoinGecko API. - */ - /* - suspend fun fetchBtcPrice(): String { - println("fetchBtcPrice()") - return withContext(Dispatchers.IO) { - try { - val response: CoinGeckoResponse = client.get("https://api.coingecko.com/api/v3/simple/price") { - parameter("ids", "bitcoin") - parameter("vs_currencies", "usd") - }.body() // Updated call to get the deserialized response body directly - println(response.toString()) - "$${response.bitcoin.usd}" - } catch (e: Exception) { - println("Error fetching BTC price: ${e.message}") - e.printStackTrace() - "Error fetching price" - } - } - } - */ } \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt index fa593a7d..4a64bc46 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt @@ -5,3 +5,4 @@ import network.bisq.mobile.domain.data.model.Greeting // this way of definingsupports both platforms // add your repositories here and then in your DI module call this classes for instanciation open class GreetingRepository: SingleObjectRepository() + diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt index 583f629d..d2be99c8 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt @@ -1,9 +1,13 @@ package network.bisq.mobile.domain.di import network.bisq.mobile.domain.data.model.Greeting +import network.bisq.mobile.domain.data.repository.BisqStatsRepository import network.bisq.mobile.domain.data.repository.GreetingRepository +import network.bisq.mobile.domain.data.repository.PriceRepository import org.koin.dsl.module val domainModule = module { single> { GreetingRepository() } + single { BisqStatsRepository() } + single { PriceRepository() } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt index cd05633d..6548d9df 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt @@ -1,10 +1,30 @@ package network.bisq.mobile.presentation.di +import androidx.navigation.NavController import network.bisq.mobile.presentation.MainPresenter import network.bisq.mobile.presentation.ui.AppPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.IOnboardingPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.ISplashPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.OnBoardingPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.SplashPresenter +import network.bisq.mobile.presentation.ui.uicases.GettingStartedPresenter +import network.bisq.mobile.presentation.ui.uicases.IGettingStarted import org.koin.dsl.bind import org.koin.dsl.module val presentationModule = module { single { MainPresenter(get()) } bind AppPresenter::class + + // TODO: Since NavController will be required for almost all Presenters for basic navigation + // Added this as top constructor level param. Is this okay? + single { (navController: NavController) -> SplashPresenter(navController) } bind ISplashPresenter::class + + single { (navController: NavController) -> OnBoardingPresenter(navController) } bind IOnboardingPresenter::class + + single { + GettingStartedPresenter( + priceRepository = get(), + bisqStatsRepository = get() + ) + } bind IGettingStarted::class } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt index 525508aa..d4a431b8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt @@ -1,59 +1,63 @@ -package network.bisq.mobile.presentation.ui.navigation.graph - -import androidx.compose.animation.AnimatedContentTransitionScope -import androidx.compose.animation.core.tween -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.navigation.NavHostController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import network.bisq.mobile.presentation.ui.navigation.* -import network.bisq.mobile.presentation.ui.screens.* -import network.bisq.mobile.presentation.ui.theme.BisqTheme - -@Composable -fun RootNavGraph( - rootNavController: NavHostController, - innerPadding: PaddingValues, - startDestination: String -) { - NavHost( - modifier = Modifier.background(color = BisqTheme.colors.backgroundColor), - navController = rootNavController, - startDestination = startDestination, - ) { - composable(route = Routes.Splash.name) { - SplashScreen(rootNavController = rootNavController, innerPadding = innerPadding) - } - composable(route = Routes.Onboarding.name, enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Left, - animationSpec = tween(300) - ) - }) { - OnBoardingScreen(rootNavController = rootNavController) - } - composable(route = Routes.CreateProfile.name, enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Left, - animationSpec = tween(300) - ) - }) { - CreateProfileScreen(rootNavController = rootNavController) - } - composable(route = Routes.BisqUrl.name, enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Left, - animationSpec = tween(300) - ) - }) { - URLScreen(rootNavController = rootNavController) - } - composable(route = Routes.TabContainer.name) { - TabContainerScreen(rootNavController = rootNavController) - } - TabNavGraph(rootNavController, innerPadding) - } +package network.bisq.mobile.presentation.ui.navigation.graph + +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import network.bisq.mobile.presentation.ui.navigation.* +import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.ui.uicases.* +import network.bisq.mobile.presentation.ui.uicases.startup.CreateProfileScreen +import network.bisq.mobile.presentation.ui.uicases.startup.OnBoardingScreen +import network.bisq.mobile.presentation.ui.uicases.startup.SplashScreen +import network.bisq.mobile.presentation.ui.uicases.startup.URLScreen + +@Composable +fun RootNavGraph( + rootNavController: NavHostController, + innerPadding: PaddingValues, + startDestination: String +) { + NavHost( + modifier = Modifier.background(color = BisqTheme.colors.backgroundColor), + navController = rootNavController, + startDestination = startDestination, + ) { + composable(route = Routes.Splash.name) { + SplashScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = Routes.Onboarding.name, enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween(300) + ) + }) { + OnBoardingScreen(rootNavController = rootNavController) + } + composable(route = Routes.CreateProfile.name, enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween(300) + ) + }) { + CreateProfileScreen(rootNavController = rootNavController) + } + composable(route = Routes.BisqUrl.name, enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween(300) + ) + }) { + URLScreen(rootNavController = rootNavController) + } + composable(route = Routes.TabContainer.name) { + TabContainerScreen(rootNavController = rootNavController) + } + TabNavGraph(rootNavController, innerPadding) + } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt index 011c7ffd..9bcea1d4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt @@ -1,37 +1,37 @@ -package network.bisq.mobile.presentation.ui.navigation.graph - -import PriceRepository -import androidx.compose.foundation.layout.PaddingValues -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavHostController -import androidx.navigation.compose.composable -import androidx.navigation.navigation -import network.bisq.mobile.domain.data.repository.BisqStatsRepository -import network.bisq.mobile.presentation.ui.navigation.Routes -import network.bisq.mobile.presentation.ui.navigation.Graph -import network.bisq.mobile.presentation.ui.screens.* - -fun NavGraphBuilder.TabNavGraph( - rootNavController: NavHostController, - innerPadding: PaddingValues -) { - navigation( - startDestination = Routes.TabHome.name, - route = Graph.MainScreenGraph - ) { - composable(route = Routes.TabHome.name) { - val presenter = GettingStartedPresenter(priceRepository = PriceRepository(), bisqStatsRepository = BisqStatsRepository()) - GettingStartedScreen(presenter = presenter, rootNavController = rootNavController, innerPadding = innerPadding) - } - composable(route = Routes.TabExchange.name) { - ExchangeScreen(rootNavController = rootNavController, innerPadding = innerPadding) - } - composable(route = Routes.TabMyTrades.name) { - MyTradesScreen(rootNavController = rootNavController, innerPadding = innerPadding) - } - composable(route = Routes.TabSettings.name) { - SettingsScreen(rootNavController = rootNavController, innerPadding = innerPadding) - } - } - +package network.bisq.mobile.presentation.ui.navigation.graph + +import androidx.compose.foundation.layout.PaddingValues +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.compose.composable +import androidx.navigation.navigation +import network.bisq.mobile.presentation.ui.navigation.Routes +import network.bisq.mobile.presentation.ui.navigation.Graph +import network.bisq.mobile.presentation.ui.uicases.GettingStartedScreen +import network.bisq.mobile.presentation.ui.uicases.exchange.ExchangeScreen +import network.bisq.mobile.presentation.ui.uicases.settings.SettingsScreen +import network.bisq.mobile.presentation.ui.uicases.trades.MyTradesScreen + +fun NavGraphBuilder.TabNavGraph( + rootNavController: NavHostController, + innerPadding: PaddingValues +) { + navigation( + startDestination = Routes.TabHome.name, + route = Graph.MainScreenGraph + ) { + composable(route = Routes.TabHome.name) { + GettingStartedScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = Routes.TabExchange.name) { + ExchangeScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = Routes.TabMyTrades.name) { + MyTradesScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + composable(route = Routes.TabSettings.name) { + SettingsScreen(rootNavController = rootNavController, innerPadding = innerPadding) + } + } + } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt similarity index 81% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedPresenter.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt index 317dde50..0fe162ae 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt @@ -1,15 +1,15 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases -import PriceRepository import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch import network.bisq.mobile.domain.data.repository.BisqStatsRepository +import network.bisq.mobile.domain.data.repository.PriceRepository import network.bisq.mobile.presentation.BasePresenter /** * Main Presenter as an example of implementation for now. */ +// open class MainPresenter(private val greetingRepository: GreetingRepository) : BasePresenter(), AppPresenter { class GettingStartedPresenter(private val priceRepository: PriceRepository, private val bisqStatsRepository: BisqStatsRepository) : BasePresenter(), IGettingStarted { private val _btcPrice = MutableStateFlow("Loading...")//("$75,000") override val btcPrice: StateFlow = _btcPrice @@ -24,11 +24,6 @@ class GettingStartedPresenter(private val priceRepository: PriceRepository, priv _btcPrice.value = priceRepository.getValue() _offersOnline.value = bisqStatsRepository.getOffersOnline() _publishedProfiles.value = bisqStatsRepository.getPublishedProfiles() - -// presenterScope.launch { -// val price = priceRepository.fetchBtcPrice() -// _btcPrice.value = price -// } } override fun onResume() { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt similarity index 98% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt index 0f615042..97169bbc 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/GettingStartedScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -39,6 +39,7 @@ import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource +import org.koin.compose.koinInject interface IGettingStarted { val btcPrice: StateFlow @@ -48,10 +49,10 @@ interface IGettingStarted { @Composable fun GettingStartedScreen( - presenter: IGettingStarted, rootNavController: NavController, innerPadding: PaddingValues, ) { + val presenter: IGettingStarted = koinInject() val btcPrice:String = presenter.btcPrice.collectAsState().value val offersOnline:Number = presenter.offersOnline.collectAsState().value val publishedProfiles:Number = presenter.publishedProfiles.collectAsState().value diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt similarity index 95% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt index a624a254..28aa6ac4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/TabContainerScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt similarity index 98% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt index 78c77a7f..daa4e9b3 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.exchange import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt similarity index 94% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt index 72ee31b4..f838f0f7 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SettingsScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt @@ -1,5 +1,5 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.settings import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt similarity index 96% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt index 2d281532..643ba324 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.startup import androidx.compose.foundation.* import androidx.compose.foundation.layout.* diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt similarity index 56% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingPresenter.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt index c066ce20..5ace6d37 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.startup import androidx.compose.foundation.pager.PagerState @@ -9,7 +9,10 @@ import bisqapps.shared.presentation.generated.resources.img_fiat_btc import bisqapps.shared.presentation.generated.resources.img_learn_and_discover import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch +import network.bisq.mobile.presentation.BasePresenter import network.bisq.mobile.presentation.ui.model.OnBoardingPage import network.bisq.mobile.presentation.ui.navigation.Routes @@ -31,21 +34,26 @@ val onBoardingPages = listOf( ) ) -class OnBoardingPresenter( - private val navController: NavController, - val pagerState: PagerState, - private val coroutineScope: CoroutineScope, -) { - // private val coroutineScope = CoroutineScope(Dispatchers.Main) +open class OnBoardingPresenter(private val navController: NavController) : BasePresenter(), IOnboardingPresenter { - fun onNextButtonClick() { + private val _pagerState = MutableStateFlow(null) + override val pagerState: StateFlow = _pagerState + + fun setPagerState(pagerState: PagerState) { + _pagerState.value = pagerState + } + + override fun onNextButtonClick(coroutineScope: CoroutineScope) { coroutineScope.launch { - if (pagerState.currentPage == onBoardingPages.lastIndex) { - navController.navigate(Routes.CreateProfile.name) { - popUpTo(Routes.Onboarding.name) { inclusive = true } + val state = pagerState.value + if (state != null) { + if (state.currentPage == onBoardingPages.lastIndex) { + navController.navigate(Routes.CreateProfile.name) { + popUpTo(Routes.Onboarding.name) { inclusive = true } + } + } else { + state.animateScrollToPage(state.currentPage + 1) } - } else { - pagerState.animateScrollToPage(pagerState.currentPage + 1) } } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt similarity index 71% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt index 9a6498d4..85772b81 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.startup import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -17,10 +17,7 @@ import androidx.compose.foundation.pager.PageSize import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -30,22 +27,28 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.* -import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.img_bisq_Easy -import bisqapps.shared.presentation.generated.resources.img_learn_and_discover import cafe.adriel.lyricist.LocalStrings +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo import network.bisq.mobile.presentation.ui.components.atoms.BisqButton import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqScrollLayout -import network.bisq.mobile.presentation.ui.model.OnBoardingPage -import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource +import org.koin.compose.koinInject +import org.koin.core.parameter.parametersOf + +interface IOnboardingPresenter { + + val pagerState: StateFlow + // Actions + fun onNextButtonClick(coroutineScope: CoroutineScope) +} @OptIn(ExperimentalResourceApi::class) @Composable @@ -53,7 +56,12 @@ fun OnBoardingScreen(rootNavController: NavController) { val strings = LocalStrings.current val coroutineScope = rememberCoroutineScope() val pagerState = rememberPagerState(pageCount = { onBoardingPages.size }) - val presenter = remember { OnBoardingPresenter(rootNavController, pagerState, coroutineScope) } + val presenter: IOnboardingPresenter = koinInject { parametersOf(rootNavController) } + + // TODO: Any other better way to do this? + LaunchedEffect(pagerState) { + (presenter as? OnBoardingPresenter)?.setPagerState(pagerState) + } BisqScrollLayout() { BisqLogo() @@ -68,7 +76,7 @@ fun OnBoardingScreen(rootNavController: NavController) { BisqButton( text = if (pagerState.currentPage == onBoardingPages.lastIndex) strings.onboarding_button_create_profile else strings.buttons_next, - onClick = { presenter.onNextButtonClick() } + onClick = { presenter.onNextButtonClick(coroutineScope) } ) } @@ -76,32 +84,36 @@ fun OnBoardingScreen(rootNavController: NavController) { } @Composable -fun PagerView(presenter: OnBoardingPresenter) { +fun PagerView(presenter: IOnboardingPresenter) { - CompositionLocalProvider(values = arrayOf()) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(36.dp, Alignment.CenterVertically), - ) { - HorizontalPager( - pageSpacing = 56.dp, - contentPadding = PaddingValues(horizontal = 36.dp), - pageSize = PageSize.Fill, - verticalAlignment = Alignment.CenterVertically, - state = presenter.pagerState - ) { index -> - onBoardingPages.getOrNull( - index % (onBoardingPages.size) - )?.let { item -> - BannerItem( - image = item.image, - title = item.title, - desc = item.desc, - index = index, - ) + val pagerState = presenter.pagerState.collectAsState().value + + pagerState?.let { + CompositionLocalProvider(values = arrayOf()) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(36.dp, Alignment.CenterVertically), + ) { + HorizontalPager( + pageSpacing = 56.dp, + contentPadding = PaddingValues(horizontal = 36.dp), + pageSize = PageSize.Fill, + verticalAlignment = Alignment.CenterVertically, + state = it + ) { index -> + onBoardingPages.getOrNull( + index % (onBoardingPages.size) + )?.let { item -> + BannerItem( + image = item.image, + title = item.title, + desc = item.desc, + index = index, + ) + } } + LineIndicator(pagerState = it) } - LineIndicator(pagerState = presenter.pagerState) } } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt similarity index 68% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt index 89d22219..77b4da9b 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt @@ -1,19 +1,18 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.startup import androidx.navigation.NavController import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import network.bisq.mobile.domain.data.repository.NetworkRepository +import network.bisq.mobile.presentation.BasePresenter import network.bisq.mobile.presentation.ui.navigation.Routes -class SplashPresenter( - private val navController: NavController, - private val onProgressUpdate: (Float) -> Unit -) { +// open class MainPresenter(private val greetingRepository: GreetingRepository) : BasePresenter(), AppPresenter { +open class SplashPresenter(private val navController: NavController) : BasePresenter(), ISplashPresenter { private val coroutineScope = CoroutineScope(Dispatchers.Main) - fun startLoading() { + override fun startLoading(onProgressUpdate: (Float) -> Unit) { coroutineScope.launch { NetworkRepository.initializeNetwork { progress -> onProgressUpdate(progress) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt similarity index 80% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt index 4d77776e..c8e7ec31 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.startup import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable @@ -17,6 +17,13 @@ import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout import network.bisq.mobile.presentation.ui.theme.* +import org.koin.compose.koinInject +import org.koin.core.parameter.parametersOf + +interface ISplashPresenter { + // Actions + fun startLoading(onProgressUpdate: (Float) -> Unit) +} // TODO: Remove innerPadding once StaticLayout, ScrollLayout are fully done. // (or) innerPadding as a param is how it's done / best practice in Compose @@ -28,17 +35,14 @@ fun SplashScreen( val strings = LocalStrings.current var currentProgress by remember { mutableFloatStateOf(0f) } + val presenter: ISplashPresenter = koinInject { parametersOf(rootNavController) } - val presenter = remember { - SplashPresenter(rootNavController) { progress -> + LaunchedEffect(Unit) { + presenter.startLoading { progress -> currentProgress = progress } } - LaunchedEffect(Unit) { - presenter.startLoading() - } - // Render the layout BisqStaticLayout { BisqLogo() diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/URLScreen.kt similarity index 96% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/URLScreen.kt index 52ea8e77..784e4012 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/URLScreen.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.startup import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween @@ -33,6 +33,7 @@ import org.jetbrains.compose.resources.painterResource private lateinit var textState: MutableState +//TODO: Rename this to BisqConnectScreen? @OptIn(ExperimentalResourceApi::class) @Composable fun URLScreen( diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt similarity index 86% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt index 935509ca..682a6518 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/screens/MyTrades.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt @@ -1,16 +1,13 @@ -package network.bisq.mobile.presentation.ui.screens +package network.bisq.mobile.presentation.ui.uicases.trades import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.sp import androidx.navigation.NavController import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme From 328a07ae0f3acdbba955815af1943f5eaa546760 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Fri, 15 Nov 2024 23:29:28 +0530 Subject: [PATCH 19/31] Code review corrections 3/n (This partial commit fails in android) - Better data models and repositories in 'domain' - Better DI usage with screens and presenters, by moving navControllers into DI (But having some issue now, which stops tab based nav from working. RootNavGraph, TabNavGraph probably need some refactor) - Few other minor feedback corrections --- bisqapps/gradle/libs.versions.toml | 2 -- .../mobile/domain/data/model/BisqStats.kt | 24 +++++++++++++ .../mobile/domain/data/model/BtcFiatPrice.kt | 23 ++++++++++++ .../data/repository/BisqStatsRepository.kt | 9 ----- .../domain/data/repository/PriceRepository.kt | 8 ----- .../domain/data/repository/Repositories.kt | 4 +++ .../bisq/mobile/domain/di/DomainModule.kt | 8 +++-- .../presentation/di/PresentationModule.kt | 8 +++++ .../bisq/mobile/presentation/ui/App.kt | 25 +++++++++---- .../ui/{model => composeModels}/model.kt | 2 +- .../ui/navigation/BottomNavigation.kt | 2 +- .../presentation/ui/navigation/README.md | 28 +++++++++++++++ .../presentation/ui/navigation/Routes.kt | 2 +- .../ui/navigation/graph/RootNavGraph.kt | 31 ++++++++++------ .../ui/navigation/graph/TabNavGraph.kt | 15 +++----- .../ui/uicases/GettingStartedPresenter.kt | 36 +++++++++++++------ .../ui/uicases/GettingStartedScreen.kt | 10 ++---- .../ui/uicases/TabContainerScreen.kt | 17 ++++----- .../ui/uicases/exchange/ExchangeScreen.kt | 14 +++----- .../ui/uicases/settings/SettingsScreen.kt | 9 ++--- .../ui/uicases/startup/CreateProfileScreen.kt | 7 ++-- .../ui/uicases/startup/OnBoardingPresenter.kt | 2 +- .../ui/uicases/startup/OnBoardingScreen.kt | 9 ++--- .../ui/uicases/startup/SplashPresenter.kt | 1 - .../ui/uicases/startup/SplashScreen.kt | 9 ++--- ...URLScreen.kt => TrustedNodeSetupScreen.kt} | 11 +++--- .../ui/uicases/trades/MyTrades.kt | 10 +++--- 27 files changed, 214 insertions(+), 112 deletions(-) create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt delete mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt delete mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/{model => composeModels}/model.kt (81%) create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/README.md rename bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/{URLScreen.kt => TrustedNodeSetupScreen.kt} (91%) diff --git a/bisqapps/gradle/libs.versions.toml b/bisqapps/gradle/libs.versions.toml index 9ed6fea2..5fe7d489 100644 --- a/bisqapps/gradle/libs.versions.toml +++ b/bisqapps/gradle/libs.versions.toml @@ -86,14 +86,12 @@ typesafe-config = { module = 'com.typesafe:config', version.ref = 'typesafe-conf bouncycastle = { module = 'org.bouncycastle:bcprov-jdk18on', version.ref = 'bouncycastle-lib' } bouncycastle-pg = { module = 'org.bouncycastle:bcpg-jdk18on', version.ref = 'bouncycastle-lib' } -#protobuf-lite = { group ="com.google.protobuf", name = "protobuf-javalite", version.ref = "protoblite"} lyricist = { module = "cafe.adriel.lyricist:lyricist", version.ref = "lyricist" } navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "navigationCompose" } protobuf-lite = { group ="com.google.protobuf", name = "protobuf-javalite", version.ref = "protoblite"} protobuf-gradle-plugin = { module = 'com.google.protobuf:protobuf-gradle-plugin', version.ref = 'protobuf' } protoc = { module = "com.google.protobuf:protoc", version.ref = "protob" } - bisq-core-common = { module = "bisq:common", version.ref = "bisq-core" } bisq-core-security = { module = "bisq:security", version.ref = "bisq-core" } bisq-core-settings = { module = "bisq:settings", version.ref = "bisq-core" } diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt new file mode 100644 index 00000000..27360edd --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt @@ -0,0 +1,24 @@ + +package network.bisq.mobile.domain.data.model + +open class BisqStats: BaseModel() { + protected open val offersOnline = 150 + + protected open val publishedProfiles = 1275 + + fun getOffersOnline(): Int { + return offersOnline + } + + fun getPublishedProfiles(): Int { + return publishedProfiles + } +} + +interface BisqStatsFactory { + fun createBisqStats(): BisqStats +} + +class DefaultBisqStatsFactory : BisqStatsFactory { + override fun createBisqStats() = BisqStats() +} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt new file mode 100644 index 00000000..5168e00c --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt @@ -0,0 +1,23 @@ +package network.bisq.mobile.domain.data.model + +open class BtcPrice: BaseModel() { + + protected open val prices: Map = mapOf( + "USD" to 64000.50, + "EUR" to 58000.75, + "GBP" to 52000.30, + ) + + fun getBtcPrice(): Map { + return prices + } + +} + +interface BtcPriceFactory { + fun createBtcPrice(): BtcPrice +} + +class DefaultBtcPriceeFactory : BtcPriceFactory { + override fun createBtcPrice() = BtcPrice() +} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt deleted file mode 100644 index 01919f1a..00000000 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/BisqStatsRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package network.bisq.mobile.domain.data.repository - - -class BisqStatsRepository() { - - fun getOffersOnline() = 120 - - fun getPublishedProfiles() = 610 -} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt deleted file mode 100644 index f247f463..00000000 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/PriceRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package network.bisq.mobile.domain.data.repository - -class PriceRepository { - - suspend fun fetchBtcPrice(): String = "$70,000" - fun getValue() = "$70,000" - -} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt index 4a64bc46..c65404e0 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt @@ -1,8 +1,12 @@ package network.bisq.mobile.domain.data.repository +import network.bisq.mobile.domain.data.model.BtcPrice +import network.bisq.mobile.domain.data.model.BisqStats import network.bisq.mobile.domain.data.model.Greeting // this way of definingsupports both platforms // add your repositories here and then in your DI module call this classes for instanciation open class GreetingRepository: SingleObjectRepository() +open class BisqStatsRepository: SingleObjectRepository() +open class BtcPriceRepository: SingleObjectRepository() diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt index d2be99c8..2de0eaeb 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt @@ -1,13 +1,15 @@ package network.bisq.mobile.domain.di +import network.bisq.mobile.domain.data.model.BtcPrice +import network.bisq.mobile.domain.data.model.BisqStats import network.bisq.mobile.domain.data.model.Greeting import network.bisq.mobile.domain.data.repository.BisqStatsRepository +import network.bisq.mobile.domain.data.repository.BtcPriceRepository import network.bisq.mobile.domain.data.repository.GreetingRepository -import network.bisq.mobile.domain.data.repository.PriceRepository import org.koin.dsl.module val domainModule = module { single> { GreetingRepository() } - single { BisqStatsRepository() } - single { PriceRepository() } + single> { BisqStatsRepository() } + single> { BtcPriceRepository() } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt index 6548d9df..31ac1095 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt @@ -1,6 +1,8 @@ package network.bisq.mobile.presentation.di +import androidx.compose.runtime.mutableStateOf import androidx.navigation.NavController +import androidx.navigation.NavHostController import network.bisq.mobile.presentation.MainPresenter import network.bisq.mobile.presentation.ui.AppPresenter import network.bisq.mobile.presentation.ui.uicases.startup.IOnboardingPresenter @@ -9,10 +11,16 @@ import network.bisq.mobile.presentation.ui.uicases.startup.OnBoardingPresenter import network.bisq.mobile.presentation.ui.uicases.startup.SplashPresenter import network.bisq.mobile.presentation.ui.uicases.GettingStartedPresenter import network.bisq.mobile.presentation.ui.uicases.IGettingStarted +import org.koin.core.qualifier.named import org.koin.dsl.bind import org.koin.dsl.module val presentationModule = module { + + single { error("NavController has not been initialized yet") } + single(named("RootNavController")) { getKoin().getProperty("RootNavController") } + single(named("TabNavController")) { getKoin().getProperty("TabNavController") } + single { MainPresenter(get()) } bind AppPresenter::class // TODO: Since NavController will be required for almost all Presenters for basic navigation diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index 18484b7e..b43368dc 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -2,6 +2,7 @@ package network.bisq.mobile.presentation.ui import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.* +import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import cafe.adriel.lyricist.ProvideStrings import cafe.adriel.lyricist.rememberStrings @@ -14,6 +15,7 @@ import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph import network.bisq.mobile.presentation.ui.theme.BisqTheme +import org.koin.mp.KoinPlatform.getKoin interface AppPresenter { // Observables for state @@ -30,19 +32,30 @@ interface AppPresenter { @Composable @Preview fun App() { + + val rootNavController = rememberNavController() + val tabNavController = rememberNavController() + + var isNavControllerSet by remember { mutableStateOf(false) } + + LaunchedEffect(rootNavController) { + getKoin().setProperty("RootNavController", rootNavController) + getKoin().setProperty("TabNavController", tabNavController) + isNavControllerSet = true + } + val presenter: AppPresenter = koinInject() - val navController = rememberNavController() val lyricist = rememberStrings() lyricist.languageTag = Locales.FR BisqTheme(darkTheme = true) { ProvideStrings(lyricist) { - RootNavGraph( - rootNavController = navController, - innerPadding = PaddingValues(), - startDestination = Routes.Splash.name - ) + if (isNavControllerSet) { + RootNavGraph( + startDestination = Routes.Splash.name + ) + } } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/composeModels/model.kt similarity index 81% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/composeModels/model.kt index 7fcdf59d..f5e9f215 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/model/model.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/composeModels/model.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.model +package network.bisq.mobile.presentation.ui.composeModels import org.jetbrains.compose.resources.DrawableResource diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt index ad95c5bf..356317c8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/BottomNavigation.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.unit.dp import network.bisq.mobile.presentation.ui.components.atoms.BisqText -import network.bisq.mobile.presentation.ui.model.BottomNavigationItem +import network.bisq.mobile.presentation.ui.composeModels.BottomNavigationItem import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/README.md b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/README.md new file mode 100644 index 00000000..6c46b5dd --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/README.md @@ -0,0 +1,28 @@ +# Navigation Overview + +The app uses **Jetpack Compose Navigation**. + +### 1. Routes +- All routes are defined in `Routes.kt` as an `enum` for unique screen identifiers. +- Like + - /splash + - /onboarding + + +### 2. Root Navigation +- `RootNavGraph.kt` defines the top-level flow using `NavHost`. +- Maps routes to Screens with transitions like + - /splash - SplashScreen + - /onboarding -> OnboardingScreen + +### 3. Tab Navigation +- `TabNavGraph.kt` manages nested tab-based screens (`Home`, `Exchange`, `MyTrades`, `Settings`). + +### 4. Bottom Navigation +- Composable that renders the bottom navigation bar. +- Exact tabbar items are received via `items` prop. + +Ref links: + - https://developer.android.com/develop/ui/compose/navigation + - https://developer.android.com/codelabs/basic-android-kotlin-compose-navigation#0 + - https://medium.com/@KaushalVasava/navigation-in-jetpack-compose-full-guide-beginner-to-advanced-950c1133740 diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt index bf44f1b8..62f6aebb 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt @@ -10,7 +10,7 @@ enum class Routes(val title: String) { Splash(title = "splash"), Onboarding(title = "onboarding"), CreateProfile(title = "create_profile"), - BisqUrl(title = "bisq_url"), + TrustedNodeSetup(title = "trusted_node_setup"), TabContainer(title = "tab_container"), TabHome(title = "tab_home"), TabExchange(title = "tab_exchange"), diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt index d4a431b8..6dd1f2c4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/RootNavGraph.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.navigation.NavController import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -15,21 +16,29 @@ import network.bisq.mobile.presentation.ui.uicases.* import network.bisq.mobile.presentation.ui.uicases.startup.CreateProfileScreen import network.bisq.mobile.presentation.ui.uicases.startup.OnBoardingScreen import network.bisq.mobile.presentation.ui.uicases.startup.SplashScreen -import network.bisq.mobile.presentation.ui.uicases.startup.URLScreen +import network.bisq.mobile.presentation.ui.uicases.startup.TrustedNodeSetupScreen +import org.koin.compose.koinInject +import org.koin.core.qualifier.named @Composable fun RootNavGraph( - rootNavController: NavHostController, - innerPadding: PaddingValues, startDestination: String ) { + val navControllerDIName = if (startDestination == Routes.Splash.name) "RootNavController" else "TabNavController" + val navController: NavHostController = koinInject(named(navControllerDIName)) + + //TODO: [Need refactor] This is confusing / not proper. But for now, it works! + //To have both primary screens and Tab bar screens inside a single NavHost. + //At runtime, 2 actually instances are created. + //If the code also reflects the same, it will be even easy to understand. + NavHost( modifier = Modifier.background(color = BisqTheme.colors.backgroundColor), - navController = rootNavController, + navController = navController, startDestination = startDestination, ) { composable(route = Routes.Splash.name) { - SplashScreen(rootNavController = rootNavController, innerPadding = innerPadding) + SplashScreen() } composable(route = Routes.Onboarding.name, enterTransition = { slideIntoContainer( @@ -37,7 +46,7 @@ fun RootNavGraph( animationSpec = tween(300) ) }) { - OnBoardingScreen(rootNavController = rootNavController) + OnBoardingScreen() } composable(route = Routes.CreateProfile.name, enterTransition = { slideIntoContainer( @@ -45,19 +54,19 @@ fun RootNavGraph( animationSpec = tween(300) ) }) { - CreateProfileScreen(rootNavController = rootNavController) + CreateProfileScreen() } - composable(route = Routes.BisqUrl.name, enterTransition = { + composable(route = Routes.TrustedNodeSetup.name, enterTransition = { slideIntoContainer( AnimatedContentTransitionScope.SlideDirection.Left, animationSpec = tween(300) ) }) { - URLScreen(rootNavController = rootNavController) + TrustedNodeSetupScreen() } composable(route = Routes.TabContainer.name) { - TabContainerScreen(rootNavController = rootNavController) + TabContainerScreen() } - TabNavGraph(rootNavController, innerPadding) + TabNavGraph() } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt index 9bcea1d4..31a85eb6 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt @@ -1,8 +1,6 @@ package network.bisq.mobile.presentation.ui.navigation.graph -import androidx.compose.foundation.layout.PaddingValues import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavHostController import androidx.navigation.compose.composable import androidx.navigation.navigation import network.bisq.mobile.presentation.ui.navigation.Routes @@ -12,25 +10,22 @@ import network.bisq.mobile.presentation.ui.uicases.exchange.ExchangeScreen import network.bisq.mobile.presentation.ui.uicases.settings.SettingsScreen import network.bisq.mobile.presentation.ui.uicases.trades.MyTradesScreen -fun NavGraphBuilder.TabNavGraph( - rootNavController: NavHostController, - innerPadding: PaddingValues -) { +fun NavGraphBuilder.TabNavGraph() { navigation( startDestination = Routes.TabHome.name, route = Graph.MainScreenGraph ) { composable(route = Routes.TabHome.name) { - GettingStartedScreen(rootNavController = rootNavController, innerPadding = innerPadding) + GettingStartedScreen() } composable(route = Routes.TabExchange.name) { - ExchangeScreen(rootNavController = rootNavController, innerPadding = innerPadding) + ExchangeScreen() } composable(route = Routes.TabMyTrades.name) { - MyTradesScreen(rootNavController = rootNavController, innerPadding = innerPadding) + MyTradesScreen() } composable(route = Routes.TabSettings.name) { - SettingsScreen(rootNavController = rootNavController, innerPadding = innerPadding) + SettingsScreen() } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt index 0fe162ae..0e18022d 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt @@ -1,29 +1,43 @@ package network.bisq.mobile.presentation.ui.uicases +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import network.bisq.mobile.domain.data.model.BisqStats +import network.bisq.mobile.domain.data.model.BtcPrice import network.bisq.mobile.domain.data.repository.BisqStatsRepository -import network.bisq.mobile.domain.data.repository.PriceRepository +import network.bisq.mobile.domain.data.repository.BtcPriceRepository import network.bisq.mobile.presentation.BasePresenter -/** - * Main Presenter as an example of implementation for now. - */ -// open class MainPresenter(private val greetingRepository: GreetingRepository) : BasePresenter(), AppPresenter { -class GettingStartedPresenter(private val priceRepository: PriceRepository, private val bisqStatsRepository: BisqStatsRepository) : BasePresenter(), IGettingStarted { +class GettingStartedPresenter(private val priceRepository: BtcPriceRepository, private val bisqStatsRepository: BisqStatsRepository) : BasePresenter(), IGettingStarted { private val _btcPrice = MutableStateFlow("Loading...")//("$75,000") override val btcPrice: StateFlow = _btcPrice private val _offersOnline = MutableStateFlow(145) - override val offersOnline: StateFlow = _offersOnline + override val offersOnline: StateFlow = _offersOnline private val _publishedProfiles = MutableStateFlow(1145) - override val publishedProfiles: StateFlow = _publishedProfiles + override val publishedProfiles: StateFlow = _publishedProfiles fun refresh() { - _btcPrice.value = priceRepository.getValue() - _offersOnline.value = bisqStatsRepository.getOffersOnline() - _publishedProfiles.value = bisqStatsRepository.getPublishedProfiles() + CoroutineScope(Dispatchers.IO).launch { + try { + val bisqStats = bisqStatsRepository.fetch() + _offersOnline.value = bisqStats?.getOffersOnline() ?: 0 + _publishedProfiles.value = bisqStats?.getPublishedProfiles() ?: 0 + + val btcPrice = priceRepository.fetch() + val priceList = btcPrice?.getBtcPrice() + _btcPrice.value = (priceList?.get("USD") ?: 0).toString() + } catch (e: Exception) { + // Handle errors + println("Error: ${e.message}") + } + } + } override fun onResume() { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt index 97169bbc..0306aea6 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.icon_tag_outlined @@ -48,18 +49,13 @@ interface IGettingStarted { } @Composable -fun GettingStartedScreen( - rootNavController: NavController, - innerPadding: PaddingValues, -) { +fun GettingStartedScreen() { val presenter: IGettingStarted = koinInject() val btcPrice:String = presenter.btcPrice.collectAsState().value val offersOnline:Number = presenter.offersOnline.collectAsState().value val publishedProfiles:Number = presenter.publishedProfiles.collectAsState().value Column( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding), + modifier = Modifier.fillMaxSize(), ) { // TODO: Should be a child of Scaffold, in TabContainerScreen TopBar(isHome = true) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt index 28aa6ac4..35e00fce 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt @@ -1,21 +1,22 @@ package network.bisq.mobile.presentation.ui.uicases import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.navigation.NavController +import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import bisqapps.shared.presentation.generated.resources.* import bisqapps.shared.presentation.generated.resources.Res -import network.bisq.mobile.presentation.ui.model.BottomNavigationItem +import network.bisq.mobile.presentation.ui.composeModels.BottomNavigationItem import network.bisq.mobile.presentation.ui.navigation.BottomNavigation import network.bisq.mobile.presentation.ui.navigation.Graph import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph import network.bisq.mobile.presentation.ui.theme.BisqTheme +import org.koin.compose.koinInject +import org.koin.core.qualifier.named +import org.koin.mp.KoinPlatform.getKoin val navigationListItem = listOf( BottomNavigationItem("Home", Routes.TabHome.name, Res.drawable.icon_home), @@ -26,8 +27,8 @@ val navigationListItem = listOf( @Composable -fun TabContainerScreen( rootNavController: NavController) { - val navController = rememberNavController() +fun TabContainerScreen() { + val navController: NavHostController = koinInject(named("TabNavController")) val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute by remember(navBackStackEntry) { derivedStateOf { @@ -55,6 +56,6 @@ fun TabContainerScreen( rootNavController: NavController) { } ) { innerPadding -> - RootNavGraph(rootNavController = navController,innerPadding = innerPadding, startDestination = Graph.MainScreenGraph) + RootNavGraph(startDestination = Graph.MainScreenGraph) } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt index daa4e9b3..314dd7df 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.currency_euro import bisqapps.shared.presentation.generated.resources.currency_gpb @@ -29,20 +30,15 @@ import network.bisq.mobile.components.MaterialTextField import network.bisq.mobile.presentation.ui.components.molecules.TopBar import network.bisq.mobile.presentation.ui.components.atoms.icons.SortIcon import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.koin.compose.koinInject @OptIn(ExperimentalResourceApi::class) @Composable -fun ExchangeScreen( - rootNavController: NavController, - innerPadding: PaddingValues -) { +fun ExchangeScreen() { + val navController: NavHostController = koinInject() val originDirection = LocalLayoutDirection.current Column( - modifier = Modifier.fillMaxSize().padding( - start = innerPadding.calculateStartPadding(originDirection), - end = innerPadding.calculateEndPadding(originDirection), - bottom = innerPadding.calculateBottomPadding(), - ), + modifier = Modifier.fillMaxSize() ) { TopBar("Buy/Sell") Column(modifier = Modifier.padding(vertical = 12.dp, horizontal = 32.dp)) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt index f838f0f7..c8d789b8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt @@ -9,19 +9,20 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.navigation.NavController +import androidx.navigation.NavHostController import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.koin.compose.koinInject @OptIn(ExperimentalResourceApi::class) @Composable -fun SettingsScreen(rootNavController: NavController, - innerPadding: PaddingValues +fun SettingsScreen( ) { + val navController: NavHostController = koinInject() Box( modifier = Modifier - .fillMaxSize() - .padding(innerPadding), // Applies the inner padding if necessary + .fillMaxSize(), contentAlignment = Alignment.Center // Centers the content within the Box ) { BisqText.h2Regular( diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt index 643ba324..31854d28 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.img_bot_image import network.bisq.mobile.components.MaterialTextField @@ -21,14 +22,16 @@ import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource +import org.koin.compose.koinInject +import org.koin.core.qualifier.named private lateinit var textState: MutableState @OptIn(ExperimentalResourceApi::class) @Composable fun CreateProfileScreen( - rootNavController: NavController ) { + val navController: NavHostController = koinInject(named("RootNavController")) textState = remember { mutableStateOf("") } BisqScrollLayout() { BisqLogo() @@ -77,7 +80,7 @@ fun CreateProfileScreen( "Next", onClick = { if (textState.value.isNotEmpty()) { - rootNavController.navigate(Routes.BisqUrl.name) { + navController.navigate(Routes.TrustedNodeSetup.name) { popUpTo(Routes.CreateProfile.name) { inclusive = true } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt index 5ace6d37..844a1df8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt @@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import network.bisq.mobile.presentation.BasePresenter -import network.bisq.mobile.presentation.ui.model.OnBoardingPage +import network.bisq.mobile.presentation.ui.composeModels.OnBoardingPage import network.bisq.mobile.presentation.ui.navigation.Routes val onBoardingPages = listOf( diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt index 85772b81..d5104bba 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt @@ -25,13 +25,12 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.navigation.NavController +import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.* import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo import network.bisq.mobile.presentation.ui.components.atoms.BisqButton import network.bisq.mobile.presentation.ui.components.atoms.BisqText @@ -42,6 +41,7 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource import org.koin.compose.koinInject import org.koin.core.parameter.parametersOf +import org.koin.core.qualifier.named interface IOnboardingPresenter { @@ -52,11 +52,12 @@ interface IOnboardingPresenter { @OptIn(ExperimentalResourceApi::class) @Composable -fun OnBoardingScreen(rootNavController: NavController) { +fun OnBoardingScreen() { val strings = LocalStrings.current + val navController: NavHostController = koinInject(named("RootNavController")) val coroutineScope = rememberCoroutineScope() val pagerState = rememberPagerState(pageCount = { onBoardingPages.size }) - val presenter: IOnboardingPresenter = koinInject { parametersOf(rootNavController) } + val presenter: IOnboardingPresenter = koinInject { parametersOf(navController) } // TODO: Any other better way to do this? LaunchedEffect(pagerState) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt index 77b4da9b..90e1b02a 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt @@ -8,7 +8,6 @@ import network.bisq.mobile.domain.data.repository.NetworkRepository import network.bisq.mobile.presentation.BasePresenter import network.bisq.mobile.presentation.ui.navigation.Routes -// open class MainPresenter(private val greetingRepository: GreetingRepository) : BasePresenter(), AppPresenter { open class SplashPresenter(private val navController: NavController) : BasePresenter(), ISplashPresenter { private val coroutineScope = CoroutineScope(Dispatchers.Main) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt index c8e7ec31..929d4ed8 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.navigation.NavController +import androidx.navigation.NavHostController import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.presentation.ui.components.atoms.BisqProgressBar @@ -19,6 +20,7 @@ import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout import network.bisq.mobile.presentation.ui.theme.* import org.koin.compose.koinInject import org.koin.core.parameter.parametersOf +import org.koin.core.qualifier.named interface ISplashPresenter { // Actions @@ -29,13 +31,12 @@ interface ISplashPresenter { // (or) innerPadding as a param is how it's done / best practice in Compose @Composable fun SplashScreen( - rootNavController: NavController, - innerPadding: PaddingValues ) { - + // val rootNavController: NavHostController = koinInject() + val navController: NavHostController = koinInject(named("RootNavController")) val strings = LocalStrings.current var currentProgress by remember { mutableFloatStateOf(0f) } - val presenter: ISplashPresenter = koinInject { parametersOf(rootNavController) } + val presenter: ISplashPresenter = koinInject { parametersOf(navController) } LaunchedEffect(Unit) { presenter.startLoading { progress -> diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/URLScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt similarity index 91% rename from bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/URLScreen.kt rename to bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt index 784e4012..bf062309 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/URLScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.icon_question_mark import network.bisq.mobile.components.MaterialTextField @@ -30,15 +31,17 @@ import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.ui.theme.* import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource +import org.koin.compose.koinInject +import org.koin.core.qualifier.named private lateinit var textState: MutableState //TODO: Rename this to BisqConnectScreen? @OptIn(ExperimentalResourceApi::class) @Composable -fun URLScreen( - rootNavController: NavController +fun TrustedNodeSetupScreen( ) { + val navController: NavHostController = koinInject(named("RootNavController")) textState = remember { mutableStateOf("") } val isConnected by remember { mutableStateOf(false) } @@ -139,8 +142,8 @@ fun URLScreen( text = "Next", color = BisqTheme.colors.light1, onClick = { - rootNavController.navigate(Routes.TabContainer.name) { - popUpTo(Routes.BisqUrl.name) { + navController.navigate(Routes.TabContainer.name) { + popUpTo(Routes.TrustedNodeSetup.name) { inclusive = true } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt index 682a6518..0c441d48 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt @@ -9,19 +9,19 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.navigation.NavController +import androidx.navigation.NavHostController import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.koin.compose.koinInject @OptIn(ExperimentalResourceApi::class) @Composable -fun MyTradesScreen(rootNavController: NavController, - innerPadding: PaddingValues -) { +fun MyTradesScreen() { + val rootNavController: NavHostController = koinInject() Box( modifier = Modifier - .fillMaxSize() - .padding(innerPadding), // Applies the inner padding if necessary + .fillMaxSize(), contentAlignment = Alignment.Center // Centers the content within the Box ) { BisqText.h2Regular( From 7deb383e3f9f171dcf11a58eeb4693de46e28511 Mon Sep 17 00:00:00 2001 From: Rodrigo Varela Date: Sat, 16 Nov 2024 08:35:15 +1100 Subject: [PATCH 20/31] - fix compilation issue (in kotlin getters are not necessary, making fields public already generates those --- .../bisq/mobile/domain/data/model/BisqStats.kt | 12 ++---------- .../ui/uicases/GettingStartedPresenter.kt | 4 ++-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt index 27360edd..6ee31b86 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt @@ -2,17 +2,9 @@ package network.bisq.mobile.domain.data.model open class BisqStats: BaseModel() { - protected open val offersOnline = 150 + open val offersOnline = 150 - protected open val publishedProfiles = 1275 - - fun getOffersOnline(): Int { - return offersOnline - } - - fun getPublishedProfiles(): Int { - return publishedProfiles - } + open val publishedProfiles = 1275 } interface BisqStatsFactory { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt index 0e18022d..7e012beb 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt @@ -26,8 +26,8 @@ class GettingStartedPresenter(private val priceRepository: BtcPriceRepository Date: Sat, 16 Nov 2024 08:42:13 +1100 Subject: [PATCH 21/31] - fix runtime crashes by specifying which nav controller to get (to be reviewed by buddha) --- .../mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt | 3 ++- .../mobile/presentation/ui/uicases/settings/SettingsScreen.kt | 3 ++- .../presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt | 1 - .../bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt index 314dd7df..89b298fb 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt @@ -31,11 +31,12 @@ import network.bisq.mobile.presentation.ui.components.molecules.TopBar import network.bisq.mobile.presentation.ui.components.atoms.icons.SortIcon import org.jetbrains.compose.resources.ExperimentalResourceApi import org.koin.compose.koinInject +import org.koin.core.qualifier.named @OptIn(ExperimentalResourceApi::class) @Composable fun ExchangeScreen() { - val navController: NavHostController = koinInject() + val navController: NavHostController = koinInject(named("RootNavController")) val originDirection = LocalLayoutDirection.current Column( modifier = Modifier.fillMaxSize() diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt index c8d789b8..5c7a6347 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/SettingsScreen.kt @@ -14,12 +14,13 @@ import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi import org.koin.compose.koinInject +import org.koin.core.qualifier.named @OptIn(ExperimentalResourceApi::class) @Composable fun SettingsScreen( ) { - val navController: NavHostController = koinInject() + val navController: NavHostController = koinInject(named("RootNavController")) Box( modifier = Modifier .fillMaxSize(), diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt index bf062309..4ab71175 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt @@ -18,7 +18,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import androidx.navigation.NavController import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.icon_question_mark diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt index 0c441d48..c2039696 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/MyTrades.kt @@ -14,11 +14,12 @@ import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import org.jetbrains.compose.resources.ExperimentalResourceApi import org.koin.compose.koinInject +import org.koin.core.qualifier.named @OptIn(ExperimentalResourceApi::class) @Composable fun MyTradesScreen() { - val rootNavController: NavHostController = koinInject() + val rootNavController: NavHostController = koinInject(named("RootNavController")) Box( modifier = Modifier .fillMaxSize(), From d6bd1b1c5377e58d3d4342f1636915ae06385054 Mon Sep 17 00:00:00 2001 From: Rodrigo Varela Date: Sat, 16 Nov 2024 08:58:01 +1100 Subject: [PATCH 22/31] - fix compose example test compilation errors --- .../kotlin/network/bisq/mobile/presentation/ExampleTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bisqapps/shared/presentation/src/commonTest/kotlin/network/bisq/mobile/presentation/ExampleTest.kt b/bisqapps/shared/presentation/src/commonTest/kotlin/network/bisq/mobile/presentation/ExampleTest.kt index 1a2d164c..9ede4af5 100644 --- a/bisqapps/shared/presentation/src/commonTest/kotlin/network/bisq/mobile/presentation/ExampleTest.kt +++ b/bisqapps/shared/presentation/src/commonTest/kotlin/network/bisq/mobile/presentation/ExampleTest.kt @@ -1,4 +1,5 @@ -import androidx.compose.material.* +import androidx.compose.material3.Button +import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag From 038eb4e0b1f4c055cc940b359ca0052d39d905c6 Mon Sep 17 00:00:00 2001 From: Rodrigo Varela Date: Sat, 16 Nov 2024 09:52:10 +1100 Subject: [PATCH 23/31] - upgrading gradle wrapper to 8.11 to get the gradle config cache fixes and improvements. This fixes the build issue on this branch --- bisqapps/gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bisqapps/gradle/wrapper/gradle-wrapper.properties b/bisqapps/gradle/wrapper/gradle-wrapper.properties index df97d72b..94113f20 100644 --- a/bisqapps/gradle/wrapper/gradle-wrapper.properties +++ b/bisqapps/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 8fd4b09248f64c374b1e5583eec415676e807edd Mon Sep 17 00:00:00 2001 From: Rodrigo Varela Date: Sat, 16 Nov 2024 10:19:11 +1100 Subject: [PATCH 24/31] - referencing new sub readme doc from main readme (navigation docs) --- bisqapps/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bisqapps/README.md b/bisqapps/README.md index d0771830..c5d01716 100644 --- a/bisqapps/README.md +++ b/bisqapps/README.md @@ -47,7 +47,10 @@ Addicionally, for the `androidNode` module to build you need to have its depende Done! Alternatively if you are interested only in contributing for the `xClients` you can just build them individually instead of building the whole project. -### UI Designs +### UI + +**Designs** + androidNode + xClient screens are designed in Figma. Yet to differentiate between which screens goes into which. @@ -55,6 +58,10 @@ Figma link: https://www.figma.com/design/IPnuicxGKIZXq28gybxOgp/Xchange?node-id= Though the figma design captures most of the functionality, it's an evolving document. It will be updated with new screens, flow updates, based on discussions happening in GH issues / matrix. +**Navigation Implementation** + +Please refer to [this README](shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/README.md) + ### Configuring dev env: known issues - Some Apple M chips have trouble with cocoapods, follow [this guide](https://stackoverflow.com/questions/64901180/how-to-run-cocoapods-on-apple-silicon-m1/66556339#66556339) to fix it From 3119ff9fad1c1842fe0a3d3d237ebc784bea8048 Mon Sep 17 00:00:00 2001 From: Rodrigo Varela Date: Sat, 16 Nov 2024 10:22:11 +1100 Subject: [PATCH 25/31] - reverting cocoapods downgrade --- bisqapps/iosClient/Podfile.lock | 2 +- bisqapps/iosClient/Pods/Manifest.lock | 2 +- .../Pods/Pods.xcodeproj/project.pbxproj | 202 +++++++++--------- .../Pods-iosClient.debug.xcconfig | 1 + .../Pods-iosClient.release.xcconfig | 1 + 5 files changed, 110 insertions(+), 98 deletions(-) diff --git a/bisqapps/iosClient/Podfile.lock b/bisqapps/iosClient/Podfile.lock index 1a06817f..295e6bb7 100644 --- a/bisqapps/iosClient/Podfile.lock +++ b/bisqapps/iosClient/Podfile.lock @@ -18,4 +18,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e4e5bb187d8247572973af90a35b57b84c96b4c6 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/bisqapps/iosClient/Pods/Manifest.lock b/bisqapps/iosClient/Pods/Manifest.lock index 1a06817f..295e6bb7 100644 --- a/bisqapps/iosClient/Pods/Manifest.lock +++ b/bisqapps/iosClient/Pods/Manifest.lock @@ -18,4 +18,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e4e5bb187d8247572973af90a35b57b84c96b4c6 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj b/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj index f0fd5c11..69267914 100644 --- a/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj +++ b/bisqapps/iosClient/Pods/Pods.xcodeproj/project.pbxproj @@ -32,25 +32,25 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 6D8AEE933A29DC7B08810C345CFA5E24 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - CAC030B21B2C869E7ACF12303AAC81C8 /* Pods-iosClient-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E481B77DFE58C61A03CF060B546D43 /* Pods-iosClient-dummy.m */; }; - F69108046F55BD4137DDB333E58FB806 /* Pods-iosClient-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BE8A23FBC0272A84B2B6DF475B94078C /* Pods-iosClient-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 348FFC44A5E9B7B78B5AFA2AFED5280D /* Pods-iosClient-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BE8A23FBC0272A84B2B6DF475B94078C /* Pods-iosClient-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 47FAAB4F7EFABDB8C6D42B0132784DF1 /* Pods-iosClient-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E481B77DFE58C61A03CF060B546D43 /* Pods-iosClient-dummy.m */; }; + 9F54DC905AC77CABA77E9F04008E9B6F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 384DDA2CB25005BD6479B5987C619DD4 /* Foundation.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 6270F50CCD4DE87ED97016FF300F6833 /* PBXContainerItemProxy */ = { + 43926A465BA48F490AAD4266561191E9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = CA23A621E427291AD7AAC241FE14977E; - remoteInfo = presentation; + remoteGlobalIDString = 9FA10608F377AE5B47F00969C58A08B0; + remoteInfo = domain; }; - ECE0965C37EE068DC96145D99562455D /* PBXContainerItemProxy */ = { + D94579C113BF9D6877F572CEBE34C518 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 9FA10608F377AE5B47F00969C58A08B0; - remoteInfo = domain; + remoteGlobalIDString = CA23A621E427291AD7AAC241FE14977E; + remoteInfo = presentation; }; /* End PBXContainerItemProxy section */ @@ -59,10 +59,10 @@ 08F36E9886CC49F84B0FAF507C3E9B5B /* Pods-iosClient-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-iosClient-acknowledgements.plist"; sourceTree = ""; }; 12A9F0027D088186CD39E0238C94B9C8 /* Pods-iosClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-iosClient.release.xcconfig"; sourceTree = ""; }; 204E5861AA89F6485AE0E7BE7CC61EB9 /* presentation.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = presentation.release.xcconfig; sourceTree = ""; }; + 384DDA2CB25005BD6479B5987C619DD4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 49F48C70711D582068D8EF03B5D062B2 /* Pods-iosClient */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-iosClient"; path = Pods_iosClient.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4AAF1B0BB5C923912BF8947076BB504A /* presentation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = presentation.framework; path = build/cocoapods/framework/presentation.framework; sourceTree = ""; }; 703090F2823E5D42D1ED04CAF0E55193 /* Pods-iosClient.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-iosClient.modulemap"; sourceTree = ""; }; - 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 74ED85F89A4112470D68D97319C810B5 /* domain.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = domain.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 804065BB4F007C057F539031BA89C4D2 /* domain.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = domain.debug.xcconfig; sourceTree = ""; }; 8EA548F0CBB66C825F5F196469AE443C /* presentation.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = presentation.debug.xcconfig; sourceTree = ""; }; @@ -82,11 +82,11 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - C42E73C43E7636D285E3EFB564AED2A2 /* Frameworks */ = { + EBBD9B769AA45797F4E13290D3F4D389 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6D8AEE933A29DC7B08810C345CFA5E24 /* Foundation.framework in Frameworks */, + 9F54DC905AC77CABA77E9F04008E9B6F /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -141,14 +141,6 @@ path = ../../shared/domain; sourceTree = ""; }; - 578452D2E740E91742655AC8F1636D1F /* iOS */ = { - isa = PBXGroup; - children = ( - 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */, - ); - name = iOS; - sourceTree = ""; - }; 6B7DEDEE95A0508984457A702CE60837 /* Targets Support Files */ = { isa = PBXGroup; children = ( @@ -227,11 +219,19 @@ D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { isa = PBXGroup; children = ( - 578452D2E740E91742655AC8F1636D1F /* iOS */, + E4801F62A6B08CD9B5410329F1A18FDE /* iOS */, ); name = Frameworks; sourceTree = ""; }; + E4801F62A6B08CD9B5410329F1A18FDE /* iOS */ = { + isa = PBXGroup; + children = ( + 384DDA2CB25005BD6479B5987C619DD4 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; E9FF437E9B7237DA2D4C60336C9890D7 /* Pod */ = { isa = PBXGroup; children = ( @@ -243,11 +243,11 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - BA415ECC9F54D30119E5CC9DD75101AE /* Headers */ = { + 90BC81E26DDEAC698173DBBDF44F548F /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - F69108046F55BD4137DDB333E58FB806 /* Pods-iosClient-umbrella.h in Headers */, + 348FFC44A5E9B7B78B5AFA2AFED5280D /* Pods-iosClient-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -256,18 +256,18 @@ /* Begin PBXNativeTarget section */ F3C92A200A7569173DED928345F8DF17 /* Pods-iosClient */ = { isa = PBXNativeTarget; - buildConfigurationList = 353001358113C9F843A3BBE263DA5845 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */; + buildConfigurationList = BD19120D9E7ED18653B7259546989F15 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */; buildPhases = ( - BA415ECC9F54D30119E5CC9DD75101AE /* Headers */, - 50D8119830E647007B7C6B621F14082F /* Sources */, - C42E73C43E7636D285E3EFB564AED2A2 /* Frameworks */, - 962FF8154C877D9E2348823600E7D577 /* Resources */, + 90BC81E26DDEAC698173DBBDF44F548F /* Headers */, + A6370334C83C2D6AF3EA6C4C370A5C80 /* Sources */, + EBBD9B769AA45797F4E13290D3F4D389 /* Frameworks */, + 9F2EFCAA86FE94012544D8E099DFA032 /* Resources */, ); buildRules = ( ); dependencies = ( - 301E0E32512A3E0913F6AEC1A7C27833 /* PBXTargetDependency */, - BC1D990945D84666EE9129354C69E0FA /* PBXTargetDependency */, + 7EA97463B99B732B6B24774A9B942A85 /* PBXTargetDependency */, + 631D2882C1581DA7DF2E1CC18B1B3809 /* PBXTargetDependency */, ); name = "Pods-iosClient"; productName = Pods_iosClient; @@ -280,8 +280,8 @@ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1500; + LastSwiftUpdateCheck = 1600; + LastUpgradeCheck = 1600; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 14.0"; @@ -292,6 +292,8 @@ en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; + minimizedProjectReferenceProxies = 0; + preferredProjectObjectVersion = 77; productRefGroup = A926F4DF68FD1A33909AAB7F17266C96 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -304,7 +306,7 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 962FF8154C877D9E2348823600E7D577 /* Resources */ = { + 9F2EFCAA86FE94012544D8E099DFA032 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -371,47 +373,69 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 50D8119830E647007B7C6B621F14082F /* Sources */ = { + A6370334C83C2D6AF3EA6C4C370A5C80 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CAC030B21B2C869E7ACF12303AAC81C8 /* Pods-iosClient-dummy.m in Sources */, + 47FAAB4F7EFABDB8C6D42B0132784DF1 /* Pods-iosClient-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 301E0E32512A3E0913F6AEC1A7C27833 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = domain; - target = 9FA10608F377AE5B47F00969C58A08B0 /* domain */; - targetProxy = ECE0965C37EE068DC96145D99562455D /* PBXContainerItemProxy */; - }; - BC1D990945D84666EE9129354C69E0FA /* PBXTargetDependency */ = { + 631D2882C1581DA7DF2E1CC18B1B3809 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = presentation; target = CA23A621E427291AD7AAC241FE14977E /* presentation */; - targetProxy = 6270F50CCD4DE87ED97016FF300F6833 /* PBXContainerItemProxy */; + targetProxy = D94579C113BF9D6877F572CEBE34C518 /* PBXContainerItemProxy */; + }; + 7EA97463B99B732B6B24774A9B942A85 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = domain; + target = 9FA10608F377AE5B47F00969C58A08B0 /* domain */; + targetProxy = 43926A465BA48F490AAD4266561191E9 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 2E45E8C4BD4AFB54267F590D5DE5DC7E /* Release */ = { + 018F2F2185808E1CFC64820D5D133A46 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DA1AD272BC5CBE1D4ED4240B2689D453 /* domain.release.xcconfig */; + baseConfigurationReference = 12A9F0027D088186CD39E0238C94B9C8 /* Pods-iosClient.release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + INFOPLIST_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + "@loader_path/Frameworks", ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; @@ -477,13 +501,14 @@ }; name = Release; }; - 5073BD3B8BAE827A42C6C0745CF30855 /* Release */ = { + 437EA4C44DE0B4C7DCDF7777DED031FA /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 204E5861AA89F6485AE0E7BE7CC61EB9 /* presentation.release.xcconfig */; + baseConfigurationReference = 8EA548F0CBB66C825F5F196469AE443C /* presentation.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -491,17 +516,17 @@ ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = Release; + name = Debug; }; - 77458C92CF4EA7DEDC04735E8E580C2A /* Debug */ = { + 48F2FDB6889B575B7DB16DE30260C86D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 804065BB4F007C057F539031BA89C4D2 /* domain.debug.xcconfig */; + baseConfigurationReference = 204E5861AA89F6485AE0E7BE7CC61EB9 /* presentation.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -509,10 +534,11 @@ ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; - name = Debug; + name = Release; }; - 86AF170A2B3395569AB4C66092089CF0 /* Debug */ = { + CB606ED3E79A498A37998C1B0EED7638 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A733908725930A882438524B1F97DAE3 /* Pods-iosClient.debug.xcconfig */; buildSettings = { @@ -526,6 +552,8 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; INFOPLIST_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; @@ -549,13 +577,14 @@ }; name = Debug; }; - 9084D9814A27814E5AA332C6B109236D /* Debug */ = { + D347EF77A9147218FFD617F7E00D9870 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8EA548F0CBB66C825F5F196469AE443C /* presentation.debug.xcconfig */; + baseConfigurationReference = DA1AD272BC5CBE1D4ED4240B2689D453 /* domain.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -563,8 +592,9 @@ ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; - name = Debug; + name = Release; }; F4FF6A0D1970CA9705974E3CB2134802 /* Debug */ = { isa = XCBuildConfiguration; @@ -632,79 +662,59 @@ }; name = Debug; }; - FB7B18B0BBBBE282315F2CBBBE2B90B5 /* Release */ = { + F6743C549671A6AE48C5AF30AA7C423A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 12A9F0027D088186CD39E0238C94B9C8 /* Pods-iosClient.release.xcconfig */; + baseConfigurationReference = 804065BB4F007C057F539031BA89C4D2 /* domain.debug.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + ENABLE_USER_SCRIPT_SANDBOXING = NO; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", - "@loader_path/Frameworks", ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-iosClient/Pods-iosClient.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; - SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 353001358113C9F843A3BBE263DA5845 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 86AF170A2B3395569AB4C66092089CF0 /* Debug */, - FB7B18B0BBBBE282315F2CBBBE2B90B5 /* Release */, + F4FF6A0D1970CA9705974E3CB2134802 /* Debug */, + 30E0B9EFD9A5C45D0D351231E81B30B3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + 84A7558F1F961C4A23CF638108708641 /* Build configuration list for PBXAggregateTarget "presentation" */ = { isa = XCConfigurationList; buildConfigurations = ( - F4FF6A0D1970CA9705974E3CB2134802 /* Debug */, - 30E0B9EFD9A5C45D0D351231E81B30B3 /* Release */, + 437EA4C44DE0B4C7DCDF7777DED031FA /* Debug */, + 48F2FDB6889B575B7DB16DE30260C86D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 84A7558F1F961C4A23CF638108708641 /* Build configuration list for PBXAggregateTarget "presentation" */ = { + B978635EC7F36DF902EF0C770E5CBB10 /* Build configuration list for PBXAggregateTarget "domain" */ = { isa = XCConfigurationList; buildConfigurations = ( - 9084D9814A27814E5AA332C6B109236D /* Debug */, - 5073BD3B8BAE827A42C6C0745CF30855 /* Release */, + F6743C549671A6AE48C5AF30AA7C423A /* Debug */, + D347EF77A9147218FFD617F7E00D9870 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - B978635EC7F36DF902EF0C770E5CBB10 /* Build configuration list for PBXAggregateTarget "domain" */ = { + BD19120D9E7ED18653B7259546989F15 /* Build configuration list for PBXNativeTarget "Pods-iosClient" */ = { isa = XCConfigurationList; buildConfigurations = ( - 77458C92CF4EA7DEDC04735E8E580C2A /* Debug */, - 2E45E8C4BD4AFB54267F590D5DE5DC7E /* Release */, + CB606ED3E79A498A37998C1B0EED7638 /* Debug */, + 018F2F2185808E1CFC64820D5D133A46 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig index b5042e50..f7d607d8 100644 --- a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig +++ b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.debug.xcconfig @@ -4,6 +4,7 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/domain/build/co GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -l"c++" -framework "domain" -framework "presentation" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/domain" "-F${PODS_CONFIGURATION_BUILD_DIR}/presentation" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig index b5042e50..f7d607d8 100644 --- a/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig +++ b/bisqapps/iosClient/Pods/Target Support Files/Pods-iosClient/Pods-iosClient.release.xcconfig @@ -4,6 +4,7 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/domain/build/co GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -l"c++" -framework "domain" -framework "presentation" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/domain" "-F${PODS_CONFIGURATION_BUILD_DIR}/presentation" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. From 13eca0dfd9168d41712370448178443c94aca0f4 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 16 Nov 2024 20:14:54 +0530 Subject: [PATCH 26/31] NetworkRepository improvement - Partial --- .../bisq/mobile/domain/data/model/NetworkModel.kt | 15 +++++++++++++++ .../domain/data/repository/NetworkRepository.kt | 9 ++++++--- .../mobile/domain/data/repository/Repositories.kt | 2 +- .../network/bisq/mobile/domain/di/DomainModule.kt | 3 +++ .../mobile/presentation/di/PresentationModule.kt | 10 +++++++--- .../ui/uicases/startup/SplashPresenter.kt | 11 +++++++++-- 6 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt new file mode 100644 index 00000000..ef4b3e25 --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt @@ -0,0 +1,15 @@ +package network.bisq.mobile.domain.data.model + +import kotlinx.coroutines.delay + +open class NetworkModel: BaseModel() { + var progress: Float = 0.0f +} + +interface NetworkModelFactory { + fun createNetworkModel(): NetworkModel +} + +class DefaultNetworkModelFactory : NetworkModelFactory { + override fun createNetworkModel() = NetworkModel() +} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt index 3143879f..569f50e0 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt @@ -1,9 +1,12 @@ package network.bisq.mobile.domain.data.repository import kotlinx.coroutines.delay - - object NetworkRepository { + import network.bisq.mobile.domain.data.model.NetworkModel + + open class NetworkRepository : SingleObjectRepository() { + suspend fun initializeNetwork(updateProgress: (Float) -> Unit) { + //1. Initialize Tor here //2. Connect to peers (for androidNode), to Bisq instance (for xClients) //3. Do any other app initialization @@ -12,4 +15,4 @@ delay(25) } } - } + } \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt index c65404e0..4539a835 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt @@ -3,10 +3,10 @@ package network.bisq.mobile.domain.data.repository import network.bisq.mobile.domain.data.model.BtcPrice import network.bisq.mobile.domain.data.model.BisqStats import network.bisq.mobile.domain.data.model.Greeting +import network.bisq.mobile.domain.data.model.NetworkModel // this way of definingsupports both platforms // add your repositories here and then in your DI module call this classes for instanciation open class GreetingRepository: SingleObjectRepository() open class BisqStatsRepository: SingleObjectRepository() open class BtcPriceRepository: SingleObjectRepository() - diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt index 2de0eaeb..ec85bb4d 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt @@ -3,13 +3,16 @@ package network.bisq.mobile.domain.di import network.bisq.mobile.domain.data.model.BtcPrice import network.bisq.mobile.domain.data.model.BisqStats import network.bisq.mobile.domain.data.model.Greeting +import network.bisq.mobile.domain.data.model.NetworkModel import network.bisq.mobile.domain.data.repository.BisqStatsRepository import network.bisq.mobile.domain.data.repository.BtcPriceRepository import network.bisq.mobile.domain.data.repository.GreetingRepository +import network.bisq.mobile.domain.data.repository.NetworkRepository import org.koin.dsl.module val domainModule = module { single> { GreetingRepository() } single> { BisqStatsRepository() } single> { BtcPriceRepository() } + single> { NetworkRepository() } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt index 31ac1095..8795f571 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt @@ -16,8 +16,7 @@ import org.koin.dsl.bind import org.koin.dsl.module val presentationModule = module { - - single { error("NavController has not been initialized yet") } + single(named("RootNavController")) { getKoin().getProperty("RootNavController") } single(named("TabNavController")) { getKoin().getProperty("TabNavController") } @@ -25,7 +24,12 @@ val presentationModule = module { // TODO: Since NavController will be required for almost all Presenters for basic navigation // Added this as top constructor level param. Is this okay? - single { (navController: NavController) -> SplashPresenter(navController) } bind ISplashPresenter::class + single { + (navController: NavController) -> SplashPresenter( + navController = navController, + networkRepository = get() + ) + } bind ISplashPresenter::class single { (navController: NavController) -> OnBoardingPresenter(navController) } bind IOnboardingPresenter::class diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt index 90e1b02a..b7fdc9a4 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt @@ -5,21 +5,27 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import network.bisq.mobile.domain.data.repository.NetworkRepository +import network.bisq.mobile.domain.data.model.NetworkModel import network.bisq.mobile.presentation.BasePresenter import network.bisq.mobile.presentation.ui.navigation.Routes +import kotlinx.coroutines.delay -open class SplashPresenter(private val navController: NavController) : BasePresenter(), ISplashPresenter { +open class SplashPresenter( + private val navController: NavController, + private val networkRepository: NetworkRepository +) : BasePresenter(), ISplashPresenter { private val coroutineScope = CoroutineScope(Dispatchers.Main) override fun startLoading(onProgressUpdate: (Float) -> Unit) { coroutineScope.launch { - NetworkRepository.initializeNetwork { progress -> + networkRepository?.initializeNetwork{ progress -> onProgressUpdate(progress) } navigateToNextScreen() } } + private fun navigateToNextScreen() { // TODO: Conditional nav // If firstTimeApp launch, goto Onboarding[clientMode] (androidNode / xClient) @@ -28,4 +34,5 @@ open class SplashPresenter(private val navController: NavController) : BasePrese popUpTo(Routes.Splash.name) { inclusive = true } } } + } From 7f5f89ec9ff985c174a0a2e80c15ab2239f4fc4b Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 16 Nov 2024 21:07:30 +0530 Subject: [PATCH 27/31] [added] CreateProfilePresenter --- .../mobile/domain/data/model/UserProfile.kt | 14 ++++ .../domain/data/repository/Repositories.kt | 6 +- .../bisq/mobile/domain/di/DomainModule.kt | 11 +-- .../presentation/di/PresentationModule.kt | 9 +++ .../bisq/mobile/presentation/i18n/Locales.kt | 43 ----------- .../ui/components/MaterialTextField.kt | 4 +- .../ui/uicases/GettingStartedPresenter.kt | 5 +- .../uicases/startup/CreateProfilePresenter.kt | 71 +++++++++++++++++++ .../ui/uicases/startup/CreateProfileScreen.kt | 48 +++++++------ .../ui/uicases/startup/OnBoardingPresenter.kt | 5 +- .../ui/uicases/startup/OnBoardingScreen.kt | 6 +- .../ui/uicases/startup/SplashPresenter.kt | 1 - .../ui/uicases/startup/SplashScreen.kt | 12 ++-- 13 files changed, 143 insertions(+), 92 deletions(-) create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt delete mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt new file mode 100644 index 00000000..f7fe6262 --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt @@ -0,0 +1,14 @@ +package network.bisq.mobile.domain.data.model + +// TODO: Is it okay for the models to be mutable? +open class UserProfile: BaseModel() { + open var name = "" +} + +interface UserProfileFactory { + fun createUserProfile(): UserProfile +} + +class DefaultUserProfileFactory : UserProfileFactory { + override fun createUserProfile() = UserProfile() +} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt index 4539a835..67f2dd3f 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt @@ -1,12 +1,10 @@ package network.bisq.mobile.domain.data.repository -import network.bisq.mobile.domain.data.model.BtcPrice -import network.bisq.mobile.domain.data.model.BisqStats -import network.bisq.mobile.domain.data.model.Greeting -import network.bisq.mobile.domain.data.model.NetworkModel +import network.bisq.mobile.domain.data.model.* // this way of definingsupports both platforms // add your repositories here and then in your DI module call this classes for instanciation open class GreetingRepository: SingleObjectRepository() open class BisqStatsRepository: SingleObjectRepository() open class BtcPriceRepository: SingleObjectRepository() +open class UserProfileRepository: SingleObjectRepository() diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt index ec85bb4d..418522b9 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt @@ -1,13 +1,7 @@ package network.bisq.mobile.domain.di -import network.bisq.mobile.domain.data.model.BtcPrice -import network.bisq.mobile.domain.data.model.BisqStats -import network.bisq.mobile.domain.data.model.Greeting -import network.bisq.mobile.domain.data.model.NetworkModel -import network.bisq.mobile.domain.data.repository.BisqStatsRepository -import network.bisq.mobile.domain.data.repository.BtcPriceRepository -import network.bisq.mobile.domain.data.repository.GreetingRepository -import network.bisq.mobile.domain.data.repository.NetworkRepository +import network.bisq.mobile.domain.data.model.* +import network.bisq.mobile.domain.data.repository.* import org.koin.dsl.module val domainModule = module { @@ -15,4 +9,5 @@ val domainModule = module { single> { BisqStatsRepository() } single> { BtcPriceRepository() } single> { NetworkRepository() } + single> { UserProfileRepository() } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt index 8795f571..1565702a 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt @@ -5,8 +5,10 @@ import androidx.navigation.NavController import androidx.navigation.NavHostController import network.bisq.mobile.presentation.MainPresenter import network.bisq.mobile.presentation.ui.AppPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.ICreateProfilePresenter import network.bisq.mobile.presentation.ui.uicases.startup.IOnboardingPresenter import network.bisq.mobile.presentation.ui.uicases.startup.ISplashPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.CreateProfilePresenter import network.bisq.mobile.presentation.ui.uicases.startup.OnBoardingPresenter import network.bisq.mobile.presentation.ui.uicases.startup.SplashPresenter import network.bisq.mobile.presentation.ui.uicases.GettingStartedPresenter @@ -39,4 +41,11 @@ val presentationModule = module { bisqStatsRepository = get() ) } bind IGettingStarted::class + + single { + (navController: NavController) -> CreateProfilePresenter( + navController = navController, + userProfileRepository = get() + ) + } bind ICreateProfilePresenter::class } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt deleted file mode 100644 index 002203eb..00000000 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/i18n/Locales.kt +++ /dev/null @@ -1,43 +0,0 @@ -package network.bisq.mobile.presentation.i18n - -/** - * An object that holds locale codes used for the application’s supported languages. - * - * Currently, this object supports English (`EN`) as the default language and French ('FR') only for testing. - * Additional languages can be added in the future. - * - * ## Usage - * ### Locales.kt - * Defines all the supported languages - * - * ### Strigs.kt - * A class that defines variable for all text resources used in the app. - * TODO: This is going to be an insanely huge file. Look for ways to modularize it (for later) - * - * ### {Lang}Strings.kt - * One file for each language. Assigns actual text for each variable in that specific language. - * - * ### Actual usage: - * 1. Each view should be enclosed by `ProviderStrings`. This is now done at top level in App.kt - * - * val lyricist = rememberStrings() - * ProvideStrings(lyricist) {} - * - * 2. And current language can be changed anytime by doing - * - * lyricist.languageTag = Locales.FR - * - * 3. In the views, string resources can be accessed by - * - * LocalStrings.current.{stringResourceName} - * - * - * ## References: - * For more detailed usage, please refer lyricist documentation @ - * https://github.com/adrielcafe/lyricist/ - * https://github.com/adrielcafe/lyricist/tree/main/sample-multiplatform/src/commonMain/kotlin/cafe/adriel/lyricist/sample/multiplatform (sample project) - */ -object Locales { - const val EN = "en" - const val FR = "fr" -} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt index c14406c0..d6441498 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/MaterialTextField.kt @@ -27,7 +27,7 @@ import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.* @Composable -fun MaterialTextField(text: String,onValueChanged: (String) -> Unit) { +fun MaterialTextField(text: String, placeholder: String = "", onValueChanged: (String) -> Unit) { var isFocused by remember { mutableStateOf(false) } Box( @@ -57,7 +57,7 @@ fun MaterialTextField(text: String,onValueChanged: (String) -> Unit) { ), placeholder = { BisqText.h5Regular( - text = "Choose your nickname", + text = placeholder, color = BisqTheme.colors.secondaryHover, ) } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt index 7e012beb..ad1bc4aa 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt @@ -12,7 +12,10 @@ import network.bisq.mobile.domain.data.repository.BisqStatsRepository import network.bisq.mobile.domain.data.repository.BtcPriceRepository import network.bisq.mobile.presentation.BasePresenter -class GettingStartedPresenter(private val priceRepository: BtcPriceRepository, private val bisqStatsRepository: BisqStatsRepository) : BasePresenter(), IGettingStarted { +class GettingStartedPresenter( + private val priceRepository: BtcPriceRepository, + private val bisqStatsRepository: BisqStatsRepository +) : BasePresenter(), IGettingStarted { private val _btcPrice = MutableStateFlow("Loading...")//("$75,000") override val btcPrice: StateFlow = _btcPrice diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt new file mode 100644 index 00000000..da37e6a6 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt @@ -0,0 +1,71 @@ +package network.bisq.mobile.presentation.ui.uicases.startup + +import androidx.navigation.NavController +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.collectLatest +import network.bisq.mobile.domain.data.repository.UserProfileRepository +import network.bisq.mobile.domain.data.model.UserProfile +import network.bisq.mobile.presentation.BasePresenter +import network.bisq.mobile.presentation.ui.navigation.Routes +import kotlinx.coroutines.delay + +open class CreateProfilePresenter( + private val navController: NavController, + private val userProfileRepository: UserProfileRepository +) : BasePresenter(), ICreateProfilePresenter { + + private val _profileName = MutableStateFlow("") + override val profileName: StateFlow = _profileName + + init { + CoroutineScope(Dispatchers.IO).launch { + userProfileRepository.data.collectLatest { userProfile -> + userProfile?.let { + _profileName.value = it.name + } + } + } + } + + override fun onProfileNameChanged(newName: String) { + _profileName.value = newName + } + + override fun navigateToNextScreen() { + if (_profileName.value.isNotEmpty()) { + saveUserProfile() + navController.navigate(Routes.TrustedNodeSetup.name) { + popUpTo(Routes.CreateProfile.name) { inclusive = true } + } + } + } + + fun saveUserProfile() { + CoroutineScope(Dispatchers.IO).launch { + val updatedProfile = UserProfile().apply { + name = _profileName.value + } + userProfileRepository.update(updatedProfile) + } + } + + /* + fun onNicknameChanged(newNickname: String) { + _nickname.value = newNickname + } + + fun navigateToNextScreen() { + if (_nickname.value.isNotEmpty()) { + navController.navigate(Routes.TrustedNodeSetup.name) { + popUpTo(Routes.CreateProfile.name) { inclusive = true } + } + } + } + */ + +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt index 31854d28..c862556e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -24,25 +25,37 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource import org.koin.compose.koinInject import org.koin.core.qualifier.named +import kotlinx.coroutines.flow.StateFlow +import cafe.adriel.lyricist.LocalStrings +import org.koin.core.parameter.parametersOf -private lateinit var textState: MutableState +interface ICreateProfilePresenter { + val profileName: StateFlow + + fun onProfileNameChanged(newName: String) + fun navigateToNextScreen() +} @OptIn(ExperimentalResourceApi::class) @Composable fun CreateProfileScreen( ) { + val strings = LocalStrings.current val navController: NavHostController = koinInject(named("RootNavController")) - textState = remember { mutableStateOf("") } + val presenter: ICreateProfilePresenter = koinInject { parametersOf(navController) } + + val profileName = presenter.profileName.collectAsState().value + BisqScrollLayout() { BisqLogo() Spacer(modifier = Modifier.height(24.dp)) BisqText.h1Light( - text = "Create your profile", + text = strings.onboarding_createProfile_headline, color = BisqTheme.colors.grey1, ) Spacer(modifier = Modifier.height(12.dp)) BisqText.baseRegular( - text = "Your public profile consists of a nickname (picked by you) and bot icon (generated cryptographically)", + text = strings.onboarding_createProfile_subTitle, color = BisqTheme.colors.grey3, modifier = Modifier.padding(horizontal = 24.dp), textAlign = TextAlign.Center, @@ -51,13 +64,16 @@ fun CreateProfileScreen( Column(modifier = Modifier.padding(horizontal = 24.dp)) { //TODO: Convert this into a Form field component, which is Label + TextField BisqText.baseRegular( - text = "Profile nickname", + text = strings.onboarding_createProfile_nickName, color = BisqTheme.colors.light2, ) - MaterialTextField(textState.value, onValueChanged = { textState.value = it }) + MaterialTextField( + text = profileName, + placeholder = strings.onboarding_createProfile_nickName_prompt, + onValueChanged = { presenter.onProfileNameChanged(it) }) } Spacer(modifier = Modifier.height(36.dp)) - Image(painterResource(Res.drawable.img_bot_image), "Crypto generated image (PoW)") + Image(painterResource(Res.drawable.img_bot_image), "Crypto generated image (PoW)") // TODO: Translation Spacer(modifier = Modifier.height(32.dp)) BisqText.baseRegular( text = "Sleepily-Distracted-Zyophyte-257", @@ -65,29 +81,21 @@ fun CreateProfileScreen( ) Spacer(modifier = Modifier.height(12.dp)) BisqText.baseRegular( - text = "BOT ID", + text = strings.onboarding_createProfile_nym, color = BisqTheme.colors.grey2, ) Spacer(modifier = Modifier.height(38.dp)) BisqButton( - text ="Generate new bot iconnn", + text = strings.onboarding_createProfile_regenerate, backgroundColor = BisqTheme.colors.dark5, padding = PaddingValues(horizontal = 64.dp, vertical = 12.dp), onClick = {} ) Spacer(modifier = Modifier.height(40.dp)) BisqButton( - "Next", - onClick = { - if (textState.value.isNotEmpty()) { - navController.navigate(Routes.TrustedNodeSetup.name) { - popUpTo(Routes.CreateProfile.name) { - inclusive = true - } - } - } - }, - backgroundColor = if (textState.value.isEmpty()) BisqTheme.colors.primaryDisabled else BisqTheme.colors.primary + strings.buttons_next, + onClick = { presenter.navigateToNextScreen() }, + backgroundColor = if (profileName.isEmpty()) BisqTheme.colors.primaryDisabled else BisqTheme.colors.primary ) } } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt index 844a1df8..cdf138b7 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt @@ -1,6 +1,5 @@ package network.bisq.mobile.presentation.ui.uicases.startup - import androidx.compose.foundation.pager.PagerState import androidx.navigation.NavController import bisqapps.shared.presentation.generated.resources.Res @@ -34,7 +33,9 @@ val onBoardingPages = listOf( ) ) -open class OnBoardingPresenter(private val navController: NavController) : BasePresenter(), IOnboardingPresenter { +open class OnBoardingPresenter( + private val navController: NavController +) : BasePresenter(), IOnboardingPresenter { private val _pagerState = MutableStateFlow(null) override val pagerState: StateFlow = _pagerState diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt index d5104bba..2f339b12 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingScreen.kt @@ -44,9 +44,8 @@ import org.koin.core.parameter.parametersOf import org.koin.core.qualifier.named interface IOnboardingPresenter { - val pagerState: StateFlow - // Actions + fun onNextButtonClick(coroutineScope: CoroutineScope) } @@ -55,9 +54,10 @@ interface IOnboardingPresenter { fun OnBoardingScreen() { val strings = LocalStrings.current val navController: NavHostController = koinInject(named("RootNavController")) + val presenter: IOnboardingPresenter = koinInject { parametersOf(navController) } + val coroutineScope = rememberCoroutineScope() val pagerState = rememberPagerState(pageCount = { onBoardingPages.size }) - val presenter: IOnboardingPresenter = koinInject { parametersOf(navController) } // TODO: Any other better way to do this? LaunchedEffect(pagerState) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt index b7fdc9a4..cda4ba68 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt @@ -25,7 +25,6 @@ open class SplashPresenter( } } - private fun navigateToNextScreen() { // TODO: Conditional nav // If firstTimeApp launch, goto Onboarding[clientMode] (androidNode / xClient) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt index 929d4ed8..911fb62a 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashScreen.kt @@ -23,28 +23,24 @@ import org.koin.core.parameter.parametersOf import org.koin.core.qualifier.named interface ISplashPresenter { - // Actions fun startLoading(onProgressUpdate: (Float) -> Unit) } -// TODO: Remove innerPadding once StaticLayout, ScrollLayout are fully done. -// (or) innerPadding as a param is how it's done / best practice in Compose @Composable fun SplashScreen( ) { - // val rootNavController: NavHostController = koinInject() - val navController: NavHostController = koinInject(named("RootNavController")) val strings = LocalStrings.current - var currentProgress by remember { mutableFloatStateOf(0f) } + val navController: NavHostController = koinInject(named("RootNavController")) val presenter: ISplashPresenter = koinInject { parametersOf(navController) } + + var currentProgress by remember { mutableFloatStateOf(0f) } LaunchedEffect(Unit) { - presenter.startLoading { progress -> + presenter.startLoading { progress -> currentProgress = progress } } - // Render the layout BisqStaticLayout { BisqLogo() From 0ed838b39bb7298fbc22ca39e184c951df84c4a0 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 16 Nov 2024 22:56:27 +0530 Subject: [PATCH 28/31] [added] TrustedNodeSetupPresenter --- .../bisq/mobile/domain/data/model/Settings.kt | 14 ++++ .../domain/data/repository/Repositories.kt | 1 + .../bisq/mobile/domain/di/DomainModule.kt | 1 + .../presentation/di/PresentationModule.kt | 9 +++ .../uicases/startup/CreateProfilePresenter.kt | 1 + .../startup/TrustedNodeSetupPresenter.kt | 50 ++++++++++++++ .../uicases/startup/TrustedNodeSetupScreen.kt | 65 +++++++++++-------- 7 files changed, 114 insertions(+), 27 deletions(-) create mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Settings.kt create mode 100644 bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Settings.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Settings.kt new file mode 100644 index 00000000..7917724f --- /dev/null +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Settings.kt @@ -0,0 +1,14 @@ +package network.bisq.mobile.domain.data.model + +open class Settings : BaseModel() { + open var bisqUrl: String = "" + open var isConnected: Boolean = false +} + +interface SettingsFactory { + fun createSettings(): Settings +} + +class DefaultSettingsFactory : SettingsFactory { + override fun createSettings() = Settings() +} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt index 67f2dd3f..fe84133c 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt @@ -8,3 +8,4 @@ open class GreetingRepository: SingleObjectRepository() open class BisqStatsRepository: SingleObjectRepository() open class BtcPriceRepository: SingleObjectRepository() open class UserProfileRepository: SingleObjectRepository() +open class SettingsRepository: SingleObjectRepository() diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt index 418522b9..b872856f 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt @@ -10,4 +10,5 @@ val domainModule = module { single> { BtcPriceRepository() } single> { NetworkRepository() } single> { UserProfileRepository() } + single> { SettingsRepository() } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt index 1565702a..7a90492d 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/di/PresentationModule.kt @@ -8,9 +8,11 @@ import network.bisq.mobile.presentation.ui.AppPresenter import network.bisq.mobile.presentation.ui.uicases.startup.ICreateProfilePresenter import network.bisq.mobile.presentation.ui.uicases.startup.IOnboardingPresenter import network.bisq.mobile.presentation.ui.uicases.startup.ISplashPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.ITrustedNodeSetupPresenter import network.bisq.mobile.presentation.ui.uicases.startup.CreateProfilePresenter import network.bisq.mobile.presentation.ui.uicases.startup.OnBoardingPresenter import network.bisq.mobile.presentation.ui.uicases.startup.SplashPresenter +import network.bisq.mobile.presentation.ui.uicases.startup.TrustedNodeSetupPresenter import network.bisq.mobile.presentation.ui.uicases.GettingStartedPresenter import network.bisq.mobile.presentation.ui.uicases.IGettingStarted import org.koin.core.qualifier.named @@ -48,4 +50,11 @@ val presentationModule = module { userProfileRepository = get() ) } bind ICreateProfilePresenter::class + + single { + (navController: NavController) -> TrustedNodeSetupPresenter( + navController = navController, + settingsRepository = get() + ) + } bind ITrustedNodeSetupPresenter::class } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt index da37e6a6..2b1e4e54 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt @@ -22,6 +22,7 @@ open class CreateProfilePresenter( private val _profileName = MutableStateFlow("") override val profileName: StateFlow = _profileName + // TODO: Not working init { CoroutineScope(Dispatchers.IO).launch { userProfileRepository.data.collectLatest { userProfile -> diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt new file mode 100644 index 00000000..71268d77 --- /dev/null +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt @@ -0,0 +1,50 @@ +package network.bisq.mobile.presentation.ui.uicases.startup + +import androidx.navigation.NavController +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.collectLatest +import network.bisq.mobile.domain.data.model.Settings +import network.bisq.mobile.domain.data.repository.SettingsRepository +import network.bisq.mobile.presentation.BasePresenter +import network.bisq.mobile.presentation.ui.navigation.Routes +import kotlinx.coroutines.delay + +class TrustedNodeSetupPresenter( + private val navController: NavController, + private val settingsRepository: SettingsRepository +) : BasePresenter(), ITrustedNodeSetupPresenter { + + private val _bisqUrl = MutableStateFlow("") + override val bisqUrl: StateFlow = _bisqUrl + + private val _isConnected = MutableStateFlow(false) + override val isConnected: StateFlow = _isConnected + + override fun updateBisqUrl(newUrl: String) { + _bisqUrl.value = newUrl + } + + override fun testConnection(isTested: Boolean) { + _isConnected.value = isTested + + CoroutineScope(Dispatchers.IO).launch { + val updatedSettings = Settings().apply { + bisqUrl = _bisqUrl.value + isConnected = _isConnected.value + } + + settingsRepository.update(updatedSettings) + } + } + + override fun navigateToNextScreen() { + navController.navigate(Routes.TabContainer.name) { + popUpTo(Routes.TrustedNodeSetup.name) { inclusive = true } + } + } +} diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt index 4ab71175..7d8aef36 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -32,24 +33,39 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource import org.koin.compose.koinInject import org.koin.core.qualifier.named +import org.koin.core.parameter.parametersOf +import cafe.adriel.lyricist.LocalStrings -private lateinit var textState: MutableState +import kotlinx.coroutines.flow.StateFlow + +interface ITrustedNodeSetupPresenter { + val bisqUrl: StateFlow + val isConnected: StateFlow + + fun updateBisqUrl(newUrl: String) + + fun testConnection(isTested: Boolean) + + fun navigateToNextScreen() +} -//TODO: Rename this to BisqConnectScreen? @OptIn(ExperimentalResourceApi::class) @Composable fun TrustedNodeSetupScreen( ) { + val strings = LocalStrings.current val navController: NavHostController = koinInject(named("RootNavController")) - textState = remember { mutableStateOf("") } - val isConnected by remember { mutableStateOf(false) } + val presenter: ITrustedNodeSetupPresenter = koinInject { parametersOf(navController) } + + val bisqUrl = presenter.bisqUrl.collectAsState().value + val isConnected = presenter.isConnected.collectAsState().value BisqScrollLayout() { BisqLogo() Spacer(modifier = Modifier.height(24.dp)) Column( verticalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxSize().padding(horizontal = 24.dp) + modifier = Modifier.fillMaxSize().padding(horizontal = 0.dp) ) { Row( modifier = Modifier.fillMaxWidth(), @@ -63,7 +79,7 @@ fun TrustedNodeSetupScreen( Image(painterResource(Res.drawable.icon_question_mark), "Question mark") } - MaterialTextField(textState.value, onValueChanged = { textState.value = it }) + MaterialTextField(bisqUrl, onValueChanged = { presenter.updateBisqUrl(it) }) Row( modifier = Modifier.fillMaxWidth(), @@ -107,46 +123,41 @@ fun TrustedNodeSetupScreen( Spacer(modifier = Modifier.height(56.dp)) - var visible by remember { - mutableStateOf(false) - } - - if (!visible) { + if (!isConnected) { BisqButton( text = "Test Connection", - color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, - onClick = { visible = !visible }, + color = if (bisqUrl.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, + onClick = { + presenter.testConnection(true) + }, padding = PaddingValues(horizontal = 32.dp, vertical = 12.dp), - ) + ) } else { - Row(modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)) { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth().padding(horizontal = 0.dp) + ) { AnimatedVisibility( - visible = visible, + visible = isConnected, enter = slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(700)), ) { BisqButton( text = "Test Connection", - color = if (textState.value.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, - onClick = { }, + color = if (bisqUrl.isEmpty()) BisqTheme.colors.grey1 else BisqTheme.colors.light1, + onClick = { presenter.testConnection(true) }, padding = PaddingValues(horizontal = 32.dp, vertical = 12.dp), ) } - Spacer(modifier = Modifier.width(20.dp)) + //Spacer(modifier = Modifier.width(20.dp)) AnimatedVisibility( - visible = visible, + visible = isConnected, enter = fadeIn(animationSpec = tween(300)), ) { BisqButton( text = "Next", color = BisqTheme.colors.light1, - onClick = { - navController.navigate(Routes.TabContainer.name) { - popUpTo(Routes.TrustedNodeSetup.name) { - inclusive = true - } - } - }, + onClick = { presenter.navigateToNextScreen() }, padding = PaddingValues(horizontal = 32.dp, vertical = 12.dp), ) } From aa118e65ee14847ebe1df582ea4768a4091d75d4 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 16 Nov 2024 22:59:58 +0530 Subject: [PATCH 29/31] - i18n: revert to English --- .../kotlin/network/bisq/mobile/presentation/ui/App.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index b43368dc..8e5aa6e1 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -47,7 +47,7 @@ fun App() { val presenter: AppPresenter = koinInject() val lyricist = rememberStrings() - lyricist.languageTag = Locales.FR + // lyricist.languageTag = Locales.FR BisqTheme(darkTheme = true) { ProvideStrings(lyricist) { From ffadc0b72d33a8de1b4b17d3b2f2a26c8b01b5db Mon Sep 17 00:00:00 2001 From: Rodrigo Varela Date: Sun, 17 Nov 2024 17:22:59 +1100 Subject: [PATCH 30/31] - added presenter hierarchy to propagate lifecycle events to all presenters + small nits --- .../node/presentation/MainNodePresenter.kt | 27 +++-- bisqapps/gradle/libs.versions.toml | 103 +++++++++--------- .../mobile/domain/data/model/BisqStats.kt | 6 +- .../mobile/domain/data/model/BtcFiatPrice.kt | 10 +- .../bisq/mobile/domain/data/model/Greeting.kt | 3 + .../mobile/domain/data/model/NetworkModel.kt | 15 --- .../mobile/domain/data/model/UserProfile.kt | 5 +- .../data/repository/NetworkRepository.kt | 18 --- .../domain/data/repository/Repositories.kt | 8 +- .../bisq/mobile/domain/di/DomainModule.kt | 9 +- .../bisq/mobile/presentation/BasePresenter.kt | 51 ++++++++- .../bisq/mobile/presentation/MainPresenter.kt | 9 +- .../presentation/di/PresentationModule.kt | 9 +- .../presentation/ui/navigation/Routes.kt | 2 +- .../ui/navigation/graph/TabNavGraph.kt | 2 +- .../ui/uicases/GettingStartedPresenter.kt | 18 +-- .../ui/uicases/GettingStartedScreen.kt | 3 + .../ui/uicases/TabContainerScreen.kt | 2 +- .../ui/uicases/exchange/ExchangeScreen.kt | 5 - .../uicases/startup/CreateProfilePresenter.kt | 6 +- .../ui/uicases/startup/OnBoardingPresenter.kt | 4 +- .../ui/uicases/startup/SplashPresenter.kt | 23 +++- .../startup/TrustedNodeSetupPresenter.kt | 8 +- 23 files changed, 188 insertions(+), 158 deletions(-) delete mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt delete mode 100644 bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt diff --git a/bisqapps/androidNode/src/androidMain/kotlin/network/bisq/mobile/android/node/presentation/MainNodePresenter.kt b/bisqapps/androidNode/src/androidMain/kotlin/network/bisq/mobile/android/node/presentation/MainNodePresenter.kt index 394c8a55..b6d68c96 100644 --- a/bisqapps/androidNode/src/androidMain/kotlin/network/bisq/mobile/android/node/presentation/MainNodePresenter.kt +++ b/bisqapps/androidNode/src/androidMain/kotlin/network/bisq/mobile/android/node/presentation/MainNodePresenter.kt @@ -2,17 +2,7 @@ package network.bisq.mobile.android.node.presentation import android.app.Activity import android.os.Build -import network.bisq.mobile.presentation.MainPresenter -import bisq.common.facades.FacadeProvider -import bisq.common.facades.android.AndroidGuavaFacade -import bisq.common.facades.android.AndroidJdkFacade -import bisq.common.network.AndroidEmulatorLocalhostFacade -import org.bouncycastle.jce.provider.BouncyCastleProvider -import java.security.Security import android.os.Process -import network.bisq.mobile.android.node.domain.model.UserProfileModel -import bisq.common.observable.Observable -import bisq.user.identity.UserIdentityService import bisq.application.State import bisq.bonded_roles.market_price.MarketPrice import bisq.chat.ChatChannelDomain @@ -21,8 +11,13 @@ import bisq.chat.common.CommonPublicChatMessage import bisq.chat.two_party.TwoPartyPrivateChatChannel import bisq.chat.two_party.TwoPartyPrivateChatMessage import bisq.common.currency.MarketRepository +import bisq.common.facades.FacadeProvider +import bisq.common.facades.android.AndroidGuavaFacade +import bisq.common.facades.android.AndroidJdkFacade import bisq.common.locale.LanguageRepository +import bisq.common.network.AndroidEmulatorLocalhostFacade import bisq.common.network.TransportType +import bisq.common.observable.Observable import bisq.common.observable.Pin import bisq.common.observable.collection.CollectionObserver import bisq.common.timer.Scheduler @@ -34,16 +29,20 @@ import bisq.security.DigestUtil import bisq.security.SecurityService import bisq.user.identity.NymIdGenerator import bisq.user.identity.UserIdentity +import bisq.user.identity.UserIdentityService import bisq.user.profile.UserProfile import kotlinx.coroutines.* import network.bisq.mobile.android.node.AndroidNodeGreeting import network.bisq.mobile.android.node.domain.data.repository.NodeGreetingRepository +import network.bisq.mobile.android.node.domain.model.UserProfileModel import network.bisq.mobile.android.node.service.AndroidApplicationService import network.bisq.mobile.android.node.service.AndroidMemoryReportService import network.bisq.mobile.domain.data.model.Greeting import network.bisq.mobile.domain.data.repository.GreetingRepository -import network.bisq.mobile.domain.data.repository.SingleObjectRepository -import java.util.Optional +import network.bisq.mobile.presentation.MainPresenter +import org.bouncycastle.jce.provider.BouncyCastleProvider +import java.security.Security +import java.util.* import java.util.concurrent.CompletableFuture import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicLong @@ -105,9 +104,9 @@ class MainNodePresenter(greetingRepository: NodeGreetingRepository): MainPresent launchServices() } - override fun onDestroy() { + override fun onDestroying() { applicationService.shutdown() - super.onDestroy() + super.onDestroying() } private fun log(message: String) { diff --git a/bisqapps/gradle/libs.versions.toml b/bisqapps/gradle/libs.versions.toml index 5fe7d489..868b6e77 100644 --- a/bisqapps/gradle/libs.versions.toml +++ b/bisqapps/gradle/libs.versions.toml @@ -5,13 +5,15 @@ android-targetSdk = "34" android-minSdk = "24" android-node-minSdk = "31" androidx-activityCompose = "1.9.2" + androidx-appcompat = "1.7.0" androidx-constraintlayout = "2.1.4" androidx-core-ktx = "1.13.1" androidx-espresso-core = "3.6.1" -androidx-lifecycle = "2.8.2" androidx-material = "1.12.0" androidx-test-junit = "1.2.1" + +androidx-lifecycle = "2.8.2" androidx-test-compose-ver = "1.6.8" androidx-multidex = "2.0.1" bisq-core = "2.1.2" @@ -26,31 +28,30 @@ buildconfig = "5.5.0" navigationCompose = "2.7.0-alpha07" protobuf = "0.9.4" protob = "4.28.2" -protoblite = "4.28.2" ksp = "2.0.20-1.0.25" chimp-jsocks-lib = { strictly = '567e1cd6' } -chimp-jtorctl-lib = { strictly = '9b5ba203' } failsafe-lib = { strictly = '3.2.4' } + +bouncycastle-lib = { strictly = '1.78.1' } + +google-guava-lib = { strictly = '33.2.1-jre' } + +apache-httpcomponents-httpclient-lib = { strictly = '4.5.14' } # 5.3.1 would be better but has lot of API changes + +chimp-jtorctl-lib = { strictly = '9b5ba203' } apache-commons-lang-lib = { strictly = '3.14.0' } apache-httpcomponents-core-lib = { strictly = '4.4.16' } -apache-httpcomponents-httpclient-lib = { strictly = '4.5.14' } # 5.3.1 would be better but has lot of API changes apache-tomcat-annotations-api = { strictly = '6.0.53' } - assertj-core-lib = { strictly = '3.22.0' } -bouncycastle-lib = { strictly = '1.78.1' } - glassfish-jersey-lib = { strictly = '3.1.8' } glassfish-jaxb-runtime-lib = { strictly = '4.0.5' } - google-gson-lib = { strictly = '2.9.0' } -google-guava-lib = { strictly = '33.2.1-jre' } - grpc = { strictly = '1.61.0' } - i2p-lib = { strictly = '1.8.0' } i2p-v2 = { strictly = '2.4.0' } jackson-lib = { strictly = '2.17.2' } + lyricist = "1.7.0" koin = "4.0.0" @@ -59,20 +60,22 @@ typesafe-config-lib = { strictly = '1.4.3' } [libraries] kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } -kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } kotlin-test-junit-v180 = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlinTestJunit" } kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx" } mock-io = { module = "io.mockk:mockk", version.ref = "mockio" } junit = { group = "junit", name = "junit", version.ref = "junit" } -androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" } -androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" } androidx-multidex = { group = "androidx.multidex", name = "multidex", version.ref = "androidx-multidex" } androidx-test-compose = { group = "androidx.compose.ui", name = "ui-test-junit4-android", version.ref = "androidx-test-compose-ver" } androidx-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version.ref = "androidx-test-compose-ver" } -androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" } -androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" } -androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" } -androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" } + +#kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } +#androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" } +#androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" } +#androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" } +#androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" } +#androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" } +#androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" } + androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" } androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } @@ -88,7 +91,6 @@ bouncycastle-pg = { module = 'org.bouncycastle:bcpg-jdk18on', version.ref = 'bou lyricist = { module = "cafe.adriel.lyricist:lyricist", version.ref = "lyricist" } navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "navigationCompose" } -protobuf-lite = { group ="com.google.protobuf", name = "protobuf-javalite", version.ref = "protoblite"} protobuf-gradle-plugin = { module = 'com.google.protobuf:protobuf-gradle-plugin', version.ref = 'protobuf' } protoc = { module = "com.google.protobuf:protoc", version.ref = "protob" } @@ -115,36 +117,37 @@ bisq-core-identity = { module = "bisq:identity", version.ref = "bisq-core" } # bisq core transitive dependencies chimp-jsocks = { module = 'com.github.chimp1984:jsocks', version.ref = 'chimp-jsocks-lib' } -chimp-jtorctl = { module = 'com.github.chimp1984:jtorctl', version.ref = 'chimp-jtorctl-lib' } failsafe = { module = 'dev.failsafe:failsafe', version.ref = 'failsafe-lib' } -apache-commons-lang = { module = 'org.apache.commons:commons-lang3', version.ref = 'apache-commons-lang-lib' } -apache-httpcomponents-core = { module = 'org.apache.httpcomponents:httpcore', version.ref = 'apache-httpcomponents-core-lib' } apache-httpcomponents-httpclient = { module = 'org.apache.httpcomponents:httpclient', version.ref = 'apache-httpcomponents-httpclient-lib' } -apache-tomcat-annotations-api = { module = 'org.apache.tomcat:annotations-api', version.ref = 'apache-tomcat-annotations-api' } -assertj-core = { module = 'org.assertj:assertj-core', version.ref = 'assertj-core-lib' } -glassfish-jersey-jdk-http = { module = 'org.glassfish.jersey.containers:jersey-container-jdk-http', version.ref = 'glassfish-jersey-lib' } -glassfish-jersey-json-jackson = { module = 'org.glassfish.jersey.media:jersey-media-json-jackson', version.ref = 'glassfish-jersey-lib' } -glassfish-jersey-inject-hk2 = { module = 'org.glassfish.jersey.inject:jersey-hk2', version.ref = 'glassfish-jersey-lib' } -glassfish-jaxb-runtime = { module = 'org.glassfish.jaxb:jaxb-runtime', version.ref = 'glassfish-jaxb-runtime-lib' } - -google-gson = { module = 'com.google.code.gson:gson', version.ref = 'google-gson-lib' } google-guava = { module = 'com.google.guava:guava', version.ref = 'google-guava-lib' } -grpc-netty-shaded = { module = 'io.grpc:grpc-netty-shaded', version.ref = 'grpc' } -grpc-protobuf = { module = 'io.grpc:grpc-protobuf', version.ref = 'grpc' } -grpc-services = { module = 'io.grpc:grpc-services', version.ref = 'grpc' } -grpc-stub = { module = 'io.grpc:grpc-stub', version.ref = 'grpc' } - - -i2p-core = { module = 'net.i2p:i2p', version.ref = 'i2p-lib' } -i2p-core-v2 = { module = 'net.i2p:i2p', version.ref = 'i2p-v2' } -i2p-streaming = { module = 'net.i2p.client:streaming', version.ref = 'i2p-lib' } -i2p-streaming-v2 = { module = 'net.i2p.client:streaming', version.ref = 'i2p-v2' } -i2p-router = { module = 'net.i2p:router', version.ref = 'i2p-lib' } - -jackson-core = { module = 'com.fasterxml.jackson.core:jackson-core', version.ref = 'jackson-lib' } -jackson-annotations = { module = 'com.fasterxml.jackson.core:jackson-annotations', version.ref = 'jackson-lib' } -jackson-databind = { module = 'com.fasterxml.jackson.core:jackson-databind', version.ref = 'jackson-lib' } +#chimp-jtorctl = { module = 'com.github.chimp1984:jtorctl', version.ref = 'chimp-jtorctl-lib' } +#apache-commons-lang = { module = 'org.apache.commons:commons-lang3', version.ref = 'apache-commons-lang-lib' } +#apache-httpcomponents-core = { module = 'org.apache.httpcomponents:httpcore', version.ref = 'apache-httpcomponents-core-lib' } +#apache-tomcat-annotations-api = { module = 'org.apache.tomcat:annotations-api', version.ref = 'apache-tomcat-annotations-api' } +#assertj-core = { module = 'org.assertj:assertj-core', version.ref = 'assertj-core-lib' } +#glassfish-jersey-jdk-http = { module = 'org.glassfish.jersey.containers:jersey-container-jdk-http', version.ref = 'glassfish-jersey-lib' } +#glassfish-jersey-json-jackson = { module = 'org.glassfish.jersey.media:jersey-media-json-jackson', version.ref = 'glassfish-jersey-lib' } +#glassfish-jersey-inject-hk2 = { module = 'org.glassfish.jersey.inject:jersey-hk2', version.ref = 'glassfish-jersey-lib' } +#glassfish-jaxb-runtime = { module = 'org.glassfish.jaxb:jaxb-runtime', version.ref = 'glassfish-jaxb-runtime-lib' } +# +#google-gson = { module = 'com.google.code.gson:gson', version.ref = 'google-gson-lib' } + +#grpc-netty-shaded = { module = 'io.grpc:grpc-netty-shaded', version.ref = 'grpc' } +#grpc-protobuf = { module = 'io.grpc:grpc-protobuf', version.ref = 'grpc' } +#grpc-services = { module = 'io.grpc:grpc-services', version.ref = 'grpc' } +#grpc-stub = { module = 'io.grpc:grpc-stub', version.ref = 'grpc' } +# +# +#i2p-core = { module = 'net.i2p:i2p', version.ref = 'i2p-lib' } +#i2p-core-v2 = { module = 'net.i2p:i2p', version.ref = 'i2p-v2' } +#i2p-streaming = { module = 'net.i2p.client:streaming', version.ref = 'i2p-lib' } +#i2p-streaming-v2 = { module = 'net.i2p.client:streaming', version.ref = 'i2p-v2' } +#i2p-router = { module = 'net.i2p:router', version.ref = 'i2p-lib' } +# +#jackson-core = { module = 'com.fasterxml.jackson.core:jackson-core', version.ref = 'jackson-lib' } +#jackson-annotations = { module = 'com.fasterxml.jackson.core:jackson-annotations', version.ref = 'jackson-lib' } +#jackson-databind = { module = 'com.fasterxml.jackson.core:jackson-databind', version.ref = 'jackson-lib' } # koin koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } @@ -152,11 +155,11 @@ koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin" } koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" } [bundles] -glassfish-jersey = ['glassfish-jersey-jdk-http', 'glassfish-jersey-json-jackson', 'glassfish-jersey-inject-hk2', 'glassfish-jaxb-runtime'] -grpc = ['grpc-protobuf', 'grpc-services', 'grpc-stub'] -i2p = ['i2p-core', 'i2p-router', 'i2p-streaming'] -i2p-v2 = ['i2p-core-v2', 'i2p-streaming-v2'] -jackson = ['jackson-core', 'jackson-annotations', 'jackson-databind'] +#glassfish-jersey = ['glassfish-jersey-jdk-http', 'glassfish-jersey-json-jackson', 'glassfish-jersey-inject-hk2', 'glassfish-jaxb-runtime'] +#grpc = ['grpc-protobuf', 'grpc-services', 'grpc-stub'] +#i2p = ['i2p-core', 'i2p-router', 'i2p-streaming'] +#i2p-v2 = ['i2p-core-v2', 'i2p-streaming-v2'] +#jackson = ['jackson-core', 'jackson-annotations', 'jackson-databind'] [plugins] kotlinCocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" } diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt index 6ee31b86..2a5452da 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BisqStats.kt @@ -1,10 +1,10 @@ package network.bisq.mobile.domain.data.model -open class BisqStats: BaseModel() { - open val offersOnline = 150 +class BisqStats: BaseModel() { + val offersOnline = 150 - open val publishedProfiles = 1275 + val publishedProfiles = 1275 } interface BisqStatsFactory { diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt index 5168e00c..726092ad 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/BtcFiatPrice.kt @@ -1,17 +1,11 @@ package network.bisq.mobile.domain.data.model -open class BtcPrice: BaseModel() { - - protected open val prices: Map = mapOf( +class BtcPrice: BaseModel() { + val prices: Map = mapOf( "USD" to 64000.50, "EUR" to 58000.75, "GBP" to 52000.30, ) - - fun getBtcPrice(): Map { - return prices - } - } interface BtcPriceFactory { diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Greeting.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Greeting.kt index cde04698..ad6afba4 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Greeting.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/Greeting.kt @@ -2,6 +2,9 @@ package network.bisq.mobile.domain.data.model import network.bisq.mobile.domain.getPlatform +/** + * In general the models should remain closed, this is just an example from the time when we didn't have repositories and presenter + */ open class Greeting: BaseModel() { protected val platform = getPlatform() protected open val greetText = "Hello, ${platform.name}!" diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt deleted file mode 100644 index ef4b3e25..00000000 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/NetworkModel.kt +++ /dev/null @@ -1,15 +0,0 @@ -package network.bisq.mobile.domain.data.model - -import kotlinx.coroutines.delay - -open class NetworkModel: BaseModel() { - var progress: Float = 0.0f -} - -interface NetworkModelFactory { - fun createNetworkModel(): NetworkModel -} - -class DefaultNetworkModelFactory : NetworkModelFactory { - override fun createNetworkModel() = NetworkModel() -} \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt index f7fe6262..b945806d 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/model/UserProfile.kt @@ -1,8 +1,7 @@ package network.bisq.mobile.domain.data.model -// TODO: Is it okay for the models to be mutable? -open class UserProfile: BaseModel() { - open var name = "" +class UserProfile: BaseModel() { + var name = "" } interface UserProfileFactory { diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt deleted file mode 100644 index 569f50e0..00000000 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/NetworkRepository.kt +++ /dev/null @@ -1,18 +0,0 @@ - package network.bisq.mobile.domain.data.repository - - import kotlinx.coroutines.delay - import network.bisq.mobile.domain.data.model.NetworkModel - - open class NetworkRepository : SingleObjectRepository() { - - suspend fun initializeNetwork(updateProgress: (Float) -> Unit) { - - //1. Initialize Tor here - //2. Connect to peers (for androidNode), to Bisq instance (for xClients) - //3. Do any other app initialization - for (i in 1..100) { - updateProgress(i.toFloat() / 100) - delay(25) - } - } - } \ No newline at end of file diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt index fe84133c..0ebf0612 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/data/repository/Repositories.kt @@ -5,7 +5,7 @@ import network.bisq.mobile.domain.data.model.* // this way of definingsupports both platforms // add your repositories here and then in your DI module call this classes for instanciation open class GreetingRepository: SingleObjectRepository() -open class BisqStatsRepository: SingleObjectRepository() -open class BtcPriceRepository: SingleObjectRepository() -open class UserProfileRepository: SingleObjectRepository() -open class SettingsRepository: SingleObjectRepository() +open class BisqStatsRepository: SingleObjectRepository() +open class BtcPriceRepository: SingleObjectRepository() +open class UserProfileRepository: SingleObjectRepository() +open class SettingsRepository: SingleObjectRepository() diff --git a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt index b872856f..99374209 100644 --- a/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt +++ b/bisqapps/shared/domain/src/commonMain/kotlin/network/bisq/mobile/domain/di/DomainModule.kt @@ -6,9 +6,8 @@ import org.koin.dsl.module val domainModule = module { single> { GreetingRepository() } - single> { BisqStatsRepository() } - single> { BtcPriceRepository() } - single> { NetworkRepository() } - single> { UserProfileRepository() } - single> { SettingsRepository() } + single { BisqStatsRepository() } + single { BtcPriceRepository() } + single { UserProfileRepository() } + single { SettingsRepository() } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt index 75a6a275..1220047c 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt @@ -10,50 +10,91 @@ import kotlinx.coroutines.cancel * Presenter for any type of view. * The view should define its own interface that the child presenter should implement as well, but * this class provide generic useful and common behaviour for presenters + * + * Base class allows to have a tree hierarchy of presenters. If the rootPresenter is null, this presenter acts as root + * if root present is passed, this present attach itself to the root to get updates (consequently its dependants will be always empty */ -abstract class BasePresenter { +abstract class BasePresenter(private val rootPresenter: MainPresenter?) { protected var view: Any? = null private val log = Logger.withTag("BasePresenter") + // Coroutine scope for the presenter + protected val presenterScope = CoroutineScope(Dispatchers.Main + Job()) + + private val dependants = if (isRoot()) mutableListOf() else null + + init { + rootPresenter?.registerChild(child = this) + } /** * This can be used as initialization method AFTER view gets attached (so view is available) */ open fun onViewAttached() { } - // Coroutine scope for the presenter - protected val presenterScope = CoroutineScope(Dispatchers.Main + Job()) /** * This can be used as cleanup BEFORE unattaching a view */ open fun onViewUnattaching() { } + /** + * This can be used to do cleanup when the view is getting destroyed + * Base Presenter corouting scope gets cancelled right before this method is called + */ + open fun onDestroying() { } + open fun onStart() { log.i { "Lifecycle: START" } + this.dependants?.forEach { it.onStart() } } open fun onResume() { log.i { "Lifecycle: RESUME" } + this.dependants?.forEach { it.onResume() } } open fun onPause() { log.i { "Lifecycle: PAUSE" } + this.dependants?.forEach { it.onPause() } } open fun onStop() { log.i { "Lifecycle: STOP" } + this.dependants?.forEach { it.onStop() } } - open fun onDestroy() { + fun onDestroy() { log.i { "Lifecycle: DESTROY" } + dependants?.forEach { it.onDestroy() } + rootPresenter?.unregisterChild(this) presenterScope.cancel() + onDestroying() } fun attachView(view: Any) { + // at the moment the attach view is with the activity/ main view in ios + // unless we change this there is no point in sharing with dependents this.view = view log.i { "Lifecycle: View Attached from Presenter" } onViewAttached() } - open fun detachView() { + fun detachView() { onViewUnattaching() this.view = null log.i { "Lifecycle: View Dettached from Presenter" } } + + protected fun registerChild(child: BasePresenter) { + if (!isRoot()) { + throw IllegalStateException("You can't register to a non root presenter") + } + this.dependants!!.add(child) + } + + // TODO we need to test to find what are exactly the best places to register/unregister + protected fun unregisterChild(child: BasePresenter) { + if (!isRoot()) { + throw IllegalStateException("You can't unregister to a non root presenter") + } + this.dependants!!.remove(child) + } + + private fun isRoot() = rootPresenter == null } \ No newline at end of file diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/MainPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/MainPresenter.kt index b87dd2b5..82dcd922 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/MainPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/MainPresenter.kt @@ -15,13 +15,13 @@ import network.bisq.mobile.presentation.ui.AppPresenter /** * Main Presenter as an example of implementation for now. */ -open class MainPresenter(private val greetingRepository: GreetingRepository) : BasePresenter(), AppPresenter { +open class MainPresenter(private val greetingRepository: GreetingRepository) : BasePresenter(null), AppPresenter { private val log = Logger.withTag("MainPresenter") // Observable state private val _isContentVisible = MutableStateFlow(false) override val isContentVisible: StateFlow = _isContentVisible - // The following bounds the specific field I want to grab from the model using the stateflow to automatically observe updates + // TODO remove we don't need all the gretting example stuff anymore - but this code to passthrough should be a helper for presentation private val _greetingText: StateFlow = greetingRepository.data .map { it?.greet() ?: "" } // Transform Greeting to String, we don't want the null .stateIn( @@ -29,6 +29,7 @@ open class MainPresenter(private val greetingRepository: GreetingRepository = _greetingText init { @@ -49,4 +50,8 @@ open class MainPresenter(private val greetingRepository: GreetingRepository SplashPresenter( - navController = navController, - networkRepository = get() + get(), + navController = navController ) } bind ISplashPresenter::class - single { (navController: NavController) -> OnBoardingPresenter(navController) } bind IOnboardingPresenter::class + single { (navController: NavController) -> OnBoardingPresenter(get(), navController) } bind IOnboardingPresenter::class single { GettingStartedPresenter( + get(), priceRepository = get(), bisqStatsRepository = get() ) @@ -46,6 +47,7 @@ val presentationModule = module { single { (navController: NavController) -> CreateProfilePresenter( + get(), navController = navController, userProfileRepository = get() ) @@ -53,6 +55,7 @@ val presentationModule = module { single { (navController: NavController) -> TrustedNodeSetupPresenter( + get(), navController = navController, settingsRepository = get() ) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt index 62f6aebb..25dc0b40 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/Routes.kt @@ -3,7 +3,7 @@ package network.bisq.mobile.presentation.ui.navigation import org.jetbrains.compose.resources.StringResource object Graph { - const val MainScreenGraph = "mainScreenGraph" + const val MAIN_SCREEN_GRAPH_KEY = "mainScreenGraph" } enum class Routes(val title: String) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt index 31a85eb6..4a2aaf61 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/graph/TabNavGraph.kt @@ -13,7 +13,7 @@ import network.bisq.mobile.presentation.ui.uicases.trades.MyTradesScreen fun NavGraphBuilder.TabNavGraph() { navigation( startDestination = Routes.TabHome.name, - route = Graph.MainScreenGraph + route = Graph.MAIN_SCREEN_GRAPH_KEY ) { composable(route = Routes.TabHome.name) { GettingStartedScreen() diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt index ad1bc4aa..4739d0f6 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedPresenter.kt @@ -6,16 +6,16 @@ import kotlinx.coroutines.IO import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import network.bisq.mobile.domain.data.model.BisqStats -import network.bisq.mobile.domain.data.model.BtcPrice import network.bisq.mobile.domain.data.repository.BisqStatsRepository import network.bisq.mobile.domain.data.repository.BtcPriceRepository import network.bisq.mobile.presentation.BasePresenter +import network.bisq.mobile.presentation.MainPresenter class GettingStartedPresenter( - private val priceRepository: BtcPriceRepository, - private val bisqStatsRepository: BisqStatsRepository -) : BasePresenter(), IGettingStarted { + mainPresenter: MainPresenter, + private val priceRepository: BtcPriceRepository, + private val bisqStatsRepository: BisqStatsRepository +) : BasePresenter(mainPresenter), IGettingStarted { private val _btcPrice = MutableStateFlow("Loading...")//("$75,000") override val btcPrice: StateFlow = _btcPrice @@ -25,7 +25,7 @@ class GettingStartedPresenter( private val _publishedProfiles = MutableStateFlow(1145) override val publishedProfiles: StateFlow = _publishedProfiles - fun refresh() { + private fun refresh() { CoroutineScope(Dispatchers.IO).launch { try { val bisqStats = bisqStatsRepository.fetch() @@ -33,14 +33,18 @@ class GettingStartedPresenter( _publishedProfiles.value = bisqStats?.publishedProfiles ?: 0 val btcPrice = priceRepository.fetch() - val priceList = btcPrice?.getBtcPrice() + val priceList = btcPrice?.prices _btcPrice.value = (priceList?.get("USD") ?: 0).toString() } catch (e: Exception) { // Handle errors println("Error: ${e.message}") } } + } + override fun onViewAttached() { + super.onViewAttached() + refresh() } override fun onResume() { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt index 0306aea6..65fd1008 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/GettingStartedScreen.kt @@ -54,6 +54,9 @@ fun GettingStartedScreen() { val btcPrice:String = presenter.btcPrice.collectAsState().value val offersOnline:Number = presenter.offersOnline.collectAsState().value val publishedProfiles:Number = presenter.publishedProfiles.collectAsState().value + + // TODO attach view should happen here to let the presenter know? + Column( modifier = Modifier.fillMaxSize(), ) { diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt index 35e00fce..aaf23955 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/TabContainerScreen.kt @@ -56,6 +56,6 @@ fun TabContainerScreen() { } ) { innerPadding -> - RootNavGraph(startDestination = Graph.MainScreenGraph) + RootNavGraph(startDestination = Graph.MAIN_SCREEN_GRAPH_KEY) } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt index 89b298fb..e3751023 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/exchange/ExchangeScreen.kt @@ -3,11 +3,8 @@ package network.bisq.mobile.presentation.ui.uicases.exchange import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.calculateEndPadding -import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -19,7 +16,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.dp -import androidx.navigation.NavController import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.currency_euro @@ -33,7 +29,6 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.koin.compose.koinInject import org.koin.core.qualifier.named -@OptIn(ExperimentalResourceApi::class) @Composable fun ExchangeScreen() { val navController: NavHostController = koinInject(named("RootNavController")) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt index 2b1e4e54..d4d4c4ee 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt @@ -13,11 +13,13 @@ import network.bisq.mobile.domain.data.model.UserProfile import network.bisq.mobile.presentation.BasePresenter import network.bisq.mobile.presentation.ui.navigation.Routes import kotlinx.coroutines.delay +import network.bisq.mobile.presentation.MainPresenter open class CreateProfilePresenter( + mainPresenter: MainPresenter, private val navController: NavController, - private val userProfileRepository: UserProfileRepository -) : BasePresenter(), ICreateProfilePresenter { + private val userProfileRepository: UserProfileRepository +) : BasePresenter(mainPresenter), ICreateProfilePresenter { private val _profileName = MutableStateFlow("") override val profileName: StateFlow = _profileName diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt index cdf138b7..d1bcdd43 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/OnBoardingPresenter.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import network.bisq.mobile.presentation.BasePresenter +import network.bisq.mobile.presentation.MainPresenter import network.bisq.mobile.presentation.ui.composeModels.OnBoardingPage import network.bisq.mobile.presentation.ui.navigation.Routes @@ -34,8 +35,9 @@ val onBoardingPages = listOf( ) open class OnBoardingPresenter( + mainPresenter: MainPresenter, private val navController: NavController -) : BasePresenter(), IOnboardingPresenter { +) : BasePresenter(mainPresenter), IOnboardingPresenter { private val _pagerState = MutableStateFlow(null) override val pagerState: StateFlow = _pagerState diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt index cda4ba68..ee32925a 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/SplashPresenter.kt @@ -4,27 +4,38 @@ import androidx.navigation.NavController import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import network.bisq.mobile.domain.data.repository.NetworkRepository -import network.bisq.mobile.domain.data.model.NetworkModel import network.bisq.mobile.presentation.BasePresenter import network.bisq.mobile.presentation.ui.navigation.Routes import kotlinx.coroutines.delay +import network.bisq.mobile.presentation.MainPresenter open class SplashPresenter( - private val navController: NavController, - private val networkRepository: NetworkRepository -) : BasePresenter(), ISplashPresenter { + mainPresenter: MainPresenter, + private val navController: NavController +) : BasePresenter(mainPresenter), ISplashPresenter { private val coroutineScope = CoroutineScope(Dispatchers.Main) override fun startLoading(onProgressUpdate: (Float) -> Unit) { coroutineScope.launch { - networkRepository?.initializeNetwork{ progress -> + initializeNetwork{ progress -> onProgressUpdate(progress) } navigateToNextScreen() } } + // TODO refactor into a service once networking is done + protected open suspend fun initializeNetwork(updateProgress: (Float) -> Unit) { + + //1. Initialize Tor here + //2. Connect to peers (for androidNode), to Bisq instance (for xClients) + //3. Do any other app initialization + for (i in 1..100) { + updateProgress(i.toFloat() / 100) + delay(25) + } + } + private fun navigateToNextScreen() { // TODO: Conditional nav // If firstTimeApp launch, goto Onboarding[clientMode] (androidNode / xClient) diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt index 71268d77..ef9315bf 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/TrustedNodeSetupPresenter.kt @@ -7,17 +7,17 @@ import kotlinx.coroutines.IO import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import kotlinx.coroutines.flow.collectLatest import network.bisq.mobile.domain.data.model.Settings import network.bisq.mobile.domain.data.repository.SettingsRepository import network.bisq.mobile.presentation.BasePresenter +import network.bisq.mobile.presentation.MainPresenter import network.bisq.mobile.presentation.ui.navigation.Routes -import kotlinx.coroutines.delay class TrustedNodeSetupPresenter( + mainPresenter: MainPresenter, private val navController: NavController, - private val settingsRepository: SettingsRepository -) : BasePresenter(), ITrustedNodeSetupPresenter { + private val settingsRepository: SettingsRepository +) : BasePresenter(mainPresenter), ITrustedNodeSetupPresenter { private val _bisqUrl = MutableStateFlow("") override val bisqUrl: StateFlow = _bisqUrl From 2d52845d35d22dc701e628dede3a75ac32250f05 Mon Sep 17 00:00:00 2001 From: Rodrigo Varela Date: Sun, 17 Nov 2024 17:40:30 +1100 Subject: [PATCH 31/31] - using iOS notification center for a more precise onResume() behaviour --- .../LifecycleAwareComposeViewController.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bisqapps/iosClient/iosClient/LifecycleAwareComposeViewController.swift b/bisqapps/iosClient/iosClient/LifecycleAwareComposeViewController.swift index c800a17a..5916a3b3 100644 --- a/bisqapps/iosClient/iosClient/LifecycleAwareComposeViewController.swift +++ b/bisqapps/iosClient/iosClient/LifecycleAwareComposeViewController.swift @@ -18,12 +18,22 @@ class LifecycleAwareComposeViewController: UIViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) + NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil) presenter.onPause() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) presenter.onResume() + NotificationCenter.default.addObserver( + self, + selector: #selector(handleDidBecomeActive), + name: UIApplication.didBecomeActiveNotification, + object: nil) + } + + @objc private func handleDidBecomeActive() { + presenter.onResume() } override func viewWillAppear(_ animated: Bool) {