solara 0.1.0

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 (175) hide show
  1. checksums.yaml +7 -0
  2. data/bin/solara +18 -0
  3. data/solara/lib/.DS_Store +0 -0
  4. data/solara/lib/core/.DS_Store +0 -0
  5. data/solara/lib/core/aliases/alias_generator.rb +128 -0
  6. data/solara/lib/core/aliases/alias_generator_manager.rb +28 -0
  7. data/solara/lib/core/aliases/solara_terminal_setup.rb +103 -0
  8. data/solara/lib/core/brands/brand_onboarder.rb +46 -0
  9. data/solara/lib/core/brands/brand_switcher.rb +204 -0
  10. data/solara/lib/core/brands/brands_manager.rb +154 -0
  11. data/solara/lib/core/dashboard/.DS_Store +0 -0
  12. data/solara/lib/core/dashboard/brand/.DS_Store +0 -0
  13. data/solara/lib/core/dashboard/brand/BrandDetail.js +11 -0
  14. data/solara/lib/core/dashboard/brand/BrandDetailController.js +361 -0
  15. data/solara/lib/core/dashboard/brand/BrandDetailModel.js +155 -0
  16. data/solara/lib/core/dashboard/brand/BrandDetailView.js +245 -0
  17. data/solara/lib/core/dashboard/brand/brand.html +477 -0
  18. data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +123 -0
  19. data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +260 -0
  20. data/solara/lib/core/dashboard/brands/Brands.js +10 -0
  21. data/solara/lib/core/dashboard/brands/BrandsController.js +155 -0
  22. data/solara/lib/core/dashboard/brands/BrandsModel.js +136 -0
  23. data/solara/lib/core/dashboard/brands/BrandsView.js +136 -0
  24. data/solara/lib/core/dashboard/brands/brands.html +345 -0
  25. data/solara/lib/core/dashboard/component/AddFieldSheet.js +212 -0
  26. data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +128 -0
  27. data/solara/lib/core/dashboard/component/BrandOptionsBottomSheet.js +130 -0
  28. data/solara/lib/core/dashboard/component/ConfirmationDialog.js +103 -0
  29. data/solara/lib/core/dashboard/component/MessageBottomSheet.js +80 -0
  30. data/solara/lib/core/dashboard/component/OnboardBrandBottomSheet.js +214 -0
  31. data/solara/lib/core/dashboard/dashboard_manager.rb +19 -0
  32. data/solara/lib/core/dashboard/dashboard_server.rb +132 -0
  33. data/solara/lib/core/dashboard/handler/base_handler.rb +25 -0
  34. data/solara/lib/core/dashboard/handler/brand_alisases_handler.rb +33 -0
  35. data/solara/lib/core/dashboard/handler/brand_configurations_handler.rb +18 -0
  36. data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +73 -0
  37. data/solara/lib/core/dashboard/handler/brand_icon_handler.rb +20 -0
  38. data/solara/lib/core/dashboard/handler/brand_section_handler.rb +20 -0
  39. data/solara/lib/core/dashboard/handler/brands_handler.rb +14 -0
  40. data/solara/lib/core/dashboard/handler/current_brand_handler.rb +18 -0
  41. data/solara/lib/core/dashboard/handler/doctor_handler.rb +39 -0
  42. data/solara/lib/core/dashboard/handler/edit_section_handler.rb +55 -0
  43. data/solara/lib/core/dashboard/handler/offboard_brand_handler.rb +34 -0
  44. data/solara/lib/core/dashboard/handler/onboard_brand_handler.rb +53 -0
  45. data/solara/lib/core/dashboard/handler/redirect_handler.rb +12 -0
  46. data/solara/lib/core/dashboard/handler/switch_handler.rb +25 -0
  47. data/solara/lib/core/dashboard/index.html +36 -0
  48. data/solara/lib/core/dashboard/local.html +41 -0
  49. data/solara/lib/core/dashboard/res/favicon/android-chrome-192x192.png +0 -0
  50. data/solara/lib/core/dashboard/res/favicon/android-chrome-512x512.png +0 -0
  51. data/solara/lib/core/dashboard/res/favicon/apple-touch-icon.png +0 -0
  52. data/solara/lib/core/dashboard/res/favicon/favicon-16x16.png +0 -0
  53. data/solara/lib/core/dashboard/res/favicon/favicon-32x32.png +0 -0
  54. data/solara/lib/core/dashboard/res/favicon/favicon.ico +0 -0
  55. data/solara/lib/core/dashboard/res/favicon/site.webmanifest +1 -0
  56. data/solara/lib/core/dashboard/solara.png +0 -0
  57. data/solara/lib/core/doctor/brand_doctor.rb +94 -0
  58. data/solara/lib/core/doctor/doctor_manager.rb +35 -0
  59. data/solara/lib/core/doctor/project_doctor.rb +8 -0
  60. data/solara/lib/core/doctor/schema/brand_configurations.json +60 -0
  61. data/solara/lib/core/doctor/schema/platform/android/android_config.json +23 -0
  62. data/solara/lib/core/doctor/schema/platform/android/android_signing.json +23 -0
  63. data/solara/lib/core/doctor/schema/platform/ios/ios_config.json +27 -0
  64. data/solara/lib/core/doctor/schema/platform/ios/ios_signing.json +27 -0
  65. data/solara/lib/core/doctor/schema/platform/shared/theme.json +48 -0
  66. data/solara/lib/core/doctor/validator/brand_settings_validator.rb +55 -0
  67. data/solara/lib/core/doctor/validator/brand_settings_validator_manager.rb +82 -0
  68. data/solara/lib/core/doctor/validator/directory_structure_validator.rb +38 -0
  69. data/solara/lib/core/doctor/validator/file_structure_validator.rb +37 -0
  70. data/solara/lib/core/doctor/validator/json_file_validator.rb +21 -0
  71. data/solara/lib/core/doctor/validator/json_schema_validator.rb +32 -0
  72. data/solara/lib/core/doctor/validator/project_filesystem_validator.rb +70 -0
  73. data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +51 -0
  74. data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +53 -0
  75. data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +51 -0
  76. data/solara/lib/core/doctor/validator/template/template_validator.rb +108 -0
  77. data/solara/lib/core/doctor/validator/validation_strategy.rb +7 -0
  78. data/solara/lib/core/scripts/brand_config_generator.rb +245 -0
  79. data/solara/lib/core/scripts/brand_config_manager.rb +90 -0
  80. data/solara/lib/core/scripts/brand_exporter.rb +38 -0
  81. data/solara/lib/core/scripts/brand_importer.rb +84 -0
  82. data/solara/lib/core/scripts/brand_offboarder.rb +19 -0
  83. data/solara/lib/core/scripts/brand_resources_manager.rb +77 -0
  84. data/solara/lib/core/scripts/directory_creator.rb +22 -0
  85. data/solara/lib/core/scripts/file_manager.rb +90 -0
  86. data/solara/lib/core/scripts/file_path.rb +327 -0
  87. data/solara/lib/core/scripts/folder_copier.rb +41 -0
  88. data/solara/lib/core/scripts/gitignore_manager.rb +54 -0
  89. data/solara/lib/core/scripts/interactive_file_system_validator.rb +110 -0
  90. data/solara/lib/core/scripts/platform/android/android_manifest_switcher.rb +24 -0
  91. data/solara/lib/core/scripts/platform/android/android_strings_switcher.rb +39 -0
  92. data/solara/lib/core/scripts/platform/android/gradle_switcher.rb +233 -0
  93. data/solara/lib/core/scripts/platform/android/properties_generator.rb +31 -0
  94. data/solara/lib/core/scripts/platform/ios/ios_file_path_manager.rb +109 -0
  95. data/solara/lib/core/scripts/platform/ios/ios_plist_manager.rb +42 -0
  96. data/solara/lib/core/scripts/platform/ios/xcconfig_generator.rb +44 -0
  97. data/solara/lib/core/scripts/platform/ios/xcode_asset_manager.rb +56 -0
  98. data/solara/lib/core/scripts/platform/ios/xcode_project_manager.rb +82 -0
  99. data/solara/lib/core/scripts/platform/ios/xcode_project_switcher.rb +130 -0
  100. data/solara/lib/core/scripts/project_settings_manager.rb +39 -0
  101. data/solara/lib/core/scripts/solara_logger.rb +103 -0
  102. data/solara/lib/core/scripts/solara_settings_manager.rb +73 -0
  103. data/solara/lib/core/scripts/solara_status_manager.rb +55 -0
  104. data/solara/lib/core/scripts/solara_version_manager.rb +42 -0
  105. data/solara/lib/core/scripts/strings_xml_manager.rb +22 -0
  106. data/solara/lib/core/scripts/terminal_input_manager.rb +22 -0
  107. data/solara/lib/core/scripts/theme_generator.rb +250 -0
  108. data/solara/lib/core/scripts/yaml_manager.rb +72 -0
  109. data/solara/lib/core/solara_configurator.rb +15 -0
  110. data/solara/lib/core/template/brands/android/android_config.json +8 -0
  111. data/solara/lib/core/template/brands/android/android_signing.json +6 -0
  112. data/solara/lib/core/template/brands/android/res/.DS_Store +0 -0
  113. data/solara/lib/core/template/brands/android/res/mipmap-hdpi/ic_launcher.png +0 -0
  114. data/solara/lib/core/template/brands/android/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  115. data/solara/lib/core/template/brands/android/res/mipmap-mdpi/ic_launcher.png +0 -0
  116. data/solara/lib/core/template/brands/android/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  117. data/solara/lib/core/template/brands/android/res/mipmap-xhdpi/ic_launcher.png +0 -0
  118. data/solara/lib/core/template/brands/android/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  119. data/solara/lib/core/template/brands/android/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  120. data/solara/lib/core/template/brands/android/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  121. data/solara/lib/core/template/brands/android/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  122. data/solara/lib/core/template/brands/android/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  123. data/solara/lib/core/template/brands/brands.json +4 -0
  124. data/solara/lib/core/template/brands/ios/assets/.DS_Store +0 -0
  125. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/100.png +0 -0
  126. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/102.png +0 -0
  127. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/1024.png +0 -0
  128. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/114.png +0 -0
  129. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/120.png +0 -0
  130. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/128.png +0 -0
  131. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/144.png +0 -0
  132. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/152.png +0 -0
  133. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/16.png +0 -0
  134. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/167.png +0 -0
  135. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/172.png +0 -0
  136. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/180.png +0 -0
  137. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/196.png +0 -0
  138. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/20.png +0 -0
  139. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/216.png +0 -0
  140. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/256.png +0 -0
  141. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/29.png +0 -0
  142. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/32.png +0 -0
  143. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/40.png +0 -0
  144. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/48.png +0 -0
  145. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/50.png +0 -0
  146. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/512.png +0 -0
  147. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/55.png +0 -0
  148. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/57.png +0 -0
  149. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/58.png +0 -0
  150. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/60.png +0 -0
  151. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/64.png +0 -0
  152. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/66.png +0 -0
  153. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/72.png +0 -0
  154. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/76.png +0 -0
  155. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/80.png +0 -0
  156. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/87.png +0 -0
  157. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/88.png +0 -0
  158. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/92.png +0 -0
  159. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/Contents.json +1 -0
  160. data/solara/lib/core/template/brands/ios/ios_config.json +7 -0
  161. data/solara/lib/core/template/brands/ios/ios_signing.json +7 -0
  162. data/solara/lib/core/template/brands/shared/.DS_Store +0 -0
  163. data/solara/lib/core/template/brands/shared/brand_config.json +2 -0
  164. data/solara/lib/core/template/brands/shared/theme.json +46 -0
  165. data/solara/lib/core/template/config/android_template_config.json +57 -0
  166. data/solara/lib/core/template/config/flutter_template_config.json +62 -0
  167. data/solara/lib/core/template/config/ios_template_config.json +57 -0
  168. data/solara/lib/core/template/project_template_generator.rb +63 -0
  169. data/solara/lib/platform_detector.rb +84 -0
  170. data/solara/lib/solara/cli.rb +5 -0
  171. data/solara/lib/solara/version.rb +3 -0
  172. data/solara/lib/solara.rb +238 -0
  173. data/solara/lib/solara_initializer.rb +44 -0
  174. data/solara/lib/solara_manager.rb +73 -0
  175. metadata +346 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 145b33e1ba6fda109d59904bf8e356ed6ec8f4990b16857e5fbde74fb2d5e2da
