solara 0.2.0 → 0.2.2

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 +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
@@ -2,10 +2,17 @@ structure:
2
2
  android:
3
3
  type: directory
4
4
  contents:
5
- assets:
6
- type: directory
7
5
  res:
8
6
  type: directory
7
+ contents:
8
+ values:
9
+ type: directory
10
+ contents:
11
+ strings.xml:
12
+ type: file
13
+ validations:
14
+ - type: content_includes
15
+ value: <string name="app_name">
9
16
  android_config.json:
10
17
  type: file
11
18
  validations:
@@ -21,8 +28,6 @@ structure:
21
28
  ios:
22
29
  type: directory
23
30
  contents:
24
- assets:
25
- type: directory
26
31
  ios_config.json:
27
32
  type: file
28
33
  validations:
@@ -35,15 +40,26 @@ structure:
35
40
  - type: valid_json
36
41
  - type: json_schema
37
42
  schema_path: platform/ios/ios_signing.json
43
+ InfoPlist.xcstrings:
44
+ type: file
45
+ validations:
46
+ - type: valid_json
47
+ - type: json_schema
48
+ schema_path: platform/ios/InfoPlist.xcstrings
49
+ xcassets:
50
+ type: directory
51
+ contents:
52
+ AppIcon.appiconset:
53
+ type: directory
38
54
  shared:
39
55
  type: directory
40
56
  contents:
41
- assets:
42
- type: directory
43
57
  brand_config.json:
44
58
  type: file
45
59
  validations:
46
60
  - type: valid_json
61
+ - type: json_schema
62
+ schema_path: platform/shared/brand_config.json
47
63
  theme.json:
48
64
  type: file
49
65
  validations:
@@ -2,10 +2,17 @@ structure:
2
2
  android:
3
3
  type: directory
4
4
  contents:
5
- assets:
6
- type: directory
7
5
  res:
8
6
  type: directory
7
+ contents:
8
+ values:
9
+ type: directory
10
+ contents:
11
+ strings.xml:
12
+ type: file
13
+ validations:
14
+ - type: content_includes
15
+ value: <string name="app_name">
9
16
  android_config.json:
10
17
  type: file
11
18
  validations:
@@ -21,8 +28,6 @@ structure:
21
28
  ios:
22
29
  type: directory
23
30
  contents:
24
- assets:
25
- type: directory
26
31
  ios_config.json:
27
32
  type: file
28
33
  validations:
@@ -35,6 +40,17 @@ structure:
35
40
  - type: valid_json
36
41
  - type: json_schema
37
42
  schema_path: platform/ios/ios_signing.json
43
+ InfoPlist.xcstrings:
44
+ type: file
45
+ validations:
46
+ - type: valid_json
47
+ - type: json_schema
48
+ schema_path: platform/ios/InfoPlist.xcstrings
49
+ xcassets:
50
+ type: directory
51
+ contents:
52
+ AppIcon.appiconset:
53
+ type: directory
38
54
  shared:
39
55
  type: directory
40
56
  contents:
@@ -42,6 +58,8 @@ structure:
42
58
  type: file
43
59
  validations:
44
60
  - type: valid_json
61
+ - type: json_schema
62
+ schema_path: platform/shared/brand_config.json
45
63
  theme.json:
46
64
  type: file
47
65
  validations:
@@ -184,6 +184,7 @@ class BrandConfigGenerator
184
184
  end
185
185
  when 'kotlin'
186
186
  case type
187
+ when 'Bool' then 'Boolean'
187
188
  when 'Array<String>' then 'List<String>'
188
189
  when 'Array<Int>' then 'List<Int>'
189
190
  when 'Array<Double>' then 'List<Double>'
@@ -10,7 +10,7 @@ class BrandConfigManager
10
10
  name,
11
11
  language,
12
12
  platform)
13
- Solara.logger.start_step("Generate #{language} brand config for #{platform}")
13
+ Solara.logger.start_step("Generate #{name} for #{platform}")
14
14
  config = load_config(FilePath.brand_config(@brand_key))
