solara 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/solara/lib/.DS_Store +0 -0
  3. data/solara/lib/core/.DS_Store +0 -0
  4. data/solara/lib/core/brands/brand_switcher.rb +58 -1
  5. data/solara/lib/core/dashboard/brand/BrandDetail.js +34 -2
  6. data/solara/lib/core/dashboard/brand/BrandDetailController.js +23 -233
  7. data/solara/lib/core/dashboard/brand/BrandDetailModel.js +13 -5
  8. data/solara/lib/core/dashboard/brand/BrandDetailView.js +16 -200
  9. data/solara/lib/core/dashboard/brand/SectionsFormManager.js +232 -0
  10. data/solara/lib/core/dashboard/brand/brand.html +187 -177
  11. data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +2 -5
  12. data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +36 -133
  13. data/solara/lib/core/dashboard/brands/Brands.js +31 -0
  14. data/solara/lib/core/dashboard/brands/BrandsController.js +0 -5
  15. data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
  16. data/solara/lib/core/dashboard/brands/brands.html +71 -52
  17. data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +6 -6
  18. data/solara/lib/core/dashboard/component/BrandOptionsBottomSheet.js +4 -4
  19. data/solara/lib/core/dashboard/component/ConfirmationDialog.js +15 -10
  20. data/solara/lib/core/dashboard/component/EditJsonSheet.js +160 -0
  21. data/solara/lib/core/dashboard/component/MessageBottomSheet.js +5 -5
  22. data/solara/lib/core/dashboard/component/OnboardBrandBottomSheet.js +5 -3
  23. data/solara/lib/core/dashboard/handler/base_handler.rb +1 -0
  24. data/solara/lib/core/dashboard/handler/edit_section_handler.rb +1 -5
  25. data/solara/lib/core/doctor/schema/brand_configurations.json +0 -8
  26. data/solara/lib/core/doctor/schema/platform/global/resources_manifest.json +30 -0
  27. data/solara/lib/core/doctor/schema/platform/json_manifest.json +57 -0
  28. data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +35 -1
  29. data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +30 -1
  30. data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +35 -1
  31. data/solara/lib/core/doctor/validator/template/template_validator.rb +9 -9
  32. data/solara/lib/core/scripts/brand_config_manager.rb +1 -1
  33. data/solara/lib/core/scripts/brand_configurations_manager.rb +41 -0
  34. data/solara/lib/core/scripts/code_generator.rb +342 -118
  35. data/solara/lib/core/scripts/file_path.rb +21 -1
  36. data/solara/lib/core/scripts/gitignore_manager.rb +11 -3
  37. data/solara/lib/core/scripts/json_manifest_processor.rb +95 -0
  38. data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +11 -1
  39. data/solara/lib/core/scripts/resource_manifest_processor.rb +151 -0
  40. data/solara/lib/core/scripts/solara_status_manager.rb +1 -1
  41. data/solara/lib/core/scripts/theme_generator.rb +21 -242
  42. data/solara/lib/core/solara_configurator.rb +1 -1
  43. data/solara/lib/core/template/brands/global/resources_manifest.json +10 -0
  44. data/solara/lib/core/template/brands/json/Json-Manifest.md +61 -0
  45. data/solara/lib/core/template/brands/json/json_manifest.json +18 -0
  46. data/solara/lib/core/template/brands/shared/theme.json +213 -29
  47. data/solara/lib/core/template/config/android_template_config.json +50 -0
  48. data/solara/lib/core/template/config/flutter_template_config.json +35 -0
  49. data/solara/lib/core/template/config/ios_template_config.json +50 -0
  50. data/solara/lib/core/template/configurations.json +46 -0
  51. data/solara/lib/core/template/project_template_generator.rb +2 -0
  52. data/solara/lib/solara/version.rb +1 -1
  53. data/solara/lib/solara.rb +19 -0
  54. metadata +13 -4
  55. data/solara/lib/core/dashboard/component/AddFieldSheet.js +0 -175
  56. data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +0 -73
