solara 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/solara/lib/core/.DS_Store +0 -0
  3. data/solara/lib/core/aliases/alias_generator.rb +1 -0
  4. data/solara/lib/core/aliases/alias_generator_manager.rb +2 -1
  5. data/solara/lib/core/aliases/solara_terminal_setup.rb +1 -1
  6. data/solara/lib/core/brands/brand_font_switcher.rb +154 -0
  7. data/solara/lib/core/brands/brand_onboarder.rb +8 -6
  8. data/solara/lib/core/brands/brand_switcher.rb +232 -166
  9. data/solara/lib/core/brands/brands_manager.rb +15 -39
  10. data/solara/lib/core/dashboard/brand/BrandDetail.js +19 -0
  11. data/solara/lib/core/dashboard/brand/BrandDetailController.js +50 -8
  12. data/solara/lib/core/dashboard/brand/BrandDetailModel.js +9 -30
  13. data/solara/lib/core/dashboard/brand/BrandDetailView.js +49 -3
  14. data/solara/lib/core/dashboard/brand/InfoPlistStringCatalogManager.js +19 -0
  15. data/solara/lib/core/dashboard/brand/brand.html +209 -62
  16. data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +1 -1
  17. data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +38 -53
  18. data/solara/lib/core/dashboard/brands/BrandsController.js +6 -5
  19. data/solara/lib/core/dashboard/brands/BrandsModel.js +2 -2
  20. data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
  21. data/solara/lib/core/dashboard/brands/brands.html +3 -1
  22. data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +7 -5
  23. data/solara/lib/core/dashboard/dashboard_manager.rb +2 -0
  24. data/solara/lib/core/dashboard/dashboard_server.rb +13 -8
  25. data/solara/lib/core/dashboard/handler/brand_alisases_handler.rb +4 -11
  26. data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +11 -11
  27. data/solara/lib/core/dashboard/handler/{brand_configurations_handler.rb → brand_details_handler.rb} +4 -4
  28. data/solara/lib/core/dashboard/handler/brands_handler.rb +1 -1
  29. data/solara/lib/core/dashboard/handler/edit_section_handler.rb +8 -8
  30. data/solara/lib/core/doctor/brand_doctor.rb +31 -31
  31. data/solara/lib/core/doctor/doctor_manager.rb +0 -1
  32. data/solara/lib/core/doctor/project_doctor.rb +0 -1
  33. data/solara/lib/core/doctor/schema/platform/android/android_config.json +0 -4
  34. data/solara/lib/core/doctor/schema/platform/ios/InfoPlist.xcstrings +15 -0
  35. data/solara/lib/core/doctor/schema/platform/ios/ios_config.json +0 -5
  36. data/solara/lib/core/doctor/schema/platform/shared/brand_config.json +9 -0
  37. data/solara/lib/core/doctor/schema/platform/shared/theme.json +94 -9
  38. data/solara/lib/core/doctor/validator/brand_settings_validator.rb +6 -0
  39. data/solara/lib/core/doctor/validator/brand_settings_validator_manager.rb +9 -21
  40. data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +22 -4
  41. data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +22 -6
  42. data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +22 -4
  43. data/solara/lib/core/scripts/brand_config_generator.rb +1 -0
  44. data/solara/lib/core/scripts/brand_config_manager.rb +2 -4
  45. data/solara/lib/core/scripts/brand_exporter.rb +1 -1
  46. data/solara/lib/core/scripts/brand_importer.rb +2 -3
  47. data/solara/lib/core/scripts/brand_offboarder.rb +5 -0
  48. data/solara/lib/core/scripts/brand_resources_manager.rb +127 -54
  49. data/solara/lib/core/scripts/directory_creator.rb +2 -2
  50. data/solara/lib/core/scripts/file_manager.rb +53 -19
  51. data/solara/lib/core/scripts/file_path.rb +175 -30
  52. data/solara/lib/core/scripts/folder_copier.rb +3 -7
  53. data/solara/lib/core/scripts/gitignore_manager.rb +21 -10
  54. data/solara/lib/core/scripts/interactive_file_system_validator.rb +8 -2
  55. data/solara/lib/core/scripts/platform/android/android_manifest_switcher.rb +3 -3
  56. data/solara/lib/core/scripts/platform/android/android_strings_switcher.rb +26 -24
  57. data/solara/lib/core/scripts/platform/android/gradle_switcher.rb +7 -6
  58. data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +123 -0
  59. data/solara/lib/core/scripts/platform/ios/infoplist_switcher.rb +59 -0
  60. data/solara/lib/core/scripts/platform/ios/ios_plist_manager.rb +11 -20
  61. data/solara/lib/core/scripts/platform/ios/plist_font_manager.rb +33 -0
  62. data/solara/lib/core/scripts/platform/ios/xcconfig_generator.rb +15 -3
  63. data/solara/lib/core/scripts/platform/ios/xcode_asset_manager.rb +2 -3
  64. data/solara/lib/core/scripts/platform/ios/xcode_project_manager.rb +80 -1
  65. data/solara/lib/core/scripts/platform/ios/xcode_project_switcher.rb +15 -34
  66. data/solara/lib/core/scripts/solara_logger.rb +10 -0
  67. data/solara/lib/core/scripts/solara_settings_manager.rb +26 -1
  68. data/solara/lib/core/scripts/strings_xml_manager.rb +17 -2
  69. data/solara/lib/core/scripts/theme_generator.rb +133 -130
  70. data/solara/lib/core/scripts/yaml_manager.rb +23 -0
  71. data/solara/lib/core/solara_configurator.rb +1 -1
  72. data/solara/lib/core/template/brands/android/android_config.json +0 -1
  73. data/solara/lib/core/template/brands/android/res/values/strings.xml +4 -0
  74. data/solara/lib/core/template/brands/ios/InfoPlist.xcstrings +30 -0
  75. data/solara/lib/core/template/brands/ios/ios_config.json +1 -2
  76. data/solara/lib/core/template/brands/shared/brand_config.json +1 -0
  77. data/solara/lib/core/template/brands/shared/theme.json +3 -3
  78. data/solara/lib/core/template/config/android_template_config.json +11 -1
  79. data/solara/lib/core/template/config/flutter_template_config.json +12 -2
  80. data/solara/lib/core/template/config/ios_template_config.json +11 -1
  81. data/solara/lib/core/template/project_template_generator.rb +8 -3
  82. data/solara/lib/solara/version.rb +1 -1
  83. data/solara/lib/solara.rb +8 -4
  84. data/solara/lib/solara_initializer.rb +5 -2
  85. data/solara/lib/solara_manager.rb +1 -1
  86. metadata +62 -43
  87. data/solara/lib/core/dashboard/handler/brand_section_handler.rb +0 -20
  88. data/solara/lib/core/doctor/validator/directory_structure_validator.rb +0 -38
  89. data/solara/lib/core/doctor/validator/file_structure_validator.rb +0 -37
  90. data/solara/lib/core/scripts/platform/ios/ios_file_path_manager.rb +0 -109
  91. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/.DS_Store +0 -0
  92. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/100.png +0 -0
  93. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/102.png +0 -0
  94. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/1024.png +0 -0
  95. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/114.png +0 -0
  96. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/120.png +0 -0
  97. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/128.png +0 -0
  98. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/144.png +0 -0
  99. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/152.png +0 -0
  100. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/16.png +0 -0
  101. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/167.png +0 -0
  102. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/172.png +0 -0
  103. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/180.png +0 -0
  104. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/196.png +0 -0
  105. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/20.png +0 -0
  106. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/216.png +0 -0
  107. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/256.png +0 -0
  108. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/29.png +0 -0
  109. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/32.png +0 -0
  110. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/40.png +0 -0
  111. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/48.png +0 -0
  112. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/50.png +0 -0
  113. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/512.png +0 -0
  114. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/55.png +0 -0
  115. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/57.png +0 -0
  116. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/58.png +0 -0
  117. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/60.png +0 -0
  118. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/64.png +0 -0
  119. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/66.png +0 -0
  120. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/72.png +0 -0
  121. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/76.png +0 -0
  122. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/80.png +0 -0
  123. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/87.png +0 -0
  124. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/88.png +0 -0
  125. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/92.png +0 -0
  126. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/Contents.json +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 190a0c29bbb6d5e00c92181dd75543be6a37c671110d2db37c2704a92f962ff3
