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
@@ -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)