@@ -99,6 +99,14 @@ module FilePath
99
99
  File.join(brands, brand_key)
100
100
  end
101
101
 
102
+ def self.brand_json_dir(brand_key, platform = nil)
103
+ File.join(brand(brand_key), platform || SolaraSettingsManager.instance.platform, 'json')
104
+ end
105
+
106
+ def self.brand_global_json_dir
107
+ File.join(global, 'json')
108
+ end
109
+
102
110
  def self.android_config(brand_key)
103
111
  File.join(android_brand_root(brand_key), 'android_config.json')
104
112
  end
@@ -116,7 +124,15 @@ module FilePath
116
124
  end
117
125
 
118
126
  def self.brand_fonts
119
- File.join(solara_brand, 'global', 'fonts')
127
+ File.join(global, 'fonts')
128
+ end
129
+
130
+ def self.resources_manifest
131
+ File.join(global, 'resources_manifest.json')
132
+ end
133
+
134
+ def self.global
135
+ File.join(solara_brand, 'global')
120
136
  end
121
137
 
122
138
  def self.brand_config(brand_key)
@@ -287,6 +303,10 @@ module FilePath
287
303
  File.join(root, 'core', 'template')
288
304
  end
289
305
 
306
+ def self.brand_configurations
307
+ File.join(solara_template, 'configurations.json')
308
+ end
309
+
290
310
  def self.solara_aliases_json
291
311
  File.join(dot_solara, 'aliases', 'aliases.json')
292
312
  end
@@ -4,7 +4,7 @@ class GitignoreManager
4
4
  create_gitignore_if_not_exists
5
5
  end
6
6
 
7
- def self.ignore
7
+ def self.ignore_common_files
8
8
  Solara.logger.start_step("Exclude Brand-Generated Files and Folders from Git")
9
9
 