4
- data.tar.gz: 37977f6295ce0ec00be3427e62b2930353091dde1705d12eb967932187b9ea89
3
+ metadata.gz: bf4626fe23d16f245e1e77267bf23f3b368cd4bb2fd286cb038a73f52f7f6b65
4
+ data.tar.gz: a4bbc04dfe9844532227f16283c4c3b7cf86450a21a75b01a479a88be8021c82
5
5
  SHA512:
6
- metadata.gz: 7ae71b89f2009fb46d5ec2f50baaba4b759a38b75a2bd1040117ef87263c5bfbb97b38aba44f2b911b5711d60a9c72109a91cb8a65841a0779b318d522fa271a
7
- data.tar.gz: 9c204a83bb994794f1afebbd793c73901596bf4cebae5ff38ed0ae844cc17bc6cb289232af14fa8c75520f5e0c5318866477bdd1a19ac3e62d073cd71f3f8144
6
+ metadata.gz: c490881fbbcf873cb1fae33bcad4f25989cff5196ff70d0494238e2640cd39d68089512fe940590863d633494528755ee6dd4024d05d58f379c503cdd499b3ac
7
+ data.tar.gz: bcebb36d901d66ea8f184f480fcceb3c8472d35424432ea43d0a42b153409ff500f968626c32f507011f012194b5277f2defab8ce52c25064730ae2cccdc07eb
Binary file
@@ -18,6 +18,7 @@ class AliasGenerator
18
18
 
