solara 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/solara/lib/core/.DS_Store +0 -0
  3. data/solara/lib/core/aliases/alias_generator.rb +1 -0
  4. data/solara/lib/core/aliases/alias_generator_manager.rb +2 -1
  5. data/solara/lib/core/aliases/solara_terminal_setup.rb +1 -1
  6. data/solara/lib/core/brands/brand_font_switcher.rb +154 -0
  7. data/solara/lib/core/brands/brand_onboarder.rb +8 -6
  8. data/solara/lib/core/brands/brand_switcher.rb +232 -166
  9. data/solara/lib/core/brands/brands_manager.rb +15 -39
  10. data/solara/lib/core/dashboard/brand/BrandDetail.js +19 -0
  11. data/solara/lib/core/dashboard/brand/BrandDetailController.js +50 -8
  12. data/solara/lib/core/dashboard/brand/BrandDetailModel.js +9 -30
  13. data/solara/lib/core/dashboard/brand/BrandDetailView.js +49 -3
  14. data/solara/lib/core/dashboard/brand/InfoPlistStringCatalogManager.js +19 -0
  15. data/solara/lib/core/dashboard/brand/brand.html +209 -62
  16. data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +1 -1
  17. data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +38 -53
  18. data/solara/lib/core/dashboard/brands/BrandsController.js +6 -5
  19. data/solara/lib/core/dashboard/brands/BrandsModel.js +2 -2
  20. data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
  21. data/solara/lib/core/dashboard/brands/brands.html +3 -1
  22. data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +7 -5
  23. data/solara/lib/core/dashboard/dashboard_manager.rb +2 -0
  24. data/solara/lib/core/dashboard/dashboard_server.rb +13 -8
  25. data/solara/lib/core/dashboard/handler/brand_alisases_handler.rb +4 -11
  26. data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +11 -11
  27. data/solara/lib/core/dashboard/handler/{brand_configurations_handler.rb → brand_details_handler.rb} +4 -4
  28. data/solara/lib/core/dashboard/handler/brands_handler.rb +1 -1
  29. data/solara/lib/core/dashboard/handler/edit_section_handler.rb +8 -8
  30. data/solara/lib/core/doctor/brand_doctor.rb +31 -31
  31. data/solara/lib/core/doctor/doctor_manager.rb +0 -1
  32. data/solara/lib/core/doctor/project_doctor.rb +0 -1
  33. data/solara/lib/core/doctor/schema/platform/android/android_config.json +0 -4
  34. data/solara/lib/core/doctor/schema/platform/ios/InfoPlist.xcstrings +15 -0
  35. data/solara/lib/core/doctor/schema/platform/ios/ios_config.json +0 -5
  36. data/solara/lib/core/doctor/schema/platform/shared/brand_config.json +9 -0
  37. data/solara/lib/core/doctor/schema/platform/shared/theme.json +94 -9
  38. data/solara/lib/core/doctor/validator/brand_settings_validator.rb +6 -0
  39. data/solara/lib/core/doctor/validator/brand_settings_validator_manager.rb +9 -21
  40. data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +22 -4
  41. data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +22 -6
  42. data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +22 -4
  43. data/solara/lib/core/scripts/brand_config_generator.rb +1 -0
  44. data/solara/lib/core/scripts/brand_config_manager.rb +2 -4
  45. data/solara/lib/core/scripts/brand_exporter.rb +1 -1
  46. data/solara/lib/core/scripts/brand_importer.rb +2 -3
  47. data/solara/lib/core/scripts/brand_offboarder.rb +5 -0
  48. data/solara/lib/core/scripts/brand_resources_manager.rb +127 -54
  49. data/solara/lib/core/scripts/directory_creator.rb +2 -2
  50. data/solara/lib/core/scripts/file_manager.rb +53 -19
  51. data/solara/lib/core/scripts/file_path.rb +175 -30
  52. data/solara/lib/core/scripts/folder_copier.rb +3 -7
  53. data/solara/lib/core/scripts/gitignore_manager.rb +21 -10
  54. data/solara/lib/core/scripts/interactive_file_system_validator.rb +8 -2
  55. data/solara/lib/core/scripts/platform/android/android_manifest_switcher.rb +3 -3
  56. data/solara/lib/core/scripts/platform/android/android_strings_switcher.rb +26 -24
  57. data/solara/lib/core/scripts/platform/android/gradle_switcher.rb +7 -6
  58. data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +123 -0
  59. data/solara/lib/core/scripts/platform/ios/infoplist_switcher.rb +59 -0
  60. data/solara/lib/core/scripts/platform/ios/ios_plist_manager.rb +11 -20
  61. data/solara/lib/core/scripts/platform/ios/plist_font_manager.rb +33 -0
  62. data/solara/lib/core/scripts/platform/ios/xcconfig_generator.rb +15 -3
  63. data/solara/lib/core/scripts/platform/ios/xcode_asset_manager.rb +2 -3
  64. data/solara/lib/core/scripts/platform/ios/xcode_project_manager.rb +80 -1
  65. data/solara/lib/core/scripts/platform/ios/xcode_project_switcher.rb +15 -34
  66. data/solara/lib/core/scripts/solara_logger.rb +10 -0
  67. data/solara/lib/core/scripts/solara_settings_manager.rb +26 -1
  68. data/solara/lib/core/scripts/strings_xml_manager.rb +17 -2
  69. data/solara/lib/core/scripts/theme_generator.rb +133 -130
  70. data/solara/lib/core/scripts/yaml_manager.rb +23 -0
  71. data/solara/lib/core/solara_configurator.rb +1 -1
  72. data/solara/lib/core/template/brands/android/android_config.json +0 -1
  73. data/solara/lib/core/template/brands/android/res/values/strings.xml +4 -0
  74. data/solara/lib/core/template/brands/ios/InfoPlist.xcstrings +30 -0
  75. data/solara/lib/core/template/brands/ios/ios_config.json +1 -2
  76. data/solara/lib/core/template/brands/shared/brand_config.json +1 -0
  77. data/solara/lib/core/template/brands/shared/theme.json +3 -3
  78. data/solara/lib/core/template/config/android_template_config.json +11 -1
  79. data/solara/lib/core/template/config/flutter_template_config.json +12 -2
  80. data/solara/lib/core/template/config/ios_template_config.json +11 -1
  81. data/solara/lib/core/template/project_template_generator.rb +8 -3
  82. data/solara/lib/solara/version.rb +1 -1
  83. data/solara/lib/solara.rb +8 -4
  84. data/solara/lib/solara_initializer.rb +5 -2
  85. data/solara/lib/solara_manager.rb +1 -1
  86. metadata +62 -43
  87. data/solara/lib/core/dashboard/handler/brand_section_handler.rb +0 -20
  88. data/solara/lib/core/doctor/validator/directory_structure_validator.rb +0 -38
  89. data/solara/lib/core/doctor/validator/file_structure_validator.rb +0 -37
  90. data/solara/lib/core/scripts/platform/ios/ios_file_path_manager.rb +0 -109
  91. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/.DS_Store +0 -0
  92. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/100.png +0 -0
  93. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/102.png +0 -0
  94. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/1024.png +0 -0
  95. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/114.png +0 -0
  96. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/120.png +0 -0
  97. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/128.png +0 -0
  98. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/144.png +0 -0
  99. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/152.png +0 -0
  100. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/16.png +0 -0
  101. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/167.png +0 -0
  102. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/172.png +0 -0
  103. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/180.png +0 -0
  104. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/196.png +0 -0
  105. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/20.png +0 -0
  106. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/216.png +0 -0
  107. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/256.png +0 -0
  108. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/29.png +0 -0
  109. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/32.png +0 -0
  110. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/40.png +0 -0
  111. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/48.png +0 -0
  112. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/50.png +0 -0
  113. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/512.png +0 -0
  114. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/55.png +0 -0
  115. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/57.png +0 -0
  116. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/58.png +0 -0
  117. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/60.png +0 -0
  118. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/64.png +0 -0
  119. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/66.png +0 -0
  120. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/72.png +0 -0
  121. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/76.png +0 -0
  122. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/80.png +0 -0
  123. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/87.png +0 -0
  124. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/88.png +0 -0
  125. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/92.png +0 -0
  126. /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/Contents.json +0 -0
