solara 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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