15
15
  add_basic_brand_info(config, platform)
16
16
  config_generator = BrandConfigGenerator.new(
@@ -20,7 +20,7 @@ class BrandConfigManager
20
20
  platform
21
21
  )
22
22
  config_generator.generate
23
- Solara.logger.end_step("Generate #{language} brand config for #{platform}")
23
+ Solara.logger.end_step("Generate #{name} for #{platform}")
24
24
  end
25
25
 
26
26
  def generate_android_properties
@@ -52,7 +52,6 @@ class BrandConfigManager
52
52
  def add_android_info(config, prefix: '')
53
53
  android_config = load_config(FilePath.android_config(@brand_key))
54
54
  config_mappings = {
55
- 'brandName' => 'BrandName',
56
55
  'applicationId' => 'ApplicationId',
57
56
  'versionName' => 'VersionName',
58
57
  'versionCode' => 'VersionCode'
@@ -64,7 +63,6 @@ class BrandConfigManager
64
63
  def add_ios_info(config, prefix: '')
65
64
  ios_config = load_config(FilePath.ios_config(@brand_key))
66
65
  config_mappings = {
67
- 'PRODUCT_NAME' => 'ProductName',
68
66
  'PRODUCT_BUNDLE_IDENTIFIER' => 'BundleIdentifier',
69
67
  'MARKETING_VERSION' => 'MarketingVersion',
70
68
  'BUNDLE_VERSION' => 'BundleVersion'
@@ -19,7 +19,7 @@ class BrandExporter
19
19
  private
20
20
 
21
21
  def export(brand_key, directory)
22
- if BrandsManager.instance.find(brand_key).nil?
22
+ unless BrandsManager.instance.exists(brand_key)
23
23
  Solara.logger.failure("#{brand_key} doesn't exist!")
24
24
  return
25
25
  end
@@ -8,7 +8,6 @@ class BrandImporter
8
8
  configurations_paths.each do |path|
9
9
  import(path)
10
10
  end
11
-
12
11
  end
13
12
 
14
13
  private
@@ -46,14 +45,14 @@ class BrandImporter
46
45
  brand_path = FilePath.brand(brand_key)
47
46
 
48
47
  configurations_json['configurations'].each do |configuration|
49
- file_name = "#{configuration['key']}.json"
48
+ file_name = configuration['key']
50
49
  file_path = find_file_in_subdirectories(brand_path, file_name)
51
50
 
52
51
  # Create or replace the contents of the configuration file
53
52
  if file_path
54
53
  File.write(file_path, JSON.pretty_generate(configuration['content']))
55
54
  else
56
- Solara.logger.failure("File #{file_name} not found in #{brand_path}, ignoring it!")
55
+ Solara.logger.failure("File #{file_name} not found in #{brand_path}, ignoring importing it!")
57
56
  end
58
57
  end
59
58
  end
@@ -1,6 +1,11 @@
1
1
  class BrandOffboarder
2
2
 
3
3
  def offboard(brand_key, confirm: true)
4
+ unless BrandsManager.instance.exists(brand_key)
5
+ Solara.logger.fatal("Brnad key #{brand_key} doesn't exist!")
6
+ return
7
+ end
8
+
4
9
  if confirm
5
10
  Solara.logger.warn("Are you sure you need to offboard #{brand_key} and delete all its configurations? (y/n)")
6
11
  confirmation = STDIN.gets.chomp.downcase
@@ -1,77 +1,150 @@
1
1
  require 'fileutils'
2
- require_relative 'file_manager'
3
- require_relative 'yaml_manager'
4
2
 
5
- class BrandResourcesManager
3
+ class BrandResourcesSwitcher
4
+
6
5
  def initialize(brand_key)
7
- @brand_key = brand_key
6
+ @brand_key = brand_key
7
+ end
8
+
9
+ def switch(platform)
10
+ case platform
11
+ when Platform::Flutter
12
+ FlutterResourcesSwitcher.new(@brand_key).switch
13
+ AndroidResourcesSwitcher.new(@brand_key).switch
14
+ IOSResourcesSwitcher.new(@brand_key).switch
15
+ when Platform::Android
16
+ AndroidResourcesSwitcher.new(@brand_key).switch
17
+ when Platform::IOS
18
+ IOSResourcesSwitcher.new(@brand_key).switch
19
+ else
20
+ raise ArgumentError, "Invalid platform: #{platform}"
21
+ end
22
+ end
23
+ end
24
+
25
+ class IOSResourcesSwitcher
26
+
27
+ def initialize(brand_key)
28
+ @brand_key = brand_key
29
+ end
30
+
31
+ def switch
32
+ Solara.logger.log_step("Switch iOS resources") do
33
+ add_raw_assets_to_asset_catalog
34
+
35
+ copy_directories_not_files(FilePath.ios_brand_xcassets(@brand_key), FilePath.ios_project_assets_artifacts)
36
+
37
+ switch_brand_name
38
+
39
+ copy_solara_assets
40
+
41
+ remove_original_app_icon
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def switch_brand_name
48
+ brand_config_path = FilePath.brand_config(@brand_key)
49
+ brand_config = JSON.parse(File.read(brand_config_path))
50
+ brand_name = brand_config['brandName']
51
+
52
+ manager = InfoPListStringCatalogManager.new(FilePath.project_infoplist_string_catalog)
53
+ source_language = manager.source_language
54
+ data = {
55
+ "CFBundleDisplayName" => {
56
+ source_language => brand_name
57
+ },
58
+ "CFBundleName" => {
59
+ source_language => brand_name
60
+ }
61
+ }
62
+ manager.update(data, can_remove_extra_values: false)
63
+
64
+ Solara.logger.debug("Updated app anme in #{FilePath.project_infoplist_string_catalog} from #{brand_config_path}.")
8
65
  end
9
66
 
10
- require 'fileutils'
11
67
 
12
- def update_ios
13
- Solara.logger.start_step("Update iOS resources")
14
- source = IOSFilePathManager.instance.brand_assets(@brand_key)
15
- destination = IOSFilePathManager.instance.assets_artifacts
16
- FileManager.delete_if_exists(destination)
68
+ def copy_solara_assets
69
+ source = FilePath.ios_brand_assets(@brand_key)
70
+ destination = FilePath.ios_project_artifacts_assets
17
71
 
18
- # Copy images and set the Content.json for each one
19
- add_to_asset_catalog
72
+ return unless File.exist?(source)
20
73
 
21
- # Copy all folders only in source to destination
22
- Dir.glob("#{source}/*").each do |item|
23
- if File.directory?(item)
24
- FileUtils.cp_r(item, destination)
25
- end
74
+ FolderCopier.new(source, destination).copy
75
+ end
76
+
77
+ def add_raw_assets_to_asset_catalog
78
+ source = FilePath.ios_brand_xcassets(@brand_key)
79
+ destination = FilePath.ios_project_assets_artifacts
80
+ asset_manager = XcodeAssetManager.new(destination)
81
+ asset_manager.add(source)
82
+ end
83
+
84
+ def copy_directories_not_files(source, destination)
85
+ Dir.glob("#{source}/*").each do |item|
86
+ if File.directory?(item)
87
+ destination_path = File.join(destination, File.basename(item))
88
+ FolderCopier.new(item, destination_path).copy
26
89
  end
90
+ end
91
+ end
27
92
 
28
- Solara.logger.end_step("Update iOS resources")
93
+ def remove_original_app_icon
94
+ FileManager.delete_if_exists(FilePath.ios_project_original_app_icon)
29
95
  end
96
+ end
30
97
 
31
- def add_to_asset_catalog
32
- source = IOSFilePathManager.instance.brand_assets(@brand_key)
33
- destination = IOSFilePathManager.instance.assets_artifacts
34
- asset_manager = XcodeAssetManager.new(destination)
35
- asset_manager.add(source)
98
+ class AndroidResourcesSwitcher
99
+
100
+ def initialize(brand_key)
101
+ @brand_key = brand_key
36
102
  end
37
103
 
38
- def update_android
39
- Solara.logger.start_step("Update Android resources")
104
+ def switch
105
+ Solara.logger.log_step("Switch Android resources") do
40
106
  FileManager.new.copy_files_recursively(
41
- FilePath.android_brand_res(@brand_key),
42
- FilePath.android_res_artifacts)
107
+ FilePath.android_brand_res(@brand_key),
108
+ FilePath.android_project_main_artifacts
109
+ )
43
110
 
44
- assets_artifacts = File.join(FilePath.android_project_assets, 'artifacts')
45
- FileManager.delete_if_exists(assets_artifacts)
111
+ AndroidStringsSwitcher.new(@brand_key).switch
112
+
113
+ assets_artifacts = FilePath.android_project_assets_artifacts
46
114
 
47
115
  FileManager.new.copy_files_recursively(
48
- FilePath.android_brand_assets(@brand_key),
49
- assets_artifacts)
116
+ FilePath.android_brand_assets(@brand_key),
117
+ assets_artifacts
118
+ )
50
119
 
