solara 0.2.0 → 0.2.1

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 +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
@@ -0,0 +1,59 @@
1
+ $LOAD_PATH.unshift(File.expand_path(__dir__))
2
+
3
+ class InfoPlistSwitcher
4
+ def initialize(project_path, brand_key)
5
+ @project_path = project_path
6
+ @brand_key = brand_key
7
+ @project = Xcodeproj::Project.open(@project_path)
8
+ end
9
+
10
+ def switch
11
+ copy_string_catalog
12
+ update_info_plist
13
+ @project.save
14
+ Solara.logger.debug("Switched #{FilePath.info_plist} successfully.")
15
+ end
16
+
17
+ private
18
+
19
+ def copy_string_catalog
20
+ # Remove from project before copying
21
+ project_infoplist_string_catalog = FilePath.project_infoplist_string_catalog
22
+ if File.exist?(project_infoplist_string_catalog)
23
+ FileManager.delete_if_exists(project_infoplist_string_catalog)
24
+ Solara.logger.debug("Deleted #{project_infoplist_string_catalog} successfully.")
25
+ end
26
+
27
+ source = FilePath.brand_infoplist_string_catalog(@brand_key)
28
+ destination = FilePath.project_info_plist_directory
29
+ FolderCopier.new(source, destination).copy
30
+
31
+ # Add reference to XcodeProject
32
+ XcodeProjectManager.add_file_near_info_plist(@project, project_infoplist_string_catalog)
33
+ end
34
+
35
+ def update_info_plist
36
+ info_plist_path = FilePath.info_plist
37
+ manager = IOSPlistManager.new(@project, info_plist_path)
38
+ manager.set_info_plist_in_build_settings
39
+
40
+ xcconfig_values = {
41
+ 'CFBUNDLE_DISPLAY_NAME' => "$(CFBUNDLE_DISPLAY_NAME)",
42
+ 'CFBUNDLE_NAME' => "$(CFBUNDLE_NAME)",
43
+ 'PRODUCT_NAME' => "$(PRODUCT_NAME)",
44
+ 'PRODUCT_BUNDLE_IDENTIFIER' => "$(PRODUCT_BUNDLE_IDENTIFIER)",
45
+ 'MARKETING_VERSION' => "$(MARKETING_VERSION)",
46
+ 'BUNDLE_VERSION' => "$(BUNDLE_VERSION)"
47
+ }
48
+
49
+ info_plist = Xcodeproj::Plist.read_from_path(info_plist_path)
50
+ info_plist[InfoPListKey::BUNDLE_DISPLAY_NAME] = xcconfig_values['CFBUNDLE_DISPLAY_NAME']
51
+ info_plist[InfoPListKey::BUNDLE_NAME] = xcconfig_values['CFBUNDLE_NAME']
52
+ info_plist['CFBundleIdentifier'] = xcconfig_values['PRODUCT_BUNDLE_IDENTIFIER']
53
+ info_plist['CFBundleShortVersionString'] = xcconfig_values['MARKETING_VERSION']
54
+ info_plist['CFBundleVersion'] = xcconfig_values['BUNDLE_VERSION']
55
+
56
+ Xcodeproj::Plist.write_to_path(info_plist, info_plist_path)
57
+ end
58
+
59
+ end
@@ -1,4 +1,5 @@
1
1
  require 'xcodeproj'
2
+ require 'plist'
2
3
 
3
4
  class IOSPlistManager
4
5
  def initialize(project, info_plist_path)
@@ -6,31 +7,20 @@ class IOSPlistManager
6
7
  @info_plist_path = info_plist_path
7
8
  end
8
9
 
9
- def create_and_add_info_plist
10
- # add_info_plist_to_project
11
- set_info_plist_in_build_settings
12
- save_project
13
- end
14
-
15
- private
16
-
17
- def add_info_plist_to_project
18
- file_ref = @project.files.select { |f| f.path == @info_plist_path }.first
19
- if file_ref
20
- Solara.logger.debug("Info.plist file reference already exists in the project. Skipping this step.")
21
- else
22
- file_ref = XcodeProjectManager.new.add_single_file_to_group(@project, @project.main_group, @info_plist_path)
23
- Solara.logger.debug("Info.plist file created. file_ref = #{file_ref}")
24
- end
25
- end
26
-
27
10
  def set_info_plist_in_build_settings