@@ -1,77 +1,65 @@
1
1
  require 'json'
2
2
  require 'fileutils'
3
3
 
4
- class ThemeGenerator
5
- def initialize(input_path, output_path, language)
6
- @theme = JSON.parse(File.read(input_path))
7
- @output_path = output_path
8
- @language = language.downcase
4
+ class ThemeGeneratorManager
5
+ def initialize(input_path)
6
+ @input_path = input_path
7
+ end
9
8
 
10
- unless %w[kotlin swift dart].include?(@language)
11
- raise ArgumentError, "Unsupported language. Choose 'kotlin', 'swift', or 'dart'."
9
+ def generate(language, output_path)
10
+ case language.downcase
11
+ when 'kotlin'
12
+ generator = KotlinThemeGenerator.new(@input_path, output_path)
13
+ when 'swift'
14
+ generator = SwiftThemeGenerator.new(@input_path, output_path)
15
+ when 'dart'
16
+ generator = DartThemeGenerator.new(@input_path, output_path)
17
+ else
18
+ Solara.logger.fatal("Unsupported language: #{language}")
19
+ return
12
20
  end
13
- end
14
21
 
15
- def generate
16
- code = send("generate_#{@language}")
17
- write_to_file(code)
22
+ generator.generate
18
23
  end