19
19
  def add_brand_aliases(brands)
20
20
  alias_templates = [
21
+ "solara_export_{brand_key}='solara export --brand_keys {brand_key}'",
21
22
  "solara_offboard_{brand_key}='solara offboard -k {brand_key}'",
22
23
  "solara_switch_{brand_key}='solara switch -k {brand_key}'",
23
24
  "solara_doctor_{brand_key}='solara doctor -k {brand_key}'",
@@ -1,6 +1,6 @@
1
1
  class AliasGeneratorManager
2
2
  def initialize
3
- @generator = AliasGenerator.new()
3
+ @generator = AliasGenerator.new
4
4
  end
5
5
 
6
6
  def start
@@ -8,6 +8,7 @@ class AliasGeneratorManager
8
8
  common_aliases = [
9
9
  "solara_dashboard='solara dashboard'",
10
10
  "solara_doctor='solara doctor'",
11
+ "solara_status='solara status'",
11
12
  ]
12
13
 
13
14
  @generator.add_brand_aliases(BrandsManager.instance.brands_list)
@@ -83,7 +83,7 @@ class SolaraSetup
83
83
  reg['AutoRun', Win32::Registry::REG_EXPAND_SZ] = @windows_setup_file
84
84
  end
85
85
  Solara.logger.success("Windows AutoRun registry key set up successfully.")
86
- pSolara.logger.warn("Please restart your Command Prompt to apply changes.")
86
+ Solara.logger.warn("Please restart your Command Prompt to apply changes.")
87
87
  rescue Win32::Registry::Error => e
88
88
  Solara.logger.failure("Failed to set up Windows registry: #{e.message}")
89
89
  Solara.logger.failure("Please add the following file path to your AutoRun registry key manually:")
@@ -0,0 +1,154 @@
1
+ Dir[File.expand_path('scripts/*.rb', __dir__)].each { |file| require_relative file }
2
+ Dir[File.expand_path('../template/*.rb', __dir__)].each { |file| require_relative file }
3
+ Dir[File.expand_path('platform/android/*.rb', __dir__)].each { |file| require_relative file }
4
+ Dir[File.expand_path('platform/ios/*.rb', __dir__)].each { |file| require_relative file }
5
+ Dir[File.expand_path('platform/flutter/*.rb', __dir__)].each { |file| require_relative file }
6
+ class BrandFontSwitcher
7
+ def initialize(brand_key)
8
+ @brand_key = brand_key
9
+ @fonts_path = FilePath.brand_fonts
10
+ @font_files = Dir.glob(File.join(@fonts_path, '*.{ttf,otf}'))
11
+ Solara.logger.end_step("Switch Info.plist")
12
+ end
13
+
14
+ def switch
15
+ Solara.logger.header("Switch Fonts")
16
+
17
+ case SolaraSettingsManager.instance.platform
18
+ when Platform::Flutter
19
+ FlutterFontSwitcher.new(@brand_key, @font_files).switch
20
+ AndroidFontSwitcher.new(@brand_key, @font_files).switch
21
+ IOSFontSwitcher.new(@brand_key, @font_files).switch
22
+ when Platform::Android
23
+ AndroidFontSwitcher.new(@brand_key, @font_files).switch
24
+ when Platform::IOS
25
+ IOSFontSwitcher.new(@brand_key, @font_files).switch
26
+ else
27
+ raise ArgumentError, "Invalid platform: #{SolaraSettingsManager.instance.platform}"
28
+ end
29
+ end
30
+ end
31
+
32
+ class FlutterFontSwitcher
33
+ def initialize(brand_key, font_files)
34
+ @brand_key = brand_key
35
+ @font_files = font_files
36
+ end
37
+
38
+ def switch
39
+ Solara.logger.start_step("Switch Flutter fonts")
40
+ destination = FilePath.flutter_project_fonts
41
+ copy_fonts(destination)
42
+
43
+ add_fonts_to_pubspec
44
+ Solara.logger.end_step("Switch Flutter fonts")
45
+ end
46
+
47
+ private
48
+
49
+ def add_fonts_to_pubspec
50
+ yaml_manager = YamlManager.new(FilePath.pub_spec_yaml)
51
+ font_families = Hash.new { |hash, key| hash[key] = [] }
52
+
53
+ font_names = @font_files.map { |file| File.basename(file) }
54
+ font_names.each do |font_file|
55
+ base_name = File.basename(font_file, File.extname(font_file))
56
+ family_name = base_name.split('-').first
57
+ font_families[family_name] << font_file
58
+ end
59
+
60
+ font_families.each do |family_name, files|
61
+ assets = files.map { |file| { 'asset' => "assets/solara_fonts/#{file}" } }
62
+ yaml_manager.add_font(family_name, assets)
63
+ end
64
+ end
65
+
66
+ def copy_fonts(destination)
67
+ FontCopier.new.copy(destination, @font_files)
68
+ end
69
+ end
70
+
71
+ class AndroidFontSwitcher
72
+ def initialize(brand_key, font_files)
73
+ @brand_key = brand_key
74
+ @font_files = font_files
75
+ end
76
+
77
+ def switch
78
+ Solara.logger.start_step("Switch Android fonts")
79
+ destination = FilePath.android_project_fonts
80
+ copy_fonts(destination)
81
+ rename_fonts_in_directory(FilePath.android_project_fonts)
82
+ Solara.logger.end_step("Switch Android fonts")
83
+ end
84
+
85
+ private
86
+
87
+ def rename_fonts_in_directory(directory)
88
+ Dir.foreach(directory) do |file|
89
+ next if file == '.' || file == '..' # Skip current and parent directory entries
90
+
91
+ old_path = File.join(directory, file)
92
+ if File.file?(old_path)
93
+ new_name = sanitize_font_name(file)
94
+ new_path = File.join(directory, new_name)
95
+
96
+ # Rename the file if the new name is different
97
+ unless old_path == new_path
98
+ FileUtils.mv(old_path, new_path)
99
+ Solara.logger.debug("Renamed: #{file} -> #{new_name}")
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def sanitize_font_name(font_name)
106
+ # Convert to lowercase
107
+ sanitized_name = font_name.downcase
108
+ # Replace spaces with underscores
109
+ sanitized_name.gsub!('-', '_')
110
+ sanitized_name.gsub!(' ', '_')
111
+ # Remove special characters (except underscores and dots)
112
+ sanitized_name.gsub!(/[^a-z0-9_.]/, '')
113
+ sanitized_name
114
+ end
115
+
116
+ def copy_fonts(destination)
117
+ FontCopier.new.copy(destination, @font_files)
118
+ end
119
+ end
120
+
121
+ class IOSFontSwitcher
122
+ def initialize(brand_key, font_files)
123
+ @brand_key = brand_key
124
+ @font_files = font_files
125
+ end
126
+
127
+ def switch
128
+ Solara.logger.start_step("Switch iOS fonts")
129
+ destination = FilePath.ios_project_fonts
130
+ copy_fonts(destination)
131
+
132
+ font_names = @font_files.map { |file| File.basename(file) }
133
+ info_plist_path = FilePath.info_plist
134
+ manager = IOSPlistManager.new(@project, info_plist_path)
135
+ manager.add_fonts(font_names)
136
+
137
+ Solara.logger.end_step("Switch iOS fonts")
138
+ end
139
+
140
+ private
141
+
142
+ def copy_fonts(destination)
143
+ FontCopier.new.copy(destination, @font_files)
144
+ end
145
+ end
146
+
147
+ class FontCopier
148
+ def copy(destination, font_files)
149
+ FileUtils.mkdir_p(destination)
150
+ return if font_files.empty?
151
+
152
+ FolderCopier.new(FilePath.brand_fonts, destination).copy
153
+ end
154
+ end
@@ -20,15 +20,11 @@ class BrandOnboarder
20
20
  add_to_brands_list
21
21
  end
22
22
 
23
- def add_to_brands_list
24
- BrandsManager.instance.add_brand(@brand_name, @brand_key)
25
- end
26
-
27
23
  def generate_brand_template
28
24
  Solara.logger.debug("Onboarding #{@brand_key} from template.")
29
25
 
30
26
  template_dir = FilePath.template_brands
31
- target_dir = File.join(FilePath.solara, 'brands', @brand_key)
27
+ target_dir = FilePath.brand(@brand_key)
32
28
  config_file = FilePath.template_config
33
29
 
34
30
  generator = ProjectTemplateGenerator.new(template_dir, target_dir, config_file)
@@ -38,9 +34,15 @@ class BrandOnboarder
38
34
  def clone_brand
39
35
  Solara.logger.debug("Cloning #{@clone_brand_key} to #{@brand_key}")
40
36
  source = FilePath.brand(@clone_brand_key)
41
- destination = File.join(FilePath.solara, 'brands', @brand_key)
37
+ destination = FilePath.brand(@brand_key)
38
+
39
+ FileManager.delete_if_exists(destination)
42
40
  FolderCopier.new(source, destination).copy
43
41
  end
44
42
 
43
+ def add_to_brands_list
44
+ BrandsManager.instance.add_brand(@brand_name, @brand_key)
45
+ end
46
+
45
47
  end
46
48
 
@@ -1,204 +1,270 @@
1
+ # Load required files
1
2
  Dir[File.expand_path('scripts/*.rb', __dir__)].each { |file| require_relative file }
2
3
  Dir[File.expand_path('platform/android/*.rb', __dir__)].each { |file| require_relative file }
3
4
  Dir[File.expand_path('platform/ios/*.rb', __dir__)].each { |file| require_relative file }
4
5
  Dir[File.expand_path('platform/flutter/*.rb', __dir__)].each { |file| require_relative file }
5
6
 
6
7
  class BrandSwitcher
7
- def initialize(brand_key, ignore_health_check: false)
8
- Solara.logger.debug("ignore_health_check = #{ignore_health_check}")
9
- @brand_key = brand_key
10
- @ignore_health_check = ignore_health_check
11
- @platform = SolaraSettingsManager.instance.platform
12
- end
8
+ def initialize(brand_key, ignore_health_check: false)
9
+ @brand_key = brand_key
10
+ @ignore_health_check = ignore_health_check
11
+ @platform = SolaraSettingsManager.instance.platform
12
+ @health_checker = HealthChecker.new(@brand_key, @ignore_health_check)
13
+ @artifacts_switcher = ArtifactSwitcher.new(@platform)
14
+ end
15
+
16
+ def start
17
+ Solara.logger.header("Switching to #{@brand_key}")
18
+
19
+ @health_checker.check_health
20
+ BrandsManager.instance.save_current_brand(@brand_key)
21
+ @artifacts_switcher.switch
22
+ switch
23
+ SolaraConfigurator.new.start
24
+
25
+ Solara.logger.success("Switched to #{@brand_key} successfully.")
26
+ end
13
27
 
14
- def self.switch_to_first_brand(ignore_health_check: true)
15
- first_brand_key = BrandsManager.instance.first_brand_key
16
- if first_brand_key.nil?
17
- return
18
- end
19
- BrandSwitcher.new(first_brand_key, ignore_health_check: ignore_health_check).start
28
+ private
29
+
30
+ def switch
31
+ BrandFontSwitcher.new(@brand_key).switch
32
+
33
+ case @platform
34
+ when Platform::Flutter
35
+ IOSBrandSwitcher.new(@brand_key).switch
36
+ AndroidBrandSwitcher.new(@brand_key).switch
37
+ FlutterBrandSwitcher.new(@brand_key).switch
38
+ when Platform::IOS
39
+ IOSBrandSwitcher.new(@brand_key).switch
40
+ when Platform::Android
41
+ AndroidBrandSwitcher.new(@brand_key).switch
42
+ else
43
+ raise ArgumentError, "Invalid platform: #{@platform}"
20
44
  end
45
+ end
46
+ end
21
47
 
22
- def start
23
- Solara.logger.header("Switching to #{@brand_key}")
48
+ class FlutterBrandSwitcher
49
+ def initialize(brand_key)
50
+ @brand_key = brand_key
51
+ @theme_switcher = ThemeSwitcher.new(@brand_key)
52
+ @brand_config_switcher = BrandConfigSwitcher.new(@brand_key)
53
+ end
24
54
 
25
- health_errors = SolaraManager.new.doctor([@brand_key]).select { |issue| issue.type == Issue::ERROR }
26
- unless health_errors.empty?
27
- unless @ignore_health_check
28
- errors_with_index = health_errors.each_with_index.map { |error, index| "#{index + 1}: #{error}" }
29
- raise "Health check completed with errors: \n\n#{errors_with_index.join("\n")}."
30
- end
31
- end
55
+ def switch
56
+ @theme_switcher.switch(Language::Dart)
57
+ @brand_config_switcher.switch(Language::Dart)
58
+ BrandResourcesSwitcher.new(@brand_key).switch(Platform::Flutter)
59
+ end
60
+ end
32
61
 
33
- BrandsManager.instance.save_current_brand(@brand_key)
62
+ class AndroidBrandSwitcher
63
+ def initialize(brand_key)
64
+ @brand_key = brand_key
65
+ @theme_switcher = ThemeSwitcher.new(@brand_key)
66
+ @brand_config_switcher = BrandConfigSwitcher.new(@brand_key)
67
+ end
34
68
 
35
- Solara.logger.start_step("Create artifacts directories")
36
- create_artifacts_dirs
37
- Solara.logger.end_step("Create artifacts directories")
69
+ def switch
70
+ BrandConfigManager.new(@brand_key).generate_android_properties
38
71
 
39
- switch
72
+ config_path = FilePath.android_brand_config(@brand_key)
73
+ config = JSON.parse(File.read(config_path))
40
74
 
41
- SolaraConfigurator.new.start
75
+ GradleSwitcher.new(@brand_key).switch
76
+ AndroidManifestSwitcher.new.switch(config)
77
+ @theme_switcher.switch(Language::Kotlin)
78
+ @brand_config_switcher.switch(Language::Kotlin)
79
+ BrandResourcesSwitcher.new(@brand_key).switch(Platform::Android)
80
+ end
81
+ end
42
82
 
43
- Solara.logger.success("Switched to #{@brand_key} successfully.")
44
- end
83
+ class IOSBrandSwitcher
84
+ def initialize(brand_key)
85
+ @brand_key = brand_key
86
+ @theme_switcher = ThemeSwitcher.new(@brand_key)
87
+ @brand_config_switcher = BrandConfigSwitcher.new(@brand_key)
88
+ end
45
89
 
46
- def create_artifacts_dirs
47
- case @platform
48
- when Platform::Flutter
49
- directories = [
50
- FilePath::flutter_artifacts,
51
- FilePath::android_artifacts,
52
- IOSFilePathManager.instance.artifacts
53
- ]
54
- DirectoryCreator.create_directories(directories, delete_if_exists: true)
55
-
56
- when Platform::IOS
57
- directories = [
58
- IOSFilePathManager.instance.artifacts
59
- ]
60
- DirectoryCreator.create_directories(directories, delete_if_exists: true)
61
-
62
- when Platform::Android
63
- directories = [
64
- FilePath::android_artifacts
65
- ]
66
- DirectoryCreator.create_directories(directories, delete_if_exists: true)
67
- else
68
- raise ArgumentError, "Invalid platform: #{@platform}"
69
- end
70
- end
90
+ def switch
91
+ BrandConfigManager.new(@brand_key).generate_ios_xcconfig
92
+ @theme_switcher.switch(Language::Swift)
93
+ @brand_config_switcher.switch(Language::Swift)
94
+ switch_infoplist
95
+ BrandResourcesSwitcher.new(@brand_key).switch(Platform::IOS)
96
+ switch_xcode_project
97
+ end
71
98
 
72
- def switch
73
- case @platform
74
- when Platform::Flutter
75
- switch_flutter
76
- switch_android
77
- switch_ios
78
-
79
- when Platform::IOS
80
- switch_ios
81
-
82
- when Platform::Android
83
- switch_android
84
- else
85
- raise ArgumentError, "Invalid platform: #{@platform}"
86
- end
87
- end
99
+ private
88
100
 
89
- def generate_theme_kotlin
90
- generate_theme(
91
- 'BrandTheme.kt',
92
- Language::Kotlin,
93
- Platform::Android)
94
- end
101
+ def switch_infoplist
102
+ Solara.logger.start_step("Switch Info.plist")
103
+ project_path = FilePath.xcode_project
104
+ InfoPlistSwitcher.new(project_path, @brand_key).switch
105
+ Solara.logger.end_step("Switch Info.plist")
106
+ end
95
107
 
96
- def generate_theme_swift
97
- generate_theme(
98
- 'BrandTheme.swift',
99
- Language::Swift,
100
- Platform::IOS)
101
- end
108
+ def switch_xcode_project
109
+ Solara.logger.start_step("Switch Xcode project")
110
+ project_path = FilePath.xcode_project
111
+ XcodeProjectSwitcher.new(project_path, @brand_key).switch
112
+ Solara.logger.end_step("Switch Xcode project")
113
+ end
114
+ end
102
115
 
103
- def generate_theme_dart
104
- generate_theme(
105
- 'brand_theme.dart',
106
- Language::Dart,
107
- Platform::Flutter)
108
- end
116
+ class HealthChecker
117
+ def initialize(brand_key, ignore_health_check)
118
+ @brand_key = brand_key
119
+ @ignore_health_check = ignore_health_check
120
+ end
109
121
 
110
- def generate_theme(
111
- name,
112
- language,
113
- platform)
114
- Solara.logger.start_step("Generate #{language} theme for #{platform}")
115
- generator = ThemeGenerator.new(
116
- FilePath.brand_theme(@brand_key),
117
- FilePath.generated_config(name, platform),
118
- language)
119
- generator.generate
120
- Solara.logger.end_step("Generate #{language} theme for #{platform}")
121
- end
122
+ def check_health
123
+ health_errors = SolaraManager.new.doctor([@brand_key]).select { |issue| issue.type == Issue::ERROR }
124
+ return if health_errors.empty?
122
125
 
123
- def generate_app_config_kotlin
124
- generate_brand_config(
125
- 'BrandConfig.kt',
126
- Language::Kotlin,
127
- Platform::Android
128
- )
126
+ unless @ignore_health_check
127
+ errors_with_index = health_errors.each_with_index.map { |error, index| "#{index + 1}: #{error}" }
128
+ raise Issue.error("Health check completed with errors: \n\n#{errors_with_index.join("\n")}.")
129
129
  end
130
+ end
131
+ end
130
132
 
131
- def generate_app_config_swift
132
- generate_brand_config(
133
- 'BrandConfig.swift',
134
- Language::Swift,
135
- Platform::IOS)
136
- end
133
+ class ArtifactSwitcher
134
+ def initialize(platform)
135
+ @platform = platform
136
+ end
137
137
 
138
- def generate_app_config_dart
139
- generate_brand_config(
140
- 'brand_config.dart',
141
- Language::Dart,
142
- Platform::Flutter)
143
- end
138
+ def switch
139
+ Solara.logger.start_step("Switch artifacts directories")
140
+ directories = directories_for_platform
141
+ DirectoryCreator.create_directories(directories, delete_if_exists: true)
142
+ Solara.logger.end_step("Switch artifacts directories")
143
+ end
144
144
 
145
- def generate_brand_config(
146
- name,
147
- language,
148
- platform)
149
- BrandConfigManager.new(@brand_key).generate_brand_config(
150
- name,
151
- language,
152
- platform)
153
- end
145
+ private
154
146
 
155
- def switch_flutter
156
- generate_theme_dart
157
- generate_app_config_dart
158
- BrandResourcesManager.new(@brand_key).update_flutter
147
+ def directories_for_platform
148
+ case @platform
149
+ when Platform::Flutter
150
+ FlutterArtifactSwitcher.new.directories +
151
+ IOSArtifactSwitcher.new.directories +
152
+ AndroidArtifactSwitcher.new.directories
153
+ when Platform::IOS
154
+ IOSArtifactSwitcher.new.directories
155
+ when Platform::Android
156
+ AndroidArtifactSwitcher.new.directories
157
+ else
158
+ raise ArgumentError, "Invalid platform: #{@platform}"
159
159
  end
160
+ end
161
+ end
160
162
 
161
- def switch_android
162
- BrandConfigManager.new(@brand_key).generate_android_properties
163
- config_path = FilePath.android_brand_config(@brand_key)
164
- config = JSON.parse(File.read(config_path))
165
- update_build_gradle
166
- update_manifest(config)
167
- update_strings_xml(config)
168
- BrandResourcesManager.new(@brand_key).update_android
169
- generate_theme_kotlin
170
- generate_app_config_kotlin
171
- end
163
+ class FlutterArtifactSwitcher
164
+ def directories
165
+ [
166
+ FilePath.flutter_lib_artifacts,
167
+ FilePath.flutter_assets_artifacts,
168
+ FilePath.flutter_project_fonts,
169
+ ]
170
+ end
171
+ end
172
172
 
173
- def update_build_gradle
174
- switcher = GradleSwitcher.new(@brand_key)
175
- switcher.update_build_gradle
176
- end
173
+ class IOSArtifactSwitcher
174
+ def directories
175
+ [
176
+ FilePath.ios_project_root_artifacts,
177
+ FilePath.ios_project_assets_artifacts,
178
+ ]
179
+ end
180
+ end
177
181
 
178
- def update_manifest(config)
179
- switcher = AndroidManifestSwitcher.new
180
- switcher.update_manifest(config)
181
- end
182
+ class AndroidArtifactSwitcher
183
+ def directories
184
+ [
185
+ FilePath.android_project_root_artifacts,
186
+ FilePath.android_project_main_artifacts,
187
+ FilePath.android_project_java_artifacts,
188
+ FilePath.android_project_assets_artifacts
189
+ ]
190
+ end
191
+ end
182
192
 
183
- def update_strings_xml(config)
184
- switcher = AndroidStringsSwitcher.new
185
- switcher.update(config)
186
- end
193
+ class ThemeSwitcher
194
+ def initialize(brand_key)
195
+ @brand_key = brand_key
196
+ end
187
197
 
188
- def switch_ios
189
- BrandConfigManager.new(@brand_key).generate_ios_xcconfig
190
- generate_theme_swift
191
- generate_app_config_swift
192
- update_xcode_project
193
- BrandResourcesManager.new(@brand_key).update_ios
198
+ def switch(language)
199
+ case language
200
+ when Language::Dart
201
+ generate_dart
202
+ when Language::Kotlin
203
+ generate_kotlin
204
+ when Language::Swift
205
+ generate_swift
206
+ else
207
+ raise ArgumentError, "Invalid language: #{language}"
194
208
  end
209
+ end
210
+
211
+ def generate_dart
212
+ generate_theme('brand_theme.dart', Language::Dart, Platform::Flutter)
213
+ end
214
+
215
+ def generate_kotlin
216
+ generate_theme('BrandTheme.kt', Language::Kotlin, Platform::Android)
217
+ end
218
+
219
+ def generate_swift
220
+ generate_theme('BrandTheme.swift', Language::Swift, Platform::IOS)
221
+ end
222
+
223
+ private
224
+
225
+ def generate_theme(name, language, platform)
226
+ Solara.logger.start_step("Generate #{name} for #{platform}")
195
227
 
196
- def update_xcode_project
197
- Solara.logger.start_step("Update Xcode project")
198
- project_path = IOSFilePathManager.instance.xcode_project
199
- switcher = XcodeProjectSwitcher.new(project_path, @brand_key)
200
- switcher.switch
201
- Solara.logger.end_step("Update Xcode project")
228
+ theme_manager = ThemeGeneratorManager.new(FilePath.brand_theme(@brand_key))
229
+ theme_manager.generate(language, FilePath.generated_config(name, platform))
230
+
231
+ Solara.logger.end_step("Generate #{name} for #{platform}")
232
+ end
233
+ end
234
+
235
+ class BrandConfigSwitcher
236
+ def initialize(brand_key)
237
+ @brand_key = brand_key
238
+ end
239
+
240
+ def switch(language)
241
+ case language
242
+ when Language::Dart
243
+ generate_dart
244
+ when Language::Kotlin
245
+ generate_kotlin
246
+ when Language::Swift
247
+ generate_swift
248
+ else
249
+ raise ArgumentError, "Invalid language: #{language}"
202
250
  end
251
+ end
252
+
253
+ def generate_dart
254
+ generate_brand_config('brand_config.dart', Language::Dart, Platform::Flutter)
255
+ end
256
+
257
+ def generate_kotlin
258
+ generate_brand_config('BrandConfig.kt', Language::Kotlin, Platform::Android)
259
+ end
260
+
261
+ def generate_swift
262
+ generate_brand_config('BrandConfig.swift', Language::Swift, Platform::IOS)
263
+ end
264
+
265
+ private
203
266
 
267
+ def generate_brand_config(name, language, platform)
268
+ BrandConfigManager.new(@brand_key).generate_brand_config(name, language, platform)
269
+ end
204
270
  end