solara 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +1 -3
  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: dea7da41ec79265551adc948a5586af994164b9c04ef3576b2c37b9fab2f108f
4
+ data.tar.gz: 31352f627b65fa267a082095bfec2346b03173a944e2c967974107c0c30f7e9b
5
5
  SHA512:
6
- metadata.gz: 7ae71b89f2009fb46d5ec2f50baaba4b759a38b75a2bd1040117ef87263c5bfbb97b38aba44f2b911b5711d60a9c72109a91cb8a65841a0779b318d522fa271a
7
- data.tar.gz: 9c204a83bb994794f1afebbd793c73901596bf4cebae5ff38ed0ae844cc17bc6cb289232af14fa8c75520f5e0c5318866477bdd1a19ac3e62d073cd71f3f8144
6
+ metadata.gz: a4623541490f240d2ffacbb682d8b9388058633af6e40d548cd998cad186f87addd4efc4675e2257d4c90102f42ce7589e3c90d400f84775d8ca25f1af201f5b
7
+ data.tar.gz: c5158cd2c02abd104155d482c3e59e8c7a79b4289eb4316a5c9ee7de101892b6ae1d1341c247b97a38611041add484a4abaaf9d414c4380fa7cebbf12ecbbf35
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