24
+ end
19
25
 
20
- private
21
-
22
- def generate_kotlin
23
- kotlin_code = "import androidx.compose.ui.graphics.Color\n"
24
- kotlin_code += "import androidx.compose.ui.unit.dp\n"
25
- kotlin_code += "import androidx.compose.ui.unit.sp\n\n"
26
- kotlin_code += "object #{@theme['name']} {\n"
27
- kotlin_code += generate_kotlin_colors
28
- kotlin_code += generate_kotlin_typography
29
- kotlin_code += generate_kotlin_spacing
30
- kotlin_code += generate_kotlin_border_radius
31
- kotlin_code += generate_kotlin_elevation
32
- kotlin_code += "}"
33
- kotlin_code
34
- end
35
-
36
- def generate_swift
37
- swift_code = "import SwiftUI\n\n"
38
- swift_code += "struct #{@theme['name']} {\n"
39
- swift_code += generate_swift_colors
40
- swift_code += generate_swift_typography
41
- swift_code += generate_swift_spacing
42
- swift_code += generate_swift_border_radius
43
- swift_code += generate_swift_elevation
44
- swift_code += "}\n\n"
45
- swift_code += generate_swift_colors_hext_extension
46
- swift_code
47
- end
48
-
49
- def generate_dart
50
- dart_code = "import 'package:flutter/material.dart';\n\n"
51
- dart_code += generate_dart_colors
52
- dart_code += generate_dart_typography
53
- dart_code += generate_dart_spacing
54
- dart_code += generate_dart_border_radius
55
- dart_code += generate_dart_elevation
56
- dart_code
26
+ class ThemeGenerator
27
+ def initialize(input_path, output_path)
28
+ @theme = JSON.parse(File.read(input_path))
29
+ @output_path = output_path
57
30
  end
58
31
 
59
32
  def write_to_file(code)
60
33
  FileUtils.mkdir_p(File.dirname(@output_path))
61
34
  File.write(@output_path, code)
62
- Solara.logger.debug("Generated #{@language.capitalize} theme file: #{@output_path}")
35
+ Solara.logger.debug("Generated theme file: #{@output_path}")
36
+ end
37
+ end
38
+
39
+ class KotlinThemeGenerator < ThemeGenerator
40
+ def generate
41
+ code = "import android.graphics.Color\n\n"
42
+ code += "object BrandTheme {\n"
43
+ code += generate_colors
44
+ code += generate_typography
45
+ code += generate_spacing
46
+ code += generate_border_radius
47
+ code += generate_elevation
48
+ code += "}"
49
+ write_to_file(code)
63
50
  end