4
+ data.tar.gz: 401d6f18d80006e0e030d1873ad6488a845301fc8f6fb91700ecd7cf2b959c25
5
+ SHA512:
6
+ metadata.gz: 4dbd300836c1b9c4885c24e9f9506f0b10fb0baa987a5a851d95aa24d5e592e9af496d96601c05f248e386736589151916baab4a53034af1d2723ccd99f26482
7
+ data.tar.gz: 3bbc2fc137767dd083228dd520a8b47e8ab7a06eb1b78ea81fa6184524d70630167419665021f1eefb08ddab649cdaa771d265685e5288d4ec1b53778c4a2016
data/bin/solara ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if RUBY_VERSION < '2.0.0'
4
+ abort("Solara requires Ruby 2.0.0 or higher")
5
+ end
6
+
7
+ Dir.glob("#{__dir__}/core/scripts/*.rb").each { |file| require file }
8
+ Dir.glob("#{__dir__}/core/scripts/*.rb").each { |file| require file }
9
+ Dir.glob("#{__dir__}/core/*.rb").each { |file| require file }
10
+ Dir.glob("#{__dir__}/core/doctor/*.rb").each { |file| require file }
11
+ Dir.glob("#{__dir__}/core/aliases/*.rb").each { |file| require file }
12
+ Dir.glob("#{__dir__}/core/dashboard/*.rb").each { |file| require file }
13
+ Dir.glob("#{__dir__}/core/brands/*.rb").each { |file| require file }
14
+
15
+ require 'solara'
16
+
17
+ Solara::Setup.new.setup
18
+ Solara::CLI.start(ARGV)
Binary file
Binary file
@@ -0,0 +1,128 @@
1
+ Dir[File.expand_path('../scripts/*.rb', __dir__)].each { |file| require_relative file }
2
+ require 'json'
3
+
4
+ class AliasGenerator
5
+ def initialize
6
+ @output_file = FilePath.solara_aliases_sh
7
+ FileManager.create_file_if_not_exist(@output_file)
8
+
9
+ @readme_file = FilePath.solara_aliases_readme
10
+ FileManager.create_file_if_not_exist(@readme_file)
11
+
12
+ @json_file = FilePath.solara_aliases_json
13
+ FileManager.create_file_if_not_exist(@json_file)
14
+
15
+ @brand_aliases = {}
16
+ @common_aliases = []
17
+ end
18
+
19
+ def add_brand_aliases(brands)
20
+ alias_templates = [
21
+ "solara_offboard_{brand_key}='solara offboard -k {brand_key}'",
22
+ "solara_switch_{brand_key}='solara switch -k {brand_key}'",
23
+ "solara_doctor_{brand_key}='solara doctor -k {brand_key}'",
24
+ "solara_dashboard_{brand_key}='solara dashboard -k {brand_key}'"
25
+ ]
26
+
27
+ brands.each do |app|
28
+ brand_key = app['key']
29
+ @brand_aliases[brand_key] = []
30
+ alias_templates.each do |template|
31
+ alias_line = template.gsub('{brand_key}', brand_key)
32
+ @brand_aliases[brand_key] << "alias #{alias_line}"
33
+ end
34
+ end
35
+ end
36
+
37
+ def add_common_aliases(common_aliases)
38
+ @common_aliases = common_aliases.map { |alias_line| "alias #{alias_line}" }
39
+ end
40
+
41
+ def generate_shell_file
42
+ existing_content = File.exist?(@output_file) ? File.read(@output_file) : ""
43
+ new_content = []
44
+
45
+ new_content << "#!/bin/bash" if existing_content.empty?
46
+
47
+ common_aliases_added = false
48
+ @common_aliases.each do |alias_line|
49
+ unless existing_content.include?(alias_line)
50
+ new_content << "# Common Aliases" unless common_aliases_added
51
+ common_aliases_added = true
52
+ new_content << alias_line
53
+ end
54
+ end
55
+
56
+ brand_aliases_added = false
57
+ @brand_aliases.each do |brand_name, brand_aliases|
58
+ brand_aliases_for_this_brand_added = false
59
+ brand_aliases.each do |alias_line|
60
+ unless existing_content.include?(alias_line)
61
+ unless brand_aliases_added
62
+ brand_aliases_added = true
63
+ end
64
+ unless brand_aliases_for_this_brand_added
65
+ new_content << "" # Add a new line before each brand name
66
+ new_content << "# #{brand_name}"
67
+ brand_aliases_for_this_brand_added = true
68
+ end
69
+ new_content << alias_line
70
+ end
71
+ end
72
+ end
73
+
74
+ new_content.reject!(&:empty?) if new_content.size == 1
75
+
76
+ if new_content.any? && !(new_content.size == 1 && new_content.first == "#!/bin/bash")
77
+ File.open(@output_file, 'a') do |file|
78
+ file.puts new_content
79
+ end
80
+ Solara.logger.debug("Aliases have been appended to #{@output_file}")
81
+ else
82
+ Solara.logger.debug("No new aliases to add to #{@output_file}")
83
+ end
84
+ end
85
+
86
+ def generate_readme
87
+ File.open(@readme_file, 'w') do |file|
88
+ file.puts "# Aliases"
89
+ file.puts
90
+ file.puts "This document provides an overview of all available aliases."
91
+ file.puts
92
+
93
+ if @common_aliases.any?
94
+ file.puts "## Common Aliases"
95
+ file.puts
96
+ @common_aliases.each do |alias_line|
97
+ alias_name = alias_line.split('=').first.strip.gsub('alias ', '')
98
+ file.puts "- `#{alias_name}`"
99
+ end
100
+ end
101
+
102
+ file.puts
103
+
104
+ file.puts
105
+ @brand_aliases.each do |brand_name, brand_aliases|
106
+ file.puts "## #{brand_name}"
107
+ file.puts
108
+ brand_aliases.each do |alias_line|
109
+ alias_name = alias_line.split('=').first.strip.gsub('alias ', '')
110
+ file.puts "- `#{alias_name}`"
111
+ end
112
+ end
113
+ end
114
+ Solara.logger.debug("README.md has been generated in #{@readme_file}")
115
+ end
116
+
117
+ def save_aliases_to_json
118
+ json_data = {
119
+ "common_aliases" => @common_aliases,
120
+ "brand_aliases" => @brand_aliases
121
+ }
122
+
123
+ File.open(@json_file, 'w') do |file|
124
+ file.puts JSON.pretty_generate(json_data)
125
+ end
126
+ Solara.logger.debug("Aliases have been saved in JSON format in #{@json_file}")
127
+ end
128
+ end
@@ -0,0 +1,28 @@
1
+ class AliasGeneratorManager
2
+ def initialize
3
+ @generator = AliasGenerator.new()
4
+ end
5
+
6
+ def start
7
+ Solara.logger.start_step("Generate terminal command aliases")
8
+ common_aliases = [
9
+ "solara_dashboard='solara dashboard'",
10
+ "solara_doctor='solara doctor'",
11
+ ]
12
+
13
+ @generator.add_brand_aliases(BrandsManager.instance.brands_list)
14
+ @generator.add_common_aliases(common_aliases)
15
+ @generator.generate_shell_file
16
+ @generator.save_aliases_to_json
17
+ @generator.generate_readme
18
+
19
+ SolaraSetup.new.run
20
+ Solara.logger.end_step("Generate terminal command aliases")
21
+ end
22
+
23
+ def self.aliases_json
24
+ path = FilePath.solara_aliases_json
25
+ JSON.parse(File.read(path))
26
+ end
27
+
28
+ end
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Dir.glob("../scripts/*.rb").each { |file| require file }
4
+
5
+ require 'fileutils'
6
+ require 'rbconfig'
7
+
8
+ class SolaraSetup
9
+ def initialize
10
+ @aliases_file = FilePath.solara_aliases_sh
11
+ @setup_dir = File.join(ENV['HOME'], '.solara')
12
+ @unix_setup_file = File.join(@setup_dir, 'setup.sh')
13
+ @windows_setup_file = File.join(@setup_dir, 'setup.bat')
14
+ end
15
+
16
+ def run
17
+ create_setup_directory
18
+ create_unix_setup_script
19
+ create_windows_setup_script
20
+
21
+ case RbConfig::CONFIG['host_os']
22
+ when /mswin|mingw|cygwin/
23
+ setup_windows
24
+ when /darwin|mac os|linux/
25
+ setup_unix
26
+ else
27
+ Solara.logger.fatal("Unsupported operating system. Please set up manually.")
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def create_setup_directory
34
+ FileUtils.mkdir_p(@setup_dir)
35
+ end
36
+
37
+ def create_unix_setup_script
38
+ File.open(@unix_setup_file, 'w') do |file|
39
+ file.puts <<~SCRIPT
40
+ #!/bin/bash
41
+ source "#{@aliases_file}"
42
+ SCRIPT
43
+ end
44
+ FileUtils.chmod(0755, @unix_setup_file)
45
+ end
46
+
47
+ def create_windows_setup_script
48
+ File.open(@windows_setup_file, 'w') do |file|
49
+ file.puts <<~SCRIPT
50
+ @echo off
51
+ call "#{@aliases_file.gsub('/', '\\')}"
52
+ SCRIPT
53
+ end
54
+ end
55
+
56
+ def setup_unix
57
+ shell_config_file = determine_shell_config_file
58
+ setup_line = "source #{@unix_setup_file}"
59
+
60
+ if File.exist?(shell_config_file)
61
+ content = File.read(shell_config_file)
62
+ unless content.include?(setup_line)
63
+ File.open(shell_config_file, 'a') do |file|
64
+ file.puts "\n# Solara Setup"
65
+ file.puts setup_line
66
+ end
67
+ Solara.logger.debug("Configuration added to #{shell_config_file}")
68
+ Solara.logger.success("Please restart your terminal or run 'source #{shell_config_file}' to apply changes.")
69
+ else
70
+ Solara.logger.debug("Configuration already exists in #{shell_config_file}")
71
+ end
72
+ else
73
+ Solara.logger.failure("Shell configuration file not found. Please add the following line manually to your shell configuration:")
74
+ Solara.logger.failure(setup_line)
75
+ end
76
+ end
77
+
78
+ def setup_windows
79
+ require 'win32/registry'
80
+
81
+ begin
82
+ Win32::Registry::HKEY_CURRENT_USER.create('Software\Microsoft\Command Processor') do |reg|
83
+ reg['AutoRun', Win32::Registry::REG_EXPAND_SZ] = @windows_setup_file
84
+ end
85
+ Solara.logger.success("Windows AutoRun registry key set up successfully.")
86
+ pSolara.logger.warn("Please restart your Command Prompt to apply changes.")
87
+ rescue Win32::Registry::Error => e
88
+ Solara.logger.failure("Failed to set up Windows registry: #{e.message}")
89
+ Solara.logger.failure("Please add the following file path to your AutoRun registry key manually:")
90
+ Solara.logger.failure(@windows_setup_file)
91
+ end
92
+ end
93
+
94
+ def determine_shell_config_file
95
+ if ENV['SHELL'] =~ /zsh/
96
+ File.expand_path('~/.zshrc')
97
+ elsif ENV['SHELL'] =~ /bash/
98
+ File.expand_path('~/.bashrc')
99
+ else
100
+ File.expand_path('~/.profile')
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,46 @@
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
+
7
+ class BrandOnboarder
8
+ def initialize(brand_key, brand_name, clone_brand_key: nil)
9
+ @brand_key = brand_key
10
+ @brand_name = brand_name
11
+ @clone_brand_key = clone_brand_key
12
+ end
13
+
14
+ def onboard
15
+ if @clone_brand_key.nil? || @clone_brand_key.empty?
16
+ generate_brand_template
17
+ else
18
+ clone_brand
19
+ end
20
+ add_to_brands_list
21
+ end
22
+
23
+ def add_to_brands_list
24
+ BrandsManager.instance.add_brand(@brand_name, @brand_key)
25
+ end
26
+
27
+ def generate_brand_template
28
+ Solara.logger.debug("Onboarding #{@brand_key} from template.")
29
+
30
+ template_dir = FilePath.template_brands
31
+ target_dir = File.join(FilePath.solara, 'brands', @brand_key)
32
+ config_file = FilePath.template_config
33
+
34
+ generator = ProjectTemplateGenerator.new(template_dir, target_dir, config_file)
35
+ generator.create_project
36
+ end
37
+
38
+ def clone_brand
39
+ Solara.logger.debug("Cloning #{@clone_brand_key} to #{@brand_key}")
40
+ source = FilePath.brand(@clone_brand_key)
41
+ destination = File.join(FilePath.solara, 'brands', @brand_key)
42
+ FolderCopier.new(source, destination).copy
43
+ end
44
+
45
+ end
46
+
@@ -0,0 +1,204 @@
1
+ Dir[File.expand_path('scripts/*.rb', __dir__)].each { |file| require_relative file }
2
+ Dir[File.expand_path('platform/android/*.rb', __dir__)].each { |file| require_relative file }
3
+ Dir[File.expand_path('platform/ios/*.rb', __dir__)].each { |file| require_relative file }
4
+ Dir[File.expand_path('platform/flutter/*.rb', __dir__)].each { |file| require_relative file }
5
+
6
+ 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
13
+
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
20
+ end
21
+
22
+ def start
23
+ Solara.logger.header("Switching to #{@brand_key}")
24
+
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
32
+
33
+ BrandsManager.instance.save_current_brand(@brand_key)
34
+
35
+ Solara.logger.start_step("Create artifacts directories")
36
+ create_artifacts_dirs
37
+ Solara.logger.end_step("Create artifacts directories")
38
+
39
+ switch
40
+
41
+ SolaraConfigurator.new.start
42
+
43
+ Solara.logger.success("Switched to #{@brand_key} successfully.")
44
+ end
45
+
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
71
+
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
88
+
89
+ def generate_theme_kotlin
90
+ generate_theme(
91
+ 'BrandTheme.kt',
92
+ Language::Kotlin,
93
+ Platform::Android)
94
+ end
95
+
96
+ def generate_theme_swift
97
+ generate_theme(
98
+ 'BrandTheme.swift',
99
+ Language::Swift,
100
+ Platform::IOS)
101
+ end
102
+
103
+ def generate_theme_dart
104
+ generate_theme(
105
+ 'brand_theme.dart',
106
+ Language::Dart,
107
+ Platform::Flutter)
108
+ end
109
+
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
+
123
+ def generate_app_config_kotlin
124
+ generate_brand_config(
125
+ 'BrandConfig.kt',
126
+ Language::Kotlin,
127
+ Platform::Android
128
+ )
129
+ end
130
+
131
+ def generate_app_config_swift
132
+ generate_brand_config(
133
+ 'BrandConfig.swift',
134
+ Language::Swift,
135
+ Platform::IOS)
136
+ end
137
+
138
+ def generate_app_config_dart
139
+ generate_brand_config(
140
+ 'brand_config.dart',
141
+ Language::Dart,
142
+ Platform::Flutter)
143
+ end
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
154
+
155
+ def switch_flutter
156
+ generate_theme_dart
157
+ generate_app_config_dart
158
+ BrandResourcesManager.new(@brand_key).update_flutter
159
+ end
160
+
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
172
+
173
+ def update_build_gradle
174
+ switcher = GradleSwitcher.new(@brand_key)
175
+ switcher.update_build_gradle
176
+ end
177
+
178
+ def update_manifest(config)
179
+ switcher = AndroidManifestSwitcher.new
180
+ switcher.update_manifest(config)
181
+ end
182
+
183
+ def update_strings_xml(config)
184
+ switcher = AndroidStringsSwitcher.new
185
+ switcher.update(config)
186
+ end
187
+
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
194
+ end
195
+
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")
202
+ end
203
+
204
+ end
@@ -0,0 +1,154 @@
1
+ require 'singleton'
2
+ require 'json'
3
+ require 'rubygems'
4
+
5
+ class BrandsManager
6
+ include Singleton
7
+
8
+ def initialize
9
+ brands_list_path = FilePath.brands_list
10
+ @brands_list = JSON.parse(File.read(brands_list_path))
11
+ end
12
+
13
+ def first_brand
14
+ brands_list.first
15
+ end
16
+
17
+ def first_brand_key
18
+ brands_list.first["key"]
19
+ rescue
20
+ nil
21
+ end
22
+
23
+ def brand_name(brand_key)
24
+ brand_data(brand_key)["name"]
25
+ end
26
+
27
+ def brand_with_configurations(brand_key)
28
+ configurations = BrandConfigurationsManager.new(brand_key).create
29
+ {
30
+ solaraVersion: Gem.loaded_specs['solara'].version.to_s,
31
+ brand: brand_data(brand_key),
32
+ configurations: configurations
33
+ }
34
+ end
35
+
36
+ def brand_data(brand_key)
37
+ brands_list.find { |brand| brand["key"] == brand_key }
38
+ end
39
+
40
+ def brands_list
41
+ @brands_list["brands"]
42
+ end
43
+
44
+ def find(brand_key)
45
+ brands = brands_list
46
+ brands.find { |b| b["key"] == brand_key }
47
+ end
48
+
49
+ def brands_json
50
+ @brands_list
51
+ end
52
+
53
+ def exists(brand_key)
54
+ !brand_data(brand_key).nil?
55
+ end
56
+
57
+ def add_brand(brand_name, brand_key)
58
+ brand = { 'key' => brand_key, 'name' => brand_name }
59
+ existing_brand = brand_data(brand_key)
60
+ if existing_brand
61
+ update_brand(brands_list.index(existing_brand), brand)
62
+ Solara.logger.debug("#{brand_name} Brand updated in the list.")
63
+ else
64
+ brands_list.push(brand)
65
+ save_brands_list
66
+ Solara.logger.debug("#{brand_name} added to the list.")
67
+ end
68
+ end
69
+
70
+ def current_brand
71
+ JSON.parse(File.read(FilePath.current_brand))
72
+ end
73
+
74
+ def current_brand_content_changed(brand_key)
75
+ unless is_current_brand(brand_key)
76
+ return false
77
+ end
78
+ current_brand['content_changed'] == true
79
+ end
80
+
81
+ def set_current_brand_content_changed(brand_key, changed)
82
+ unless is_current_brand(brand_key)
83
+ return false
84
+ end
85
+ Solara.logger.debug("")
86
+ brand = current_brand
87
+ brand['content_changed'] = changed
88
+ save_current_brand_date(brand)
89
+ Solara.logger.debug("#{brand_key} changed saved to current_brand.json.")
90
+ end
91
+
92
+ def is_current_brand(brand_key)
93
+ current_brand['key'] == brand_key
94
+ end
95
+
96
+ def save_current_brand(brand_key)
97
+ brand = brand_data(brand_key)
98
+ save_current_brand_date(brand)
99
+ Solara.logger.debug("#{brand_key} saved as current brand.")
100
+ end
101
+
102
+ def save_current_brand_date(brand_data)
103
+ current_brand = FilePath.current_brand
104
+
105
+ # Create the file if it doesn't exist
106
+ FileUtils.touch(current_brand) unless File.exist?(current_brand)
107
+
108
+ File.open(current_brand, 'w') do |file|
109
+ file.write(JSON.pretty_generate(brand_data))
110
+ end
111
+
112
+ end
113
+
114
+ def update_brand(index, new_brand)
115
+ brands_list[index] = new_brand
116
+ save_brands_list
117
+ Solara.logger.debug("Brand updated.")
118
+ end
119
+
120
+ def remove_brand(index)
121
+ brands_list.delete_at(index)
122
+ save_brands_list
123
+ Solara.logger.debug("Brand removed.")
124
+ end
125
+
126
+ def offboard(brand_key)
127
+ index = brands_list.find_index { |brand| brand["key"] == brand_key }
128
+ if index
129
+ brand_dir = FilePath.brand(brand_key)
130
+ remove_brand(index)
131
+ FileUtils.rm_rf(brand_dir)
132
+ save_brands_list
133
+ Solara.logger.debug("Brand removed.")
134
+ else
135
+ Solara.logger.debug("Brand not found (#{brand_key}).")
136
+ end
137
+ end
138
+
139
+ # Class method to access the singleton instance
140
+ def self.instance
141
+ @instance ||= new
142
+ end
143
+
144
+ private
145
+
146
+ def save_brands_list
147
+ brands_list_path = FilePath.brands_list
148
+ File.open(brands_list_path, 'w') do |file|
149
+ file.write(JSON.pretty_generate(@brands_list))
150
+ end
151
+ end
152
+
153
+ private_class_method :new
154
+ end
Binary file