28
- path = FileManager.get_relative_path(IOSFilePathManager.instance.xcode_project_directory, @info_plist_path)
11
+ path = FileManager.get_relative_path(FilePath.xcode_project_directory, @info_plist_path)
29
12
  main_target.build_configurations.each do |config|
30
13
  config.build_settings['INFOPLIST_FILE'] = path
31
14
  end
32
15
  end
33
16
 
17
+ def add_fonts(font_names)
18
+ font_manager = PlistFontManager.new(FilePath.info_plist)
19
+ font_manager.add_fonts(font_names)
20
+ end
21
+
22
+ private
23
+
34
24
  def save_project
35
25
  @project.save
36
26
  end
@@ -39,4 +29,5 @@ class IOSPlistManager
39
29
  @project.targets.first
40
30
  end
41
31
 
42
- end
32
+ end
33
+
@@ -0,0 +1,33 @@
1
+ class PlistFontManager
2
+ def initialize(plist_path)
3
+ @plist_path = plist_path
4
+ load_plist
5
+ end
6
+
7
+ def load_plist
8
+ @plist = Plist.parse_xml(@plist_path)
9
+ @plist['UIAppFonts'] ||= []
10
+ end
11
+
12
+ def add_fonts(font_names)
13
+ font_names.each do |font_name|
14
+ add_font(font_name)
15
+ end
16
+ end
17
+
18
+ def add_font(font_name)
19
+ unless @plist['UIAppFonts'].include?(font_name)
20
+ @plist['UIAppFonts'] << font_name
21
+ save_plist
22
+ Solara.logger.debug("#{font_name} added to UIAppFonts.")
23
+ else
24
+ Solara.logger.debug("#{font_name} already exists in UIAppFonts.")
25
+ end
26
+ end
27
+
28
+ def save_plist
29
+ File.open(@plist_path, 'w') do |file|
30
+ file.write(Plist::Emit.dump(@plist))
31
+ end
32
+ end
33
+ end
@@ -6,10 +6,10 @@ class XcconfigGenerator
6
6
 
7
7
  def generate
8
8
  Solara.logger.start_step("Generate Brand.xcconfig for iOS")
9
- destination = IOSFilePathManager.instance.brand_xcconfig
9
+ destination = FilePath.brand_xcconfig
10
10
  content = generate_xcconfig_content
11
11
  File.write(destination, content)
12
- Solara.logger.debug("🎉 Generated #{IOSFilePathManager.instance.brand_xcconfig}. Content below ⬇️")
12
+ Solara.logger.debug("🎉 Generated #{FilePath.brand_xcconfig}. Content below ⬇️")
13
13
  Solara.logger.debug("--------------\n#{content}--------------")
14
14
  Solara.logger.end_step("Generate Brand.xcconfig for iOS")
15
15
  end
@@ -18,7 +18,10 @@ class XcconfigGenerator
18
18
 
19
19
  def generate_xcconfig_content
20
20
  content = <<~XCCONFIG
21
- ASSETCATALOG_COMPILER_APPICON_NAME = Artifacts/AppIcon
21
+ APPICON_NAME = AppIcon
22
+ PRODUCT_NAME = #{get_value_of(InfoPListKey::BUNDLE_DISPLAY_NAME)}
23
+ CFBUNDLE_DISPLAY_NAME = #{get_value_of(InfoPListKey::BUNDLE_DISPLAY_NAME)}
24
+ CFBUNDLE_NAME = #{get_value_of(InfoPListKey::BUNDLE_NAME)}
22
25
  #{load_config.map { |key, value| "#{key.upcase} = #{value}" }.join("\n")}
23
26
  XCCONFIG
24
27
 