51
- # Delete the original launcher icons to fix duplicate resources
52
- FileManager.new.delete_folders_by_prefix(FilePath.android_res, 'mipmap')
53
- Solara.logger.end_step("Update Android resources")
120
+ FileManager.new.delete_folders_by_prefix(FilePath.android_project_res, 'mipmap')
121
+ end
54
122
  end
55
123
 
56
- def update_flutter
57
- Solara.logger.start_step("Update Flutter resources")
58
- case SolaraSettingsManager.instance.platform
59
- when Platform::Flutter
60
- YamlManager.new(FilePath.pub_spec_yaml).add_to_nested_array(
61
- 'flutter',
62
- 'assets',
63
- 'assets/artifacts/')
64
-
65
- destination = FilePath.flutter_assets_artifacts
66
- FileManager.delete_if_exists(destination)
67
-
68
- FileManager.new.copy_files_recursively(
69
- FilePath.brand_flutter_assets(@brand_key),
70
- destination)
71
- else
72
- # Nothing
73
- end
124
+ end
125
+
126
+ class FlutterResourcesSwitcher
127
+
128
+ def initialize(brand_key)
129
+ @brand_key = brand_key
130
+ end
74
131
 
75
- Solara.logger.end_step("Update Flutter resources")
132
+ def switch
133
+ return unless Platform.is_flutter
134
+
135
+ Solara.logger.log_step("Switch Flutter resources") do
136
+ YamlManager.new(FilePath.pub_spec_yaml).add_to_nested_array(
137
+ 'flutter',
138
+ 'assets',
139
+ "assets/#{FilePath.artifacts_dir_name}/"
140
+ )
141
+
142
+ destination = FilePath.flutter_assets_artifacts
143
+
144
+ FileManager.new.copy_files_recursively(
145
+ FilePath.brand_flutter_assets(@brand_key),
146
+ destination
147
+ )
148
+ end
76
149
  end