64
51
 
65
- def generate_kotlin_colors
52
+ private
53
+
54
+ def generate_colors
66
55
  code = " object Colors {\n"
67
56
  @theme['colors'].each do |name, value|
68
- code += " val #{name} = Color(0xFF#{value[1..-1]})\n"
57
+ code += " val #{name} = Color.parseColor(\"#{value}\")\n"
69
58
  end
70
- code += " }\n\n"
71
- code
59
+ code + " }\n\n"
72
60
  end
73
61
 
74
- def generate_kotlin_typography
62
+ def generate_typography
75
63
  code = " object Typography {\n"
76
64
  code += " object FontFamily {\n"
77
65
  @theme['typography']['fontFamily'].each do |name, value|
@@ -80,82 +68,92 @@ class ThemeGenerator
80
68
  code += " }\n\n"
81
69
  code += " object FontSize {\n"
82
70
  @theme['typography']['fontSize'].each do |name, value|
83
- code += " val #{name} = #{value}.sp\n"
71
+ code += " val #{name} = #{value}\n"
84
72
  end
85
73
  code += " }\n"
86
- code += " }\n\n"
87
- code
74
+ code + " }\n\n"
88
75
  end
89
76
 
90
- def generate_kotlin_spacing
77
+ def generate_spacing
91
78
  code = " object Spacing {\n"
92
79
  @theme['spacing'].each do |name, value|
93
- code += " val #{name} = #{value}.dp\n"
80
+ code += " val #{name} = #{value}\n"
94
81
  end
95
- code += " }\n\n"
96
- code
82
+ code + " }\n\n"
97
83
  end
98
84
 
99
- def generate_kotlin_border_radius
85
+ def generate_border_radius
100
86
  code = " object BorderRadius {\n"
101
87
  @theme['borderRadius'].each do |name, value|
102
- code += " val #{name} = #{value}.dp\n"
88
+ code += " val #{name} = #{value}\n"
103
89
  end
104
- code += " }\n\n"
105
- code
90
+ code + " }\n\n"
106
91
  end
107
92
 
108
- def generate_kotlin_elevation
93
+ def generate_elevation
109
94
  code = " object Elevation {\n"
110
95
  @theme['elevation'].each do |name, value|
111
- code += " val #{name} = #{value}.dp\n"
96
+ code += " val #{name} = #{value}\n"
112
97
  end
113
- code += " }\n"
114
- code
98
+ code + " }\n"
99
+ end
100
+ end
101
+
102
+ class SwiftThemeGenerator < ThemeGenerator
103
+ def generate
104
+ code = "import UIKit\n\n"
105
+ code += "struct BrandTheme {\n"
106
+ code += generate_colors
107
+ code += generate_typography
108
+ code += generate_spacing
109
+ code += generate_border_radius
110
+ code += generate_elevation
111
+ code += "}\n\n"
112
+ code += generate_colors_hex_extension
113
+ write_to_file(code)
115
114
  end
116
115
 
117
- def generate_swift_colors
116
+ private
117
+
118
+ def generate_colors
118
119
  code = " struct Colors {\n"
119
120
  @theme['colors'].each do |name, value|