@@ -37,6 +40,15 @@ class XcconfigGenerator
37
40
  end
38
41
  end
39
42
 
43
+ def get_value_of(key)
44
+ infoplist_value = InfoPListStringCatalogManager.new(FilePath.brand_infoplist_string_catalog(@brand_key)).get(key)
45
+ return infoplist_value if !infoplist_value && !infoplist_value.empty?
46
+
47
+ brand_config_path = FilePath.brand_config(@brand_key)
48
+ brand_config = JSON.parse(File.read(brand_config_path))
49
+ brand_config['brandName']
50
+ end
51
+
40
52
  def load_config
41
53
  config_path = FilePath.ios_config(@brand_key)
42
54
  JSON.parse(File.read(config_path))
@@ -6,11 +6,10 @@ class XcodeAssetManager
6
6
  @asset_catalog_path = asset_catalog_path
7
7
  end
8
8
 
9
-
10
9
  def add(source)
11
10
  # Fetches only files in the specified source directory
12
11
  Dir.glob(File.join(source, '*.{png,jpg,jpeg,svg,heic,pdf}')).each do |file_path|
13
- if File.file?(file_path) # Ensure it's a file and not a directory
12
+ if File.file?(file_path) # Ensure it's a file and not a directory
14
13
  filename_without_extension = File.basename(file_path, File.extname(file_path))
15
14
  add_image(filename_without_extension, file_path, '1x')
16
15
  end
@@ -51,6 +50,6 @@ class XcodeAssetManager
51
50
  # Write the updated Contents.json
52
51
  File.write(contents_json_path, JSON.pretty_generate(contents))
53
52
 
54
- puts "Image '#{image_name}' added successfully at scale #{scale}."
53
+ Solara.logger.debug("XcodeAssetManager: Image '#{image_name}' added successfully at scale #{scale}.")
55
54
  end
56
55
  end
@@ -64,7 +64,6 @@ class XcodeProjectManager
64
64
 
65
65
  Solara.logger.debug("Base XCConfig files have been set for all build configurations.")
66
66
  end
67
-
68
67
  def self.set_xcconfig(project, config, xcconfig)
69
68
  # Find the existing file reference or create a new one if it doesn't exist
70
69
  file_reference = project.reference_for_path(xcconfig[:path])
@@ -79,4 +78,84 @@ class XcodeProjectManager
79
78
  end
80
79
  end
81
80
 