10
10
  items = [
@@ -29,7 +29,7 @@ class GitignoreManager
29
29
 
30
30
  def add_items(items)
31
31
  items.each do |item|
32
- add_item(item)
32
+ add_item(FileManager.get_relative_path_to_root(item))
33
33
  end
34
34
  end
35
35
 
@@ -39,7 +39,15 @@ class GitignoreManager
39
39
  if existing_items.include?(item)
40
40
  Solara.logger.debug("'#{item}' already exists in .gitignore")
41
41
  else
42
- File.open(@gitignore_path, 'a') do |file|
42
+ File.open(@gitignore_path, 'a+') do |file|
43
+ # Move the file pointer to the beginning to check the last character
44
+ file.seek(0, IO::SEEK_END)
45
+ if file.size > 0
46
+ # Only add a new line if the last character is not a newline
47
+ file.seek(-1, IO::SEEK_END)
48
+ last_char = file.getc
49
+ file.puts if last_char != "\n"
50
+ end
43
51
  file.puts(item)
44
52
  end
45
53
  Solara.logger.debug("Added '#{item}' to .gitignore")
@@ -0,0 +1,95 @@
1
+ require 'json'
2
+
3
+ class JsonManifestProcessor
4
+
5
+ def initialize(json_path, language, output_path)
6
+ @json_path = json_path
7
+ @language = language
8
+ @output_path = output_path
9
+ end
10
+
11
+ def process
12
+ manifest = read_json
13
+ process_files(manifest)
14
+ end
15
+
16
+ private
17
+
18
+ def process_files(manifest)
19
+ manifest['files'].each do |file|
20
+ generate_code(file)
21
+ end
22
+ end
23
+
24
+ def generate_code(file)
25
+ return unless file['generate']['enabled']
26
+
27
+ file_name = file['fileName']
28
+ class_name = file['generate']['className']
29
+
30
+ puts "generate_code: file_name = #{file_name}, class_name = #{class_name}"
31
+ return if file_name.empty? || class_name.empty?
32
+ puts "generate_code: file_name = #{file_name}, class_name = #{class_name}"
33
+
34
+ custom_class_names = convert_to_map(file['generate']['customClassNames'])
35
+
36
+ file_path = File.join(@json_path, file_name)
37
+ code_generator = CodeGenerator.new(
38
+ json: JSON.parse(File.read(file_path)),
39
+ language: @language ,
40
+ parent_class_name: class_name,
41
+ custom_types: custom_class_names
42
+ )
43
+
44
+ generated_code = code_generator.generate
45
+
46
+ output_path = File.join(@output_path, gnerated_filename(class_name))
47
+ write_to_file(output_path, generated_code)
48
+ end
49
+
50
+ def gnerated_filename(class_name)
51
+ case SolaraSettingsManager.instance.platform
52
+ when Platform::Flutter
53
+ "#{to_snake_case(class_name)}.dart"
54
+ when Platform::IOS
55
+ "#{class_name}.swift"
56
+ when Platform::Android
57
+ "#{class_name}.kt"
58
+ else
59
+ raise ArgumentError, "Invalid platform: #{@platform}"
60
+ end
61
+ end
62
+
63
+ def to_snake_case(string)
64
+ string.gsub(/[A-Z]/) { |match| "_#{match.downcase}" }.sub(/^_/, '')
65
+ end
66
+
67
+ def write_to_file(output, content)
68
+ puts "generate_code: output = #{output}, content = #{content}"
69
+ File.write(output, content)
70
+ Solara.logger.debug("Genrated #{output}")
71
+ rescue StandardError => e
72
+ Solara.logger.debug("Error writing to file #{file_name}: #{e.message}")
73
+ end
74
+
75
+ def convert_to_map(custom_class_names)
76
+ custom_class_names.each_with_object({}) do |item, result|
77
+ result[item['generatedName']] = item['customName']
78
+ end
79
+ end
80
+
81
+ def read_json
82
+ mainfest_path = File.join(@json_path, 'json_manifest.json')
83
+ JSON.parse(File.read(mainfest_path))
84
+ rescue JSON::ParserError => e
85
+ Solara.logger.debug("Error parsing JSON: #{e.message}")
86
+ {}
87
+ rescue Errno::ENOENT => e
88
+ Solara.logger.debug("Error reading file: #{e.message}")
89
+ {}
90
+ rescue StandardError => e
91
+ Solara.logger.debug("Unexpected error: #{e.message}")
92
+ {}
93
+ end
94
+
95
+ end
@@ -2,12 +2,22 @@ require 'json'
2
2
 
3
3
  module StringCatalogUtils
4
4
  def load_string_catalog(path)
5
+ @path = path
5
6
  JSON.parse(File.read(path))
6
7
  end
7
8
 
8
9
  def get_value(data, key, target, language)
9
10
  lang = language || data['sourceLanguage']
10
- data['strings'][key]['localizations'][lang]['stringUnit'][target]
11
+ localizations = data.dig('strings', key, 'localizations', lang)
12
+
13
+ unless localizations && localizations['stringUnit']
14
+ error_message = "The default language is #{lang}, but no localizations are available for key '#{key}'. Please address this issue in {@path}. You can easily open the file in Xcode to make the necessary adjustments."
15
+ Solara.logger.fatal(error_message)
16
+ exit 1
17
+ end
18
+
19
+ string_unit = localizations['stringUnit']
20
+ string_unit[target]
11
21
  end
12
22
 
13
23
  def has_value?(data, key, language)
@@ -0,0 +1,151 @@
1
+ require 'json'
2
+ require 'fileutils'
3
+
4
+ class ResourceManifestProcessor
5
+ def initialize(brand_key)
6
+ @brand_key = brand_key
7
+ @manifest_file = FilePath.resources_manifest
8
+ @config = load_manifest_file
9
+ end
10
+
11
+ def copy
12
+ @base_source_path = FilePath.brands
13
+ @base_destination_path = FilePath.project_root
14
+ @config['files'].each do |item|
15
+ process_file_item(item)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def clean(item, src, dst)
22
+ paths = destinations(item, src, dst)
23
+ paths.each do |path|
24
+ File.delete(path) if File.exist?(path)
25
+ end
26
+ end
27
+
28
+ def process_file_item(item)
29
+ src = resolve_source_path(@brand_key, item['source'], @base_source_path)
30
+ dst = File.join(@base_destination_path, item['destination'])
31
+
32
+ clean(item, src, dst)
33
+
34
+ return skip_empty_paths(item) if empty_paths?(item)
35
+
36
+ check_mandatory_file(item, src, dst)
37
+
38
+ if File.exist?(src)
39
+ copy_file(src, dst)
40
+ git_ignore(destinations(item, src, dst))
41
+ else
42
+ log_file_not_found(item)
43
+ end
44
+ end
45
+
46
+ def destinations(item, src, dst, visited = {})
47
+ return [] if visited[src]
48
+
49
+ visited[src] = true # Mark the current source as visited
50
+
51
+ if File.file?(src)
52
+ if File.directory?(dst)
53
+ return [File.join(dst, File.basename(src))]
54
+ else
55
+ return [dst]
56
+ end
57
+ elsif File.directory?(src)
58
+ return destinations_of_directory_contents(src, dst)
59
+ end
60
+
61
+ if !item['mandatory'] && !File.file?(src)
62
+ return get_optional_resource_destination(item, dst, visited)
63
+ end
64
+
65
+ []
66
+ end
67
+
68
+ def get_optional_resource_destination(item, dst, visited)
69
+ return [] if item['mandatory']
70
+ keys = BrandsManager.instance.brands_list.map { |brand| brand['key'] }
71
+ keys.each do |key|
72
+ src = resolve_source_path(key, item['source'], @base_source_path)
73
+ result = destinations(item, src, dst, visited)
74
+ return result unless result.empty?
75
+ end
76
+ []
77
+ end
78
+
79
+ def destinations_of_directory_contents(src_dir, dst_dir)
80
+ items = []
81
+ Dir.foreach(src_dir) do |file|
82
+ next if file == '.' || file == '..'
83
+ full_dst_path = File.join(dst_dir, file)
84
+ items << full_dst_path
85
+ end
86
+ items
87
+ end
88
+
89
+ def git_ignore(files)
90
+ files.each do |file|
91
+ GitignoreManager.new(FilePath.project_root).add_items([file])
92
+ end
93
+ end
94
+
95
+ def resolve_source_path(brand_key, source, base_source_path)
96
+ source.gsub(/\{.*?\}/, brand_key).prepend(base_source_path + '/')
97
+ end
98
+
99
+ def empty_paths?(item)
100
+ item['source'].empty? || item['destination'].empty?
101
+ end
102
+
103
+ def skip_empty_paths(item)
104
+ Solara.logger.debug("Skipped (empty source or destination) for #{@brand_key}: #{item['source']} -> #{item['destination']}")
105
+ end
106
+
107
+ def check_mandatory_file(item, src, dst)
108
+ if item['mandatory'] && !File.exist?(src)
109
+ Solara.logger.fatal("Mandatory resource file/folder not found for #{@brand_key}: #{src}. Please add the resource or mark it as not mandatory in #{FilePath.resources_manifest}.")
110
+ exit 1
111
+ end
112
+
113
+ end
114
+
115
+ def copy_file(src, dst)
116
+ if File.directory?(src)
117
+ FileUtils.mkdir_p(dst)
118
+ FileUtils.cp_r(File.join(src, '.'), dst)
119
+ else
120
+ FileUtils.mkdir_p(File.dirname(dst))
121
+ FileUtils.cp(src, dst)
122
+ end
123
+ Solara.logger.debug("Copied resource for #{@brand_key}: #{File.basename(src)} to #{File.basename(dst)}")
124
+ end
125
+
126
+ def log_file_not_found(item)
127
+ Solara.logger.debug("Skipped resource (not found) for #{@brand_key}: #{item['source']}")
128
+ end
129
+
130
+ def load_manifest_file
131
+ validate_manifest_file_existence
132
+ parse_manifest_file
133
+ end
134
+
135
+ def validate_manifest_file_existence
136
+ unless File.exist?(@manifest_file)
137
+ Solara.logger.fatal("Brand switch copy manifest not found for #{@brand_key}: #{@manifest_file}")
138
+ exit 1
139
+ end
140
+ end
141
+
142
+ def parse_manifest_file
143
+ begin
144
+ JSON.parse(File.read(@manifest_file))
145
+ rescue JSON::ParserError => e
146
+ Solara.logger.fatal("Invalid brand switch copy manifest for #{@brand_key}: #{e.message}")
147
+ exit 1
148
+ end
149
+ end
150
+
151
+ end
@@ -37,7 +37,7 @@ class SolaraStatusManager
37
37
 
38
38
  solara dashboard -k #{current_brand['key']}
39
39
 
40
- Then, click the "Apply Changes" button.
40
+ Then, click the "Sync" button.
41
41
  MESSAGE
42
42
  Solara.logger.info(message)
43
43
  end
@@ -1,253 +1,32 @@
1
1
  require 'json'
2
2
  require 'fileutils'
3
3
 
4
- class ThemeGeneratorManager
4
+ class ThemeGenerator
5
5
  def initialize(input_path)
6
6
  @input_path = input_path
7
7
  end
8
8
 
9
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
20
- end
21
-
22
- generator.generate
23
- end
24
- end
25
-
26
- class ThemeGenerator
27
- def initialize(input_path, output_path)
28
- @theme = JSON.parse(File.read(input_path))
29
- @output_path = output_path
30
- end
31
-
32
- def write_to_file(code)
33
- FileUtils.mkdir_p(File.dirname(@output_path))
34
- File.write(@output_path, code)
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)
50
- end
51
-
52
- private
53
-
54
- def generate_colors
55
- code = " object Colors {\n"
56
- @theme['colors'].each do |name, value|
57
- code += " val #{name} = Color.parseColor(\"#{value}\")\n"
58
- end
59
- code + " }\n\n"
60
- end
61
-
62
- def generate_typography
63
- code = " object Typography {\n"
64
- code += " object FontFamily {\n"
65
- @theme['typography']['fontFamily'].each do |name, value|
66
- code += " val #{name} = \"#{value}\"\n"
67
- end
68
- code += " }\n\n"
69
- code += " object FontSize {\n"
70
- @theme['typography']['fontSize'].each do |name, value|
71
- code += " val #{name} = #{value}\n"
72
- end
73
- code += " }\n"
74
- code + " }\n\n"
75
- end
76
-
77
- def generate_spacing
78
- code = " object Spacing {\n"
79
- @theme['spacing'].each do |name, value|
80
- code += " val #{name} = #{value}\n"
81
- end
82
- code + " }\n\n"
83
- end
84
-
85
- def generate_border_radius
86
- code = " object BorderRadius {\n"
87
- @theme['borderRadius'].each do |name, value|
88
- code += " val #{name} = #{value}\n"
89
- end
90
- code + " }\n\n"
91
- end
92
-
93
- def generate_elevation
94
- code = " object Elevation {\n"
95
- @theme['elevation'].each do |name, value|
96
- code += " val #{name} = #{value}\n"
97
- end
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)
114
- end
115
-
116
- private
117
-
118
- def generate_colors
119
- code = " struct Colors {\n"
120
- @theme['colors'].each do |name, value|
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)
10
+ config_generator = CodeGenerator.new(
11
+ json: JSON.parse(File.read(@input_path)),
12
+ language: language,
13
+ parent_class_name: 'BrandTheme',
14
+ custom_types: {
15
+ "BrandThemeColorSchemes" => "BrandColorScheme",
16
+ "BrandThemeTypography" => "BrandTypography",
17
+ "BrandThemeSpacing" => "BrandSpacing",
18
+ "BrandThemeBorderRadius" => "BrandBorderRadius",
19
+ "BrandThemeElevation" => "BrandElevation",
20
+ "BrandThemeOpacity" => "BrandOpacity",
21
+ "BrandThemeAnimation" => "BrandAnimation",
22
+ "BrandThemeBreakpoints" => "BrandBreakpoints",
23
+ "BrandThemeColorSchemesLight" => "BrandLightColorScheme",
24
+ "BrandThemeColorSchemesDark" => "BrandDarkColorScheme",
143
25
  }
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
- }
152
- }
153
- SWIFT
154
- end
155
-
156
- def generate_typography
157
- code = " struct Typography {\n"
158
- code += " struct FontFamily {\n"
159
- @theme['typography']['fontFamily'].each do |name, value|
160
- code += " static let #{name} = \"#{value}\"\n"
161
- end
162
- code += " }\n\n"
163
- code += " struct FontSize {\n"
164
- @theme['typography']['fontSize'].each do |name, value|
165
- code += " static let #{name}: CGFloat = #{value}\n"
166
- end
167
- code += " }\n"
168
- code + " }\n\n"
169
- end
170
-
171
- def generate_spacing
172
- code = " struct Spacing {\n"
173
- @theme['spacing'].each do |name, value|
174
- code += " static let #{name}: CGFloat = #{value}\n"
175
- end
176
- code + " }\n\n"
177
- end
178
-
179
- def generate_border_radius
180
- code = " struct BorderRadius {\n"
181
- @theme['borderRadius'].each do |name, value|
182
- code += " static let #{name}: CGFloat = #{value}\n"
183
- end
184
- code + " }\n\n"
185
- end
186
-
187
- def generate_elevation
188
- code = " struct Elevation {\n"
189
- @theme['elevation'].each do |name, value|
190
- code += " static let #{name}: CGFloat = #{value}\n"
191
- end
192
- code + " }\n"
26
+ )
27
+ content = config_generator.generate
28
+ FileManager.create_file_if_not_exist(output_path)
29
+ File.write(output_path, content)
30
+ Solara.logger.debug("Generated theme file: #{output_path}")
193
31
  end