77
- end
150
+ end
@@ -10,12 +10,12 @@ class DirectoryCreator
10
10
  def self.create_directory(dir, delete_if_exists)
11
11
  if Dir.exist?(dir)
12
12
  if delete_if_exists
13
- FileUtils.rm_rf(dir)
13
+ FileManager.delete_if_exists(dir)
14
14
  Solara.logger.debug("🧹 Deleted directory: #{dir}")
15
15
  Dir.mkdir(dir)
16
16
  end
17
17
  else
18
- Dir.mkdir(dir)
18
+ FileUtils.mkdir_p(dir)
19
19
  end
20
20
  Solara.logger.debug("✨ Created directory: #{dir}")
21
21
  end
@@ -2,34 +2,39 @@ require 'find'
2
2
 
3
3
  class FileManager
4
4
  def copy_files_recursively(source_dir, destination_dir)
5
- if Dir.exist?(source_dir)
6
- Dir.glob(File.join(source_dir, '*')).each do |item|
7
- relative_path = Pathname.new(item).relative_path_from(Pathname.new(source_dir)).to_s
8
- destination_path = File.join(destination_dir, relative_path)
9
-
10
- if File.directory?(item)
11
- FileUtils.mkdir_p(destination_path)
12
- FileUtils.cp_r(File.join(item, '.'), destination_path)
13
- else
14
- FileUtils.mkdir_p(File.dirname(destination_path))
15
- FileUtils.cp(item, destination_path)
16
- end
17
-
18
- Solara.logger.debug("🚗 Copied #{relative_path} \n\t↖️From: #{source_dir} \n\t↗️To: #{destination_dir}")
5
+ source_path = Pathname.new(source_dir).expand_path
6
+ destination_path = Pathname.new(destination_dir).expand_path
7
+
8
+ if Dir.exist?(source_path)
9
+ Dir.glob(source_path.join('*')).each do |item|
10
+ relative_path = Pathname.new(item).relative_path_from(source_path).to_s
11
+ destination_item_path = destination_path.join(relative_path)
12
+
13
+ if File.directory?(item)
14
+ FileUtils.mkdir_p(destination_item_path)
15
+ FileUtils.cp_r(item + '/.', destination_item_path) # Ensure to copy contents
16
+ else
17
+ FileUtils.mkdir_p(destination_item_path.dirname) # Create parent directory
18
+ FileUtils.cp(item, destination_item_path)
19
19
  end