81
+ def add_file_to_root(project, file_path)
82
+ Solara.logger.debug("Adding file to root: #{file_path}")
83
+
84
+ root_group = project.main_group
85
+ file_name = File.basename(file_path, File.extname(file_path))
86
+
87
+ existing_file = root_group.files.find { |f| File.basename(f.path, File.extname(f.path))&.downcase == file_name.downcase }
88
+
89
+ if existing_file
90
+ Solara.logger.debug("Ignoring file: #{file_path} (Existing file reference: #{existing_file.path})")
91
+ return nil
92
+ else
93
+ file_reference = root_group.new_file(file_path)
94
+ Solara.logger.debug("Added new file to root: #{file_path} (File reference: #{file_reference.uuid})")
95
+
96
+ # Add the file to the project's main target if it's a source file
97
+ if %w[.swift .m .mm .c .cpp].include?(File.extname(file_path).downcase)
98
+ target = project.targets.first
99
+ target.add_file_references([file_reference])
100
+ Solara.logger.debug(" Added to target: #{target.name}")
101
+ end
102
+
103
+ file_reference
104
+ end
105
+ end
106
+
107
+ def self.add_file_near_info_plist(project, file_path)
108
+ Solara.logger.debug("Adding file near Info.plist: #{file_path}")
109
+
110
+ # Find the Info.plist file path
111
+ info_plist_path = project.targets.first.build_configurations.first.build_settings['INFOPLIST_FILE']
112
+ return Solara.logger.warn("No Info.plist file found for the target") unless info_plist_path
113
+
114
+ # Get the directory of the Info.plist file
115
+ info_plist_dir = File.dirname(info_plist_path)
116
+
117
+ target_file_path = File.basename(file_path)
118
+ infoplist_group = info_plist_dir === '.' ? project.main_group : find_group_by_path(project, [info_plist_dir])
119
+
120
+ # Check if a file with the same name already exists in the target directory
121
+ existing_file = infoplist_group.files.find { |f| f.path == target_file_path }
122
+
123
+ if existing_file
124
+ Solara.logger.debug("Ignoring file: #{file_path} (Existing file reference: #{existing_file.path})")
125
+ return nil
126
+ else
127
+ # Add the file to the main group, which corresponds to the directory of Info.plist
128
+ file_reference = infoplist_group.new_file(target_file_path)
129
+ Solara.logger.debug("Added new file near Info.plist: #{file_path} (File reference: #{file_reference.uuid})")
130
+
131
+ # Add the file to the project's main target as a resource
132
+ target = project.targets.first
133
+
134
+ # Create a new build file
135
+ build_file = project.new(Xcodeproj::Project::Object::PBXBuildFile)
136
+ build_file.file_ref = file_reference
137
+
138
+ # Add the build file to the target's resources build phase
139
+ resources_build_phase = target.resources_build_phase
140
+ resources_build_phase.add_file_reference(file_reference)
141
+
142
+ Solara.logger.debug(" Added to target: #{target.name}")
143
+ Solara.logger.debug(" Added to PBXBuildFile section as a resource")
144
+
145
+ file_reference
146
+ end
147
+ end
148
+ def self.find_group_by_path(project, paths)
149
+ current_group = project.main_group
150
+
151
+ paths.each do |path|
152
+ current_group = current_group.children.find { |child|
153
+ child.is_a?(Xcodeproj::Project::Object::PBXGroup) && child.path == path
154
+ }
155
+ return nil unless current_group
156
+ end
157
+ current_group
158
+ end
159
+
160
+
82
161
  end
@@ -11,11 +11,10 @@ class XcodeProjectSwitcher
11
11
 
12
12
  def switch
13
13
  update_xcode_target_settings
14
- update_info_plist
15
14
  add_artifacts_group
16
15
  update_debug_and_release_xcconfig
17
16
  @project.save
18
- Solara.logger.debug("Updated #{@project_path} to use the values of #{IOSFilePathManager.instance.brand_xcconfig}")
17
+ Solara.logger.debug("Switched #{@project_path} Successfully.")
19
18
  end
20
19
 
21
20
  private
@@ -23,8 +22,9 @@ class XcodeProjectSwitcher
23
22
  def update_xcode_target_settings
24
23
  @target.build_configurations.each do |config|
25
24
  config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = '$(PRODUCT_BUNDLE_IDENTIFIER)'
26
- config.build_settings['PRODUCT_NAME'] = '$(PRODUCT_NAME)'
27
25
  config.build_settings['MARKETING_VERSION'] = '$(MARKETING_VERSION)'
26
+ config.build_settings['ASSETCATALOG_COMPILER_APPICON_NAME'] = '$(APPICON_NAME)'
27
+ config.build_settings['PRODUCT_NAME'] = '$(PRODUCT_NAME)'
28
28
 
29
29
  # We need to apply code signing only if the user has provided its config
30
30
  path = FilePath.brand_signing(@brand_key, Platform::IOS)
@@ -47,30 +47,9 @@ class XcodeProjectSwitcher
47
47
  end
48
48
  end
49
49
 