194
32
  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)
205
- end
206
-
207
- private
208
-
209
- def generate_colors
210
- code = " class BrandColors {\n"
211
- @theme['colors'].each do |name, value|
212
- code += " static const Color #{name} = Color(0xFF#{value[1..-1]});\n"
213
- end
214
- code + " }\n\n"
215
- end
216
-
217
- def generate_typography
218
- code = " class FontFamily {\n"
219
- @theme['typography']['fontFamily'].each do |name, value|
220
- code += " static const String #{name} = '#{value}';\n"
221
- end
222
- code += " }\n\n"
223
- code += " class FontSize {\n"
224
- @theme['typography']['fontSize'].each do |name, value|
225
- code += " static const double #{name} = #{value};\n"
226
- end
227
- code + " }\n\n"
228
- end
229
-
230
- def generate_spacing
231
- code = " class Spacing {\n"
232
- @theme['spacing'].each do |name, value|
233
- code += " static const double #{name} = #{value};\n"
234
- end
235
- code + " }\n\n"
236
- end
237
-
238
- def generate_border_radius
239
- code = " class BorderRadius {\n"
240
- @theme['borderRadius'].each do |name, value|
241
- code += " static const double #{name} = #{value};\n"
242
- end
243
- code += " }\n\n"
244
- end
245
-
246
- def generate_elevation
247
- code = " class Elevation {\n"
248
- @theme['elevation'].each do |name, value|
249
- code += " static const double #{name} = #{value};\n"
250
- end
251
- code + " }\n"
252
- end
253
- end
@@ -7,7 +7,7 @@ class SolaraConfigurator
7
7
  end
8
8
 
9
9
  def start
10
- GitignoreManager.ignore
10
+ GitignoreManager.ignore_common_files
11
11
  AliasManager.new.start
12
12
  end
13
13
 
@@ -0,0 +1,10 @@
1
+ {
2
+ "description": "This file outlines the resources to be transferred from the brand source to the codebase during the switching process.",
3
+ "files": [
4
+ {
5
+ "source": "",
6
+ "destination": "",
7
+ "mandatory": true
8
+ }
9
+ ]
10
+ }