120
- code += " static let #{name} = Color(hex: \"#{value}\")\n"
121
- end
122
- code += " }\n\n"
123
- code
124
- end
125
-
126
- def generate_swift_colors_hext_extension
127
- code = <<-SWIFT
128
- extension Color {
129
- init(hex: String) {
130
- let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
131
- var int: UInt64 = 0
132
- Scanner(string: hex).scanHexInt64(&int)
133
- let a, r, g, b: UInt64
134
- switch hex.count {
135
- case 3: // RGB (12-bit)
136
- (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
137
- case 6: // RGB (24-bit)
138
- (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
139
- case 8: // ARGB (32-bit)
140
- (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
141
- default:
142
- (a, r, g, b) = (1, 1, 1, 0)
143
- }
144
-
145
- self.init(
146
- .sRGB,
147
- red: Double(r) / 255,
148
- green: Double(g) / 255,
149
- blue: Double(b) / 255,
150
- opacity: Double(a) / 255
151
- )
152
- }
121
+ code += " static let #{name} = UIColor(hex: \"#{value}\")\n"
122
+ end
123
+ code + " }\n\n"
124
+ end
125
+
126
+ def generate_colors_hex_extension
127
+ <<-SWIFT
128
+ extension UIColor {
129
+ convenience init(hex: String) {
130
+ let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
131
+ var int: UInt64 = 0
132
+ Scanner(string: hex).scanHexInt64(&int)
133
+ let a, r, g, b: UInt64
134
+ switch hex.count {
135
+ case 3: // RGB (12-bit)
136
+ (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
137
+ case 6: // RGB (24-bit)
138
+ (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
139
+ case 8: // ARGB (32-bit)
140
+ (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
141
+ default:
142
+ (a, r, g, b) = (255, 255, 255, 0)
143
+ }
144
+
145
+ self.init(
146
+ red: CGFloat(r) / 255,
147
+ green: CGFloat(g) / 255,
148
+ blue: CGFloat(b) / 255,
149
+ alpha: CGFloat(a) / 255
150
+ )
151
+ }
153
152
  }
154
153
  SWIFT
155
- code
156
154
  end
157
155
 
158
- def generate_swift_typography
156
+ def generate_typography
159
157
  code = " struct Typography {\n"
160
158
  code += " struct FontFamily {\n"
161
159
  @theme['typography']['fontFamily'].each do |name, value|
@@ -167,47 +165,56 @@ extension Color {
167
165
  code += " static let #{name}: CGFloat = #{value}\n"
168
166
  end
169
167
  code += " }\n"
170
- code += " }\n\n"
171
- code
168
+ code + " }\n\n"
172
169
  end
173
170
 
174
- def generate_swift_spacing
171
+ def generate_spacing
175
172
  code = " struct Spacing {\n"
176
173
  @theme['spacing'].each do |name, value|
177
174
  code += " static let #{name}: CGFloat = #{value}\n"
178
175
  end
179
- code += " }\n\n"
180
- code
176
+ code + " }\n\n"
181
177
  end
182
178
 
183
- def generate_swift_border_radius
179
+ def generate_border_radius
184
180
  code = " struct BorderRadius {\n"
185
181
  @theme['borderRadius'].each do |name, value|
186
182
  code += " static let #{name}: CGFloat = #{value}\n"
187
183
  end
188
- code += " }\n\n"
189
- code
184
+ code + " }\n\n"
190
185
  end
191
186
 
192
- def generate_swift_elevation
187
+ def generate_elevation
193
188
  code = " struct Elevation {\n"
194
189
  @theme['elevation'].each do |name, value|
195
190
  code += " static let #{name}: CGFloat = #{value}\n"
196
191
  end
197
- code += " }\n"
198
- code
192
+ code + " }\n"
193
+ end
194
+ end
195
+
196
+ class DartThemeGenerator < ThemeGenerator
197
+ def generate
198
+ code = "import 'package:flutter/material.dart';\n\n"
199
+ code += generate_colors
200
+ code += generate_typography
201
+ code += generate_spacing
202
+ code += generate_border_radius
203
+ code += generate_elevation
204
+ write_to_file(code)
199
205
  end
200
206
 
201
- def generate_dart_colors
207
+ private
208
+
209
+ def generate_colors
202
210
  code = " class BrandColors {\n"
203
211
  @theme['colors'].each do |name, value|
204
212
  code += " static const Color #{name} = Color(0xFF#{value[1..-1]});\n"
205
213
  end
206
- code += " }\n\n"
207
- code
214
+ code + " }\n\n"
208
215
  end
209
216
 
210
- def generate_dart_typography
217
+ def generate_typography
211
218
  code = " class FontFamily {\n"
212
219
  @theme['typography']['fontFamily'].each do |name, value|
213
220
  code += " static const String #{name} = '#{value}';\n"
@@ -217,34 +224,30 @@ extension Color {
217
224
  @theme['typography']['fontSize'].each do |name, value|
218
225
  code += " static const double #{name} = #{value};\n"
219
226
  end
220
- code += " }\n\n"
221
- code
227
+ code + " }\n\n"
222
228
  end
223
229
 
224
- def generate_dart_spacing
230
+ def generate_spacing
225
231
  code = " class Spacing {\n"
226
232
  @theme['spacing'].each do |name, value|
227
233
  code += " static const double #{name} = #{value};\n"
228
234
  end
229
- code += " }\n\n"
230
- code
235
+ code + " }\n\n"
231
236
  end
232
237
 
233
- def generate_dart_border_radius
238
+ def generate_border_radius
234
239
  code = " class BorderRadius {\n"
235
240
  @theme['borderRadius'].each do |name, value|
236
241
  code += " static const double #{name} = #{value};\n"
237
242
  end
238
243
  code += " }\n\n"
239
- code
240
244
  end
241
245
 
242
- def generate_dart_elevation
246
+ def generate_elevation
243
247
  code = " class Elevation {\n"
244
248
  @theme['elevation'].each do |name, value|
245
249
  code += " static const double #{name} = #{value};\n"
246
250
  end
247
- code += " }\n"
248
- code
251
+ code + " }\n"
249
252
  end
250
253
  end
@@ -6,6 +6,29 @@ class YamlManager
6
6
  @file_path = file_path
7
7
  end
8
8
 
9
+ def add_font(family, assets)
10
+ yaml_data = load_yaml
11
+
12
+ # Ensure the 'flutter' key exists
13
+ yaml_data['flutter'] ||= {}
14
+ yaml_data['flutter']['fonts'] ||= []
15
+
16
+ # Check if the font family already exists
17
+ existing_font = yaml_data['flutter']['fonts'].find { |f| f['family'] == family }
18
+
19
+ if existing_font
20
+ Solara.logger.debug("YamlManager: Font family '#{family}' already exists.")
21
+ # Update existing font assets
22
+ existing_font['fonts'] = assets
23
+ else
24
+ # Add new font family
25
+ yaml_data['flutter']['fonts'] << { 'family' => family, 'fonts' => assets }
26
+ Solara.logger.debug("YamlManager: Font family '#{family}' has been added.")
27
+ end
28
+
29
+ save_yaml(yaml_data)
30
+ end
31
+
9
32
  def add_property(property_name, property_value)
10
33
  yaml_data = load_yaml
11
34
 
@@ -7,7 +7,7 @@ class SolaraConfigurator
7
7
  end
8
8
 
9
9
  def start
10
- GitignoreManager.ignore_redundant_files
10
+ GitignoreManager.ignore
11
11
  AliasGeneratorManager.new.start
12
12
  end
13
13
 
@@ -1,5 +1,4 @@
1
1
  {
2
- "brandName": "",
3
2
  "applicationId": "",
4
3
  "versionName": "1.0.0",
5
4
  "versionCode": 1,
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <string name="app_name"></string>
4
+ </resources>
@@ -0,0 +1,30 @@
1
+ {
2
+ "sourceLanguage": "en",
3
+ "strings": {
4
+ "CFBundleDisplayName": {
5
+ "comment": "Bundle display name",
6
+ "extractionState": "extracted_with_value",
7
+ "localizations": {
8
+ "en": {
9
+ "stringUnit": {
10
+ "state": "new",
11
+ "value": ""
12
+ }
13
+ }
14
+ }
15
+ },
16
+ "CFBundleName": {
17
+ "comment": "Bundle name",
18
+ "extractionState": "extracted_with_value",
19
+ "localizations": {
20
+ "en": {
21
+ "stringUnit": {
22
+ "state": "new",
23
+ "value": ""
24
+ }
25
+ }
26
+ }
27
+ }
28
+ },
29
+ "version": "1.0"
30
+ }
@@ -1,7 +1,6 @@
1
1
  {
2
- "PRODUCT_NAME": "",
3
2
  "PRODUCT_BUNDLE_IDENTIFIER": "",
4
3
  "MARKETING_VERSION": "1.0.0",
5
- "BUNDLE_VERSION": "1",
4
+ "BUNDLE_VERSION": 1,
6
5
  "APL_MRCH_ID": ""
7
6
  }
@@ -1,2 +1,3 @@
1
1
  {
2
+ "brandName": ""
2
3
  }
@@ -15,9 +15,9 @@
15
15
  },
16
16
  "typography": {
17
17
  "fontFamily": {
18
- "regular": "Roboto",
19
- "medium": "Roboto-Medium",
20
- "bold": "Roboto-Bold"
18
+ "regular": "",
19
+ "medium": "",
20
+ "bold": ""
21
21
  },
22
22
  "fontSize": {
23
23
  "small": 12,
@@ -25,10 +25,20 @@
25
25
  "target": "android/android_signing.json",
26
26
  "condition": "true"
27
27
  },
28
+ {
29
+ "source": "ios/xcassets/",
30
+ "target": "ios/xcassets/",
31
+ "condition": "true"
32
+ },
28
33
  {
29
34
  "source": "ios/assets/",
30
35
  "target": "ios/assets/",
31
- "condition": "true"
36
+ "condition": "true"
37
+ },
38
+ {
39
+ "source": "ios/InfoPlist.xcstrings",
40
+ "target": "ios/InfoPlist.xcstrings",
41
+ "condition": "true"
32
42
  },
33
43
  {
34
44
  "source": "ios/ios_config.json",
@@ -25,11 +25,21 @@
25
25
  "target": "android/android_signing.json",
26
26
  "condition": "true"
27
27
  },
28
+ {
29
+ "source": "ios/xcassets/",
30
+ "target": "ios/xcassets/",
31
+ "condition": "true"
32
+ },
28
33
  {
29
34
  "source": "ios/assets/",
30
35
  "target": "ios/assets/",
31
36
  "condition": "true"
32
37
  },
38
+ {
39
+ "source": "ios/InfoPlist.xcstrings",
40
+ "target": "ios/InfoPlist.xcstrings",
41
+ "condition": "true"
42
+ },
33
43
  {
34
44
  "source": "ios/ios_config.json",
35
45
  "target": "ios/ios_config.json",
@@ -41,8 +51,8 @@
41
51
  "condition": "true"
42
52
  },
43
53
  {
44
- "source": "shared/assets/",
45
- "target": "shared/assets/",
54
+ "source": "flutter/assets/",
55
+ "target": "flutter/assets/",
46
56
  "condition": "true"
47
57
  },
48
58
  {
@@ -25,15 +25,25 @@
25
25
  "target": "android/android_signing.json",
26
26
  "condition": "true"
27
27
  },
28
+ {
29
+ "source": "ios/xcassets/",
30
+ "target": "ios/xcassets/",
31
+ "condition": "true"
32
+ },
28
33
  {
29
34
  "source": "ios/assets/",
30
35
  "target": "ios/assets/",
31
36
  "condition": "true"
32
37
  },
38
+ {
39
+ "source": "ios/InfoPlist.xcstrings",
40
+ "target": "ios/InfoPlist.xcstrings",
41
+ "condition": "true"
42
+ },
33
43
  {
34
44
  "source": "ios/ios_config.json",
35
45
  "target": "ios/ios_config.json",
36
- "condition": "true"
46
+ "condition": "true"
37
47
  },
38
48
  {
39
49
  "source": "ios/ios_signing.json",
@@ -15,9 +15,14 @@ class ProjectTemplateGenerator
15
15
  source_path = File.join(@template_dir, file["source"])
16
16
  target_path = File.join(@target_dir, file["target"])
17
17
 
18
- copy_content = file.fetch("copy_content", true)
19
- copy_item(source_path, target_path, copy_content)
20
- replace_variables(target_path, @config["variables"]) if copy_content
18
+ if file["source"].nil? || file["source"].empty? || !File.exist?(source_path)
19
+ # Create the target directory if no source path is provided
20
+ FileUtils.mkdir_p(target_path)
21
+ else
22
+ copy_content = file.fetch("copy_content", true)
23
+ copy_item(source_path, target_path, copy_content)
24
+ replace_variables(target_path, @config["variables"]) if copy_content
25
+ end
21
26
  end
22
27
  end
23
28
  end
@@ -1,3 +1,3 @@
1
1
  module Solara
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.2"
3
3
  end
data/solara/lib/solara.rb CHANGED
@@ -54,6 +54,10 @@ module Solara
54
54
  brand_name = options['brand_name']
55
55
  input_platform = options['platform']
56
56
 
57
+ if !brand_key || !brand_name
58
+ Solara.logger.warn('To set up Solara, we need to onboard an initial brand. Please provide the following details for your first brand:')
59
+ end
60
+
57
61
  brand_key = validate_brand_key(brand_key, ignore_brand_check: true)
58
62
  brand_name = validate_brand_name(brand_name)
59
63
 
@@ -66,7 +70,7 @@ module Solara
66
70
  platform = platform.to_s.downcase
67
71
 
68
72
  SolaraSettingsManager.instance.platform = platform
69
- SolaraManager.new.init(platform, brand_key, brand_name)
73
+ SolaraManager.new.init(brand_key, brand_name)
70
74
  end
71
75
 
72
76
  desc "status", "Check the current status of Solara. The results may include information about the brand's current standing, the list of brands, and additional details."
@@ -142,7 +146,7 @@ module Solara
142
146
  brand_key = validate_brand_key(brand_key)
143
147
  begin
144
148
  SolaraManager.new.switch(brand_key)
145
- rescue StandardError => e
149
+ rescue Issue => e
146
150
  Solara.logger.fatal("Switching to #{brand_key} failed.")
147
151
  exit 1
148
152
  end
@@ -192,7 +196,7 @@ module Solara
192
196
  return brand_key
193
197
  end
194
198
 
195
- if brand_key.nil? || brand_key.empty? || (!ignore_brand_check && BrandsManager.instance.find(brand_key).nil?)
199
+ if brand_key.nil? || brand_key.empty? || (!ignore_brand_check && !BrandsManager.instance.exists(brand_key))
196
200
  message = message || (brand_key.nil? || brand_key.empty? ? "Please enter brand key: " : "Please enter existing brand key: ")
197
201
  brand_key = TerminalInputManager.new.get_validated(message) do |input|
198
202
  # Validate that it starts with a letter and contains no spaces
@@ -202,7 +206,7 @@ module Solara
202
206
  end
203
207
 
204
208
  # Check if the brand exists in the list
205
- if !ignore_brand_check && BrandsManager.instance.find(input).nil?
209
+ if !ignore_brand_check && !BrandsManager.instance.exists(input)
206
210
  Solara.logger.failure("Brand key does not exist.")
207
211
  next false # Use `next` to continue the loop
208
212
  end
@@ -20,12 +20,15 @@ class SolaraInitializer
20
20
  def init
21
21
  Solara.logger.header("Initializing Solara")
22
22
  confirm_init_if_necessary
23
+
24
+ ProjectDoctor.new.visit
25
+
23
26
  message = "Initialized #{SolaraSettingsManager.instance.platform} successfully."
24
27
  SolaraManager.new.onboard(@brand_key, @brand_name, init: true, success_message: message)
25
28
  end
26
29
 
27
30
  def confirm_init_if_necessary
28
- brand_path = File.join(FilePath.solara, 'brands')
31
+ brand_path = FilePath.brands
29
32
  # Check if Solara path exists
30
33
  if Dir.exist?(brand_path)
31
34
  Solara.logger.warn("Solara already initialized! Be aware that reinitializing will delete all current brands!")
@@ -37,7 +40,7 @@ class SolaraInitializer
37
40
  Solara.logger.info("Solara initialization cancelled.")
38
41
  exit 1
39
42
  end
40
- FileUtils.rm_rf(brand_path)
43
+ FileManager.delete_if_exists(brand_path)
41
44
  end
42
45
  end
43
46