50
- def update_info_plist
51
- info_plist_path = IOSFilePathManager.instance.info_plist
52
- manager = IOSPlistManager.new(@project, info_plist_path)
53
- manager.create_and_add_info_plist
54
-
55
- xcconfig_values = {
56
- 'PRODUCT_NAME' => "$(PRODUCT_NAME)",
57
- 'PRODUCT_BUNDLE_IDENTIFIER' => "$(PRODUCT_BUNDLE_IDENTIFIER)",
58
- 'MARKETING_VERSION' => "$(MARKETING_VERSION)",
59
- 'BUNDLE_VERSION' => "$(BUNDLE_VERSION)"
60
- }
61
-
62
- info_plist = Xcodeproj::Plist.read_from_path(info_plist_path)
63
- info_plist['CFBundleDisplayName'] = xcconfig_values['PRODUCT_NAME']
64
- info_plist['CFBundleIdentifier'] = xcconfig_values['PRODUCT_BUNDLE_IDENTIFIER']
65
- info_plist['CFBundleShortVersionString'] = xcconfig_values['MARKETING_VERSION']
66
- info_plist['CFBundleVersion'] = xcconfig_values['BUNDLE_VERSION']
67
-
68
- Xcodeproj::Plist.write_to_path(info_plist, info_plist_path)
69
- end
70
-
71
50
  def update_debug_and_release_xcconfig
72
- debug_xcconfig_path = IOSFilePathManager.instance.app_xcconfig('Debug.xcconfig')
73
- release_xcconfig_path = IOSFilePathManager.instance.app_xcconfig('Release.xcconfig')
51
+ debug_xcconfig_path = FilePath.app_xcconfig('Debug.xcconfig')
52
+ release_xcconfig_path = FilePath.app_xcconfig('Release.xcconfig')
74
53
 
75
54
  create_xcconfigs_and_add_to_project(debug_xcconfig_path, release_xcconfig_path)
76
55
  set_base_xcconfigs(debug_xcconfig_path, release_xcconfig_path)
@@ -78,7 +57,7 @@ class XcodeProjectSwitcher
78
57
 
79
58
  def create_xcconfigs_and_add_to_project(debug_xcconfig_path, release_xcconfig_path)
80
59
  FileManager.create_files_if_not_exist([debug_xcconfig_path, release_xcconfig_path])
81
- base_xcconfig_name = 'Artifacts/Brand.xcconfig'
60
+ base_xcconfig_name = "#{FilePath.artifacts_dir_name_ios}/Brand.xcconfig"
82
61
 
83
62
  case @platform
84
63
  when Platform::Flutter
@@ -87,7 +66,7 @@ class XcodeProjectSwitcher
87
66
  group_name = 'XCConfig'
88
67
  config_group = @project.groups.find { |group| group.name == group_name }
89
68
  config_group = @project.new_group(group_name) if config_group.nil?
90
- add_files_to_group(config_group, IOSFilePathManager.instance.app_xcconfig_directory)
69
+ add_files_to_group(config_group, FilePath.app_xcconfig_directory)
91
70
  else
92
71
  raise ArgumentError, "Invalid platform: #{@platform}"
93
72
  end
@@ -108,16 +87,18 @@ class XcodeProjectSwitcher
108
87
  end
109
88
 
110
89
  def add_artifacts_group
90
+ artifacts_dir_name = FilePath.artifacts_dir_name_ios
91
+
111
92
  case @platform
112
93
  when Platform::Flutter
113
94
  flutter_group = @project.groups.find { |group| group.name == 'Flutter' }
114
- artifacts_group = flutter_group.groups.find { |group| group.name == 'Artifacts' }
115
- artifacts_group = flutter_group.new_group("Artifacts") if artifacts_group.nil?
116
- add_files_to_group(artifacts_group, IOSFilePathManager.instance.artifacts)
95
+ artifacts_group = flutter_group.groups.find { |group| group.name == artifacts_dir_name }
96
+ artifacts_group = flutter_group.new_group(artifacts_dir_name) if artifacts_group.nil?
97
+ add_files_to_group(artifacts_group, FilePath.ios_project_root_artifacts)
117
98
  when Platform::IOS
118
- artifacts_group = @project.groups.find { |group| group.name == 'Artifacts' }
119
- artifacts_group = @project.new_group("Artifacts") if artifacts_group.nil?
120
- add_files_to_group(artifacts_group, IOSFilePathManager.instance.artifacts)
99
+ artifacts_group = @project.groups.find { |group| group.name == artifacts_dir_name }
100
+ artifacts_group = @project.new_group(artifacts_dir_name) if artifacts_group.nil?
101
+ add_files_to_group(artifacts_group, FilePath.ios_project_root_artifacts)
121
102
  else
