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.
- checksums.yaml +4 -4
- data/solara/lib/core/.DS_Store +0 -0
- data/solara/lib/core/aliases/alias_generator.rb +1 -0
- data/solara/lib/core/aliases/alias_generator_manager.rb +2 -1
- data/solara/lib/core/aliases/solara_terminal_setup.rb +1 -1
- data/solara/lib/core/brands/brand_font_switcher.rb +154 -0
- data/solara/lib/core/brands/brand_onboarder.rb +8 -6
- data/solara/lib/core/brands/brand_switcher.rb +232 -166
- data/solara/lib/core/brands/brands_manager.rb +15 -39
- data/solara/lib/core/dashboard/brand/BrandDetail.js +19 -0
- data/solara/lib/core/dashboard/brand/BrandDetailController.js +50 -8
- data/solara/lib/core/dashboard/brand/BrandDetailModel.js +9 -30
- data/solara/lib/core/dashboard/brand/BrandDetailView.js +49 -3
- data/solara/lib/core/dashboard/brand/InfoPlistStringCatalogManager.js +19 -0
- data/solara/lib/core/dashboard/brand/brand.html +209 -62
- data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +1 -1
- data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +38 -53
- data/solara/lib/core/dashboard/brands/BrandsController.js +6 -5
- data/solara/lib/core/dashboard/brands/BrandsModel.js +2 -2
- data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
- data/solara/lib/core/dashboard/brands/brands.html +3 -1
- data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +7 -5
- data/solara/lib/core/dashboard/dashboard_manager.rb +2 -0
- data/solara/lib/core/dashboard/dashboard_server.rb +13 -8
- data/solara/lib/core/dashboard/handler/brand_alisases_handler.rb +4 -11
- data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +11 -11
- data/solara/lib/core/dashboard/handler/{brand_configurations_handler.rb → brand_details_handler.rb} +4 -4
- data/solara/lib/core/dashboard/handler/brands_handler.rb +1 -1
- data/solara/lib/core/dashboard/handler/edit_section_handler.rb +8 -8
- data/solara/lib/core/doctor/brand_doctor.rb +31 -31
- data/solara/lib/core/doctor/doctor_manager.rb +0 -1
- data/solara/lib/core/doctor/project_doctor.rb +0 -1
- data/solara/lib/core/doctor/schema/platform/android/android_config.json +0 -4
- data/solara/lib/core/doctor/schema/platform/ios/InfoPlist.xcstrings +15 -0
- data/solara/lib/core/doctor/schema/platform/ios/ios_config.json +0 -5
- data/solara/lib/core/doctor/schema/platform/shared/brand_config.json +9 -0
- data/solara/lib/core/doctor/schema/platform/shared/theme.json +94 -9
- data/solara/lib/core/doctor/validator/brand_settings_validator.rb +6 -0
- data/solara/lib/core/doctor/validator/brand_settings_validator_manager.rb +9 -21
- data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +22 -4
- data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +22 -6
- data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +22 -4
- data/solara/lib/core/scripts/brand_config_generator.rb +1 -0
- data/solara/lib/core/scripts/brand_config_manager.rb +2 -4
- data/solara/lib/core/scripts/brand_exporter.rb +1 -1
- data/solara/lib/core/scripts/brand_importer.rb +2 -3
- data/solara/lib/core/scripts/brand_offboarder.rb +5 -0
- data/solara/lib/core/scripts/brand_resources_manager.rb +127 -54
- data/solara/lib/core/scripts/directory_creator.rb +2 -2
- data/solara/lib/core/scripts/file_manager.rb +53 -19
- data/solara/lib/core/scripts/file_path.rb +175 -30
- data/solara/lib/core/scripts/folder_copier.rb +3 -7
- data/solara/lib/core/scripts/gitignore_manager.rb +21 -10
- data/solara/lib/core/scripts/interactive_file_system_validator.rb +8 -2
- data/solara/lib/core/scripts/platform/android/android_manifest_switcher.rb +3 -3
- data/solara/lib/core/scripts/platform/android/android_strings_switcher.rb +26 -24
- data/solara/lib/core/scripts/platform/android/gradle_switcher.rb +7 -6
- data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +123 -0
- data/solara/lib/core/scripts/platform/ios/infoplist_switcher.rb +59 -0
- data/solara/lib/core/scripts/platform/ios/ios_plist_manager.rb +11 -20
- data/solara/lib/core/scripts/platform/ios/plist_font_manager.rb +33 -0
- data/solara/lib/core/scripts/platform/ios/xcconfig_generator.rb +15 -3
- data/solara/lib/core/scripts/platform/ios/xcode_asset_manager.rb +2 -3
- data/solara/lib/core/scripts/platform/ios/xcode_project_manager.rb +80 -1
- data/solara/lib/core/scripts/platform/ios/xcode_project_switcher.rb +15 -34
- data/solara/lib/core/scripts/solara_logger.rb +10 -0
- data/solara/lib/core/scripts/solara_settings_manager.rb +26 -1
- data/solara/lib/core/scripts/strings_xml_manager.rb +17 -2
- data/solara/lib/core/scripts/theme_generator.rb +133 -130
- data/solara/lib/core/scripts/yaml_manager.rb +23 -0
- data/solara/lib/core/solara_configurator.rb +1 -1
- data/solara/lib/core/template/brands/android/android_config.json +0 -1
- data/solara/lib/core/template/brands/android/res/values/strings.xml +4 -0
- data/solara/lib/core/template/brands/ios/InfoPlist.xcstrings +30 -0
- data/solara/lib/core/template/brands/ios/ios_config.json +1 -2
- data/solara/lib/core/template/brands/shared/brand_config.json +1 -0
- data/solara/lib/core/template/brands/shared/theme.json +3 -3
- data/solara/lib/core/template/config/android_template_config.json +11 -1
- data/solara/lib/core/template/config/flutter_template_config.json +12 -2
- data/solara/lib/core/template/config/ios_template_config.json +11 -1
- data/solara/lib/core/template/project_template_generator.rb +8 -3
- data/solara/lib/solara/version.rb +1 -1
- data/solara/lib/solara.rb +8 -4
- data/solara/lib/solara_initializer.rb +5 -2
- data/solara/lib/solara_manager.rb +1 -1
- metadata +62 -43
- data/solara/lib/core/dashboard/handler/brand_section_handler.rb +0 -20
- data/solara/lib/core/doctor/validator/directory_structure_validator.rb +0 -38
- data/solara/lib/core/doctor/validator/file_structure_validator.rb +0 -37
- data/solara/lib/core/scripts/platform/ios/ios_file_path_manager.rb +0 -109
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/.DS_Store +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/100.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/102.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/1024.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/114.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/120.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/128.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/144.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/152.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/16.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/167.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/172.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/180.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/196.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/20.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/216.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/256.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/29.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/32.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/40.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/48.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/50.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/512.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/55.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/57.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/58.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/60.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/64.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/66.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/72.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/76.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/80.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/87.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/88.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/92.png +0 -0
- /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
|
|
5
|
-
def initialize(input_path
|
|
6
|
-
@
|
|
7
|
-
|
|
8
|
-
@language = language.downcase
|
|
4
|
+
class ThemeGeneratorManager
|
|
5
|
+
def initialize(input_path)
|
|
6
|
+
@input_path = input_path
|
|
7
|
+
end
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
16
|
-
code = send("generate_#{@language}")
|
|
17
|
-
write_to_file(code)
|
|
22
|
+
generator.generate
|
|
18
23
|
end
|
|
24
|
+
end
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
57
|
+
code += " val #{name} = Color.parseColor(\"#{value}\")\n"
|
|
69
58
|
end
|
|
70
|
-
code
|
|
71
|
-
code
|
|
59
|
+
code + " }\n\n"
|
|
72
60
|
end
|
|
73
61
|
|
|
74
|
-
def
|
|
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}
|
|
71
|
+
code += " val #{name} = #{value}\n"
|
|
84
72
|
end
|
|
85
73
|
code += " }\n"
|
|
86
|
-
code
|
|
87
|
-
code
|
|
74
|
+
code + " }\n\n"
|
|
88
75
|
end
|
|
89
76
|
|
|
90
|
-
def
|
|
77
|
+
def generate_spacing
|
|
91
78
|
code = " object Spacing {\n"
|
|
92
79
|
@theme['spacing'].each do |name, value|
|
|
93
|
-
code += " val #{name} = #{value}
|
|
80
|
+
code += " val #{name} = #{value}\n"
|
|
94
81
|
end
|
|
95
|
-
code
|
|
96
|
-
code
|
|
82
|
+
code + " }\n\n"
|
|
97
83
|
end
|
|
98
84
|
|
|
99
|
-
def
|
|
85
|
+
def generate_border_radius
|
|
100
86
|
code = " object BorderRadius {\n"
|
|
101
87
|
@theme['borderRadius'].each do |name, value|
|
|
102
|
-
code += " val #{name} = #{value}
|
|
88
|
+
code += " val #{name} = #{value}\n"
|
|
103
89
|
end
|
|
104
|
-
code
|
|
105
|
-
code
|
|
90
|
+
code + " }\n\n"
|
|
106
91
|
end
|
|
107
92
|
|
|
108
|
-
def
|
|
93
|
+
def generate_elevation
|
|
109
94
|
code = " object Elevation {\n"
|
|
110
95
|
@theme['elevation'].each do |name, value|
|
|
111
|
-
code += " val #{name} = #{value}
|
|
96
|
+
code += " val #{name} = #{value}\n"
|
|
112
97
|
end
|
|
113
|
-
code
|
|
114
|
-
|
|
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
|
-
|
|
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} =
|
|
121
|
-
end
|
|
122
|
-
code
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
|
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
|
|
171
|
-
code
|
|
168
|
+
code + " }\n\n"
|
|
172
169
|
end
|
|
173
170
|
|
|
174
|
-
def
|
|
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
|
|
180
|
-
code
|
|
176
|
+
code + " }\n\n"
|
|
181
177
|
end
|
|
182
178
|
|
|
183
|
-
def
|
|
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
|
|
189
|
-
code
|
|
184
|
+
code + " }\n\n"
|
|
190
185
|
end
|
|
191
186
|
|
|
192
|
-
def
|
|
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
|
|
198
|
-
|
|
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
|
-
|
|
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
|
|
207
|
-
code
|
|
214
|
+
code + " }\n\n"
|
|
208
215
|
end
|
|
209
216
|
|
|
210
|
-
def
|
|
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
|
|
221
|
-
code
|
|
227
|
+
code + " }\n\n"
|
|
222
228
|
end
|
|
223
229
|
|
|
224
|
-
def
|
|
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
|
|
230
|
-
code
|
|
235
|
+
code + " }\n\n"
|
|
231
236
|
end
|
|
232
237
|
|
|
233
|
-
def
|
|
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
|
|
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
|
|
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
|
|
|
@@ -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
|
+
}
|
|
@@ -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": "
|
|
45
|
-
"target": "
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
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(
|
|
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
|
|
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.
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
43
|
+
FileManager.delete_if_exists(brand_path)
|
|
41
44
|
end
|
|
42
45
|
end
|
|
43
46
|
|