20
+
21
+ Solara.logger.debug("🚗 Copied #{relative_path} \n\t↑ From: #{source_path} \n\t↓ To: #{destination_path}")
22
+ end
20
23
  else
21
- Solara.logger.failure("#{source_dir} not found in Solara")
24
+ Solara.logger.failure("#{source_path} not found!")
22
25
  end
23
- end
26
+ end
24
27
 
25
28
  def delete_folders_by_prefix(directory, folder_prefix)
26
29
  # Get a list of all folders in the directory
27
- folders = Dir.entries(directory).select { |entry| File.directory?(File.join(directory, entry)) && entry.start_with?(folder_prefix) }
30
+ folders = Dir.entries(directory).select { |entry|
31
+ File.directory?(File.join(directory, entry)) && entry.start_with?(folder_prefix)
32
+ }
28
33
 
29
34
  # Delete each folder
30
35
  folders.each do |folder|
31
36
  folder_path = File.join(directory, folder)
32
- FileUtils.rm_rf(folder_path)
37
+ FileManager.delete_if_exists(folder_path)
33
38
  Solara.logger.debug("🧹 Deleted folder: #{folder_path}")
34
39
  end
35
40
  end
@@ -63,7 +68,36 @@ class FileManager
63
68
  end
64
69
 
65
70
  def self.find_files_by_name(directory, filename)
66
- Dir.glob(File.join(directory, "**", filename)).to_a
71
+ # Ensure proper path formatting
72
+ directory = File.expand_path(directory)
73
+
74
+ # Generate the search pattern
75
+ pattern = File.join(directory, "**", filename)
76
+
77
+ # Output the pattern for debugging
78
+ Solara.logger.debug("Searching for: #{pattern}")
79
+
80
+ # Find and return matching files
81
+ Dir.glob(pattern).to_a
82
+ end
83
+
84
+ def self.find_files_and_directories(root, name)
85
+ # Ensure proper path formatting
86
+ root = File.expand_path(root)
87
+
88
+ # Generate the search pattern
89
+ pattern = File.join(root, name)
90
+
91
+ # Output the pattern for debugging
92
+ Solara.logger.debug("Searching for: #{pattern}")
93
+
94
+ # Use Dir.glob to find files and directories
95
+ results = Dir.glob(pattern).select { |path| File.file?(path) || File.directory?(path) }
96
+
97
+ # Output results for debugging
98
+ Solara.logger.debug("Found: #{results}")
99
+
100
+ results
67
101
  end
68
102
 
69
103
  def self.get_relative_path(root_dir, sub_dir)