122
103
  raise ArgumentError, "Invalid platform: #{@platform}"
123
104
  end
@@ -24,6 +24,10 @@ class SolaraLogger
24
24
  set_default_format
25
25
  end
26
26
 
27
+ def reset_steps
28
+ @step_count = 0
29
+ end
30
+
27
31
  def verbose=(value)
28
32
  @verbose = value
29
33
  @logger.level = @verbose ? Logger::DEBUG : Logger::INFO
@@ -43,6 +47,12 @@ class SolaraLogger
43
47
  line
44
48
  end
45
49
 
50
+ def log_step(step_name)
51
+ start_step(step_name)
52
+ yield
53
+ end_step(step_name)
54
+ end
55
+
46
56
  def title(message)
47
57
  @logger.info(message.green)
48
58
  line
@@ -6,7 +6,11 @@ require 'json'
6
6
  class SolaraSettingsManager
7
7
  include Singleton
8
8
 
9
- attr_accessor :root, :project_root
9
+ attr_accessor :root, :project_root, :environment
10
+
11
+ def initialize
12
+ @environment = SolaraEnvironment::Production
13
+ end
10
14
 
11
15
  def platform
12
16
  settings['platform']
@@ -28,6 +32,10 @@ class SolaraSettingsManager
28
32
  save(json)
29
33
  end
30
34
 
35
+ def is_test_environment
36
+ @environment === 'test'
37
+ end
38
+
31
39
  private
32
40
 
33
41
  def settings
@@ -70,4 +78,21 @@ def init(platform)
70
78
  unless Platform.all.include?(platform)
71
79
  raise ArgumentError, "Invalid platform. Please use one of: #{Platform.all.join(', ')}"
72
80
  end
81
+ end
82
+
83
+ module SolaraEnvironment
84
+ Production = 'production'
85
+ Test = 'test'
86
+
87
+ def self.all
88
+ [Production, Test]
89
+ end
90
+
91
+ def self.is_production
92
+ SolaraSettingsManager.instance.environment.downcase == Production.downcase
93
+ end
94
+
95
+ def self.is_test
96
+ SolaraSettingsManager.instance.environment.downcase == Test.downcase
97
+ end
73
98
  end
@@ -3,7 +3,7 @@ require 'rexml/document'
3
3
  class StringsXmlManager
4
4
  def initialize(file_path)
5
5
  @file_path = file_path
6
- @xml_content = File.read(@file_path)
6
+ @xml_content = File.read(@file_path, encoding: 'UTF-8')
7
7
  @doc = REXML::Document.new(@xml_content)
8
8
  end
9
9
 
@@ -11,7 +11,22 @@ class StringsXmlManager
11
11
  app_name_element = @doc.elements['resources/string[@name="app_name"]']
12
12
  app_name_element.remove if app_name_element
13
13
  save_changes
14
- Solara.logger.debug("Removed app_name from #{@file_path} to avoid duplication with artifacts/strings.xml.")
14
+ Solara.logger.debug("Removed app_name from #{@file_path} to avoid duplication with #{FilePath.artifacts_dir_name}/strings.xml.")
15
+ end
16
+
17
+ def update_string_value(string_name, new_value)
18
+ string_element = @doc.elements["resources/string[@name=\"#{string_name}\"]"]
19
+ if string_element
20
+ string_element.text = new_value
21
+ save_changes
22
+ Solara.logger.debug("Updated string '#{string_name}' to '#{new_value}' in #{@file_path}.")
23
+ else
24
+ Solara.logger.warn("String '#{string_name}' not found in #{@file_path}. Update failed.")
25
+ end
26
+ end
27
+
28
+ def get_value(string_name)
29
+ @doc.elements["resources/string[@name=\"#{string_name}\"]"].text
15
30
  end
16
31
 
17
32
  private