fastlane-plugin-framer 0.2.1 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +51 -26
- data/lib/fastlane/plugin/framer/actions/framer_action.rb +243 -56
- data/lib/fastlane/plugin/framer/version.rb +1 -1
- metadata +9 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7f483825329db96f65ffb7a835c9d859e458e25eba3f592312f5eecf9fc172b8
|
4
|
+
data.tar.gz: afc487ad12cec280e48a57fd8bd21314bd9eeba576eaf83c4bc64a8043b70a47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fe4de5acdb69e3bfd2ba3c3084bff037c4be88db36073c000917c7316ce0ee63ce4314aeb84069edec1cd180fea9b40d6d6dffa3e3496cff2135c814627f645
|
7
|
+
data.tar.gz: 42e043f83d7b16f9024e9e4aecd26b148cd04711c16b288edbdbf41085421bb3615505cf5ba511574d29a09af743474c40e58a1390a83bc1a6c0aeff0104af8d
|
data/README.md
CHANGED
@@ -24,11 +24,11 @@ You can specify the position and the size of the screen in the template and (opt
|
|
24
24
|
|
25
25
|
## Example
|
26
26
|
|
27
|
-
Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin.
|
27
|
+
Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin.
|
28
28
|
|
29
|
-
There are
|
29
|
+
There are 4 lanes: 1º for a simple flow (`demo-1`), 2º with more languages and screens (`demo-2`), 3ª for android screenshots with rotation images and more them one frame(`demo-3`) and last for ios screenshots (`demo-4`).
|
30
30
|
|
31
|
-
Try them by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane
|
31
|
+
Try them by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane` and select lane.
|
32
32
|
|
33
33
|
## Configuration
|
34
34
|
|
@@ -40,16 +40,16 @@ In order to work, you need to configure each template and the text to draw in th
|
|
40
40
|
|
41
41
|
The **framer** action support 4 optional parameters (default values are used).
|
42
42
|
|
43
|
-
| Option | Description
|
44
|
-
| ----------------- |
|
45
|
-
| `source_folder` | path to the folder that contains raw screenshots and `text.json` file
|
46
|
-
| `template_folder` | path to the folder that contains the templates images and configuration
|
43
|
+
| Option | Description | Default |
|
44
|
+
| ----------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------- |
|
45
|
+
| `source_folder` | path to the folder that contains raw screenshots and `text.json` file | `./fastlane/framer/screens` |
|
46
|
+
| `template_folder` | path to the folder that contains the templates images and configuration | `./fastlane/framer/templates` |
|
47
47
|
| `output_folder` | path to the folder that will contains the final images, framed. Used then by `deliver` | `./fastlane/screenshots` (default one for `deliver`) |
|
48
|
-
| `output_suffix` | filenam suffix for the framed images
|
48
|
+
| `output_suffix` | filenam suffix for the framed images | `-framed` |
|
49
49
|
|
50
50
|
### Template Configuration
|
51
51
|
|
52
|
-
In the template folder you choose, there must be a `
|
52
|
+
In the template folder you choose, there must be a `config.json` file (see [example](fastlane/demo-1/templates/config.json)). In there you will found
|
53
53
|
|
54
54
|
- a default configuration for all templates
|
55
55
|
- a custom configuration for each template (if needed).
|
@@ -76,39 +76,64 @@ There are keys for configuring screeshot and for the text.
|
|
76
76
|
|
77
77
|
#### Image
|
78
78
|
|
79
|
-
| Key
|
80
|
-
|
|
81
|
-
| `offset`
|
82
|
-
| `width`
|
83
|
-
| `add_below`
|
79
|
+
| Key | Type | Description |
|
80
|
+
| ----------- | ------: | -----------------------------------------------------------: |
|
81
|
+
| `offset` | String | Pixel position in the format `+[X value]+[Y value]` |
|
82
|
+
| `width` | Number | space available, in pixel, for the screen |
|
83
|
+
| `add_below` | Boolean | add screen below the template or not |
|
84
|
+
| `rotation` | Number | degrees for rotate image |
|
85
|
+
| `previous` | Object | same parameters as image, used to display the previous image |
|
86
|
+
| `next` | Object | same parameters as image, used to display the previous image |
|
84
87
|
|
85
88
|
#### Text
|
86
89
|
|
87
|
-
| Key
|
88
|
-
|
|
89
|
-
| `offset_x`
|
90
|
-
| `offset_y`
|
91
|
-
| `height`
|
92
|
-
| `size`
|
93
|
-
| `font`
|
94
|
-
| `color`
|
95
|
-
| `padding`
|
90
|
+
| Key | Type | Description |
|
91
|
+
| ---------- | -----: | -----------------------------------------------: |
|
92
|
+
| `offset_x` | Number | X position of the text block |
|
93
|
+
| `offset_y` | Number | Y position of the text block |
|
94
|
+
| `height` | Number | height of the text block |
|
95
|
+
| `size` | Number | font size |
|
96
|
+
| `font` | String | path of custom font file to use |
|
97
|
+
| `color` | String | color for the text in hex format (ex. `#545454`) |
|
98
|
+
| `padding` | Number | horizontal internal padding of the text block |
|
96
99
|
|
97
100
|
### Screenshots Text
|
98
101
|
|
99
102
|
If you want some text in the final framed images, you need to create a `text.json` file and put it with the raw device screenshots. It makes sense to commit this file in your repository.
|
100
103
|
|
101
|
-
`text.json` is a simple map where
|
102
|
-
The
|
104
|
+
`text.json` is a simple map where _key_ is the part of the screenshot filename (I suggest the same string you use with the `snapshot()` command on your UI tests.
|
105
|
+
The _value_ can be any strings.
|
106
|
+
|
107
|
+
### Colors
|
108
|
+
|
109
|
+
You can customize the color of the text and the background color applyed below the template (if you have transparencies on the template, you can fill them with the background color).
|
110
|
+
|
111
|
+
`colors.json` is a simple map where _key_ is part of the screenshot filename. The _value_ is a map with 2 optional keys, _text_ and _background_.
|
112
|
+
|
113
|
+
```
|
114
|
+
{
|
115
|
+
"default": {
|
116
|
+
"background": "#00FFFF",
|
117
|
+
"text": "#FFFFFF"
|
118
|
+
},
|
119
|
+
"demo": {
|
120
|
+
"background": "#FF00FF",
|
121
|
+
}
|
122
|
+
}
|
123
|
+
```
|
124
|
+
|
125
|
+
Default values can be defined inside the _default_ map.
|
103
126
|
|
104
127
|
## Run tests for this plugin
|
105
128
|
|
106
129
|
To run both the tests, and code style validation, run
|
130
|
+
|
107
131
|
```
|
108
132
|
rake
|
109
133
|
```
|
110
134
|
|
111
|
-
To automatically fix many of the styling issues, use
|
135
|
+
To automatically fix many of the styling issues, use
|
136
|
+
|
112
137
|
```
|
113
138
|
rubocop -a
|
114
139
|
```
|
@@ -3,13 +3,33 @@ require 'json'
|
|
3
3
|
|
4
4
|
module Fastlane
|
5
5
|
module Actions
|
6
|
+
|
6
7
|
class Template
|
7
8
|
attr_accessor :name
|
8
|
-
attr_accessor :
|
9
|
+
attr_accessor :width, :height
|
9
10
|
|
10
11
|
attr_accessor :file
|
11
|
-
attr_accessor :imageOffset, :imageWidth, :imageBelow
|
12
|
-
attr_accessor :
|
12
|
+
attr_accessor :imageOffset, :imageWidth, :imageBelow, :imageRotation
|
13
|
+
attr_accessor :imagePreviousOffset, :imagePreviousWidth, :imagePreviousRotation
|
14
|
+
attr_accessor :imageNextOffset, :imageNextWidth, :imageNextRotation
|
15
|
+
attr_accessor :textOffsetX, :textOffsetY, :textWidth, :textHeight, :textPadding, :textSize, :textFont
|
16
|
+
end
|
17
|
+
|
18
|
+
class Colors
|
19
|
+
attr_accessor :text, :background
|
20
|
+
|
21
|
+
def merge(other)
|
22
|
+
unless other.text.nil? || other.text.empty?
|
23
|
+
self.text = other.text
|
24
|
+
end
|
25
|
+
unless other.background.nil? || other.background.empty?
|
26
|
+
self.background = other.background
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"{ text: #{self.text}, background: #{self.background} }"
|
32
|
+
end
|
13
33
|
end
|
14
34
|
|
15
35
|
class FramerAction < Action
|
@@ -17,7 +37,9 @@ module Fastlane
|
|
17
37
|
source_folder = params[:source_folder]
|
18
38
|
output_folder = params[:output_folder]
|
19
39
|
template_folder = params[:template_folder]
|
40
|
+
list_files = Dir.glob("#{source_folder}/**/*.png").sort
|
20
41
|
templates = []
|
42
|
+
platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
|
21
43
|
|
22
44
|
# Read config
|
23
45
|
UI.success "Fetching templates from #{template_folder}"
|
@@ -25,24 +47,27 @@ module Fastlane
|
|
25
47
|
|
26
48
|
# Process each screen
|
27
49
|
UI.success "Processing screenshots from #{source_folder}"
|
28
|
-
|
29
|
-
UI.message "Processing #{file}"
|
30
|
-
|
31
|
-
template = self.find_template(templates, file)
|
32
|
-
text = self.find_text(source_folder, file)
|
33
|
-
output = self.find_output(source_folder, file, output_folder, params[:output_suffix])
|
50
|
+
list_files.each_with_index do |file, index|
|
51
|
+
UI.message "Processing #{file} index #{index}"
|
34
52
|
|
53
|
+
template = self.find_template(templates, file, platform)
|
35
54
|
if template.nil?
|
36
55
|
UI.error "Unable to find template for screenshot #{file}"
|
37
56
|
next
|
38
57
|
end
|
58
|
+
UI.verbose "Using template: #{template.name} (#{template.width}x#{template.height})"
|
39
59
|
|
40
|
-
|
60
|
+
text = self.find_text(source_folder, file)
|
41
61
|
UI.verbose "Using text: #{text}"
|
62
|
+
|
63
|
+
colors = self.find_colors(source_folder, file, template_folder)
|
64
|
+
UI.verbose "Using colors: #{colors}"
|
65
|
+
|
66
|
+
output = self.find_output(source_folder, file, output_folder, params[:output_suffix])
|
42
67
|
UI.verbose "Saving to: #{output}"
|
43
68
|
|
44
|
-
# Do the magic
|
45
|
-
self.combine(file, template, text, output)
|
69
|
+
# # Do the magic
|
70
|
+
self.combine(file, template, colors, text, output, list_files, index)
|
46
71
|
|
47
72
|
UI.verbose "Framed screenshot #{output}"
|
48
73
|
end
|
@@ -52,7 +77,7 @@ module Fastlane
|
|
52
77
|
end
|
53
78
|
|
54
79
|
def self.load_templates(template_folder)
|
55
|
-
json_file_path = "#{template_folder}/
|
80
|
+
json_file_path = "#{template_folder}/config.json"
|
56
81
|
|
57
82
|
UI.user_error!("Missing Config.json file in template folder") unless File.exist?(json_file_path)
|
58
83
|
|
@@ -64,7 +89,6 @@ module Fastlane
|
|
64
89
|
|
65
90
|
# Detect available templates
|
66
91
|
templates = []
|
67
|
-
|
68
92
|
Dir.glob("#{template_folder}/**/*.png") do |file|
|
69
93
|
|
70
94
|
name = File.basename(file, ".png")
|
@@ -76,7 +100,8 @@ module Fastlane
|
|
76
100
|
|
77
101
|
# Read template image size
|
78
102
|
img = MiniMagick::Image.open(file)
|
79
|
-
template.
|
103
|
+
template.width = img.width
|
104
|
+
template.height = img.height
|
80
105
|
img.destroy!
|
81
106
|
|
82
107
|
# Get template config
|
@@ -87,19 +112,30 @@ module Fastlane
|
|
87
112
|
next
|
88
113
|
end
|
89
114
|
|
90
|
-
#
|
91
|
-
template.imageOffset
|
92
|
-
template.imageWidth
|
93
|
-
template.imageBelow
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
template.
|
98
|
-
template.
|
99
|
-
template.
|
100
|
-
|
101
|
-
|
102
|
-
template.
|
115
|
+
# set image
|
116
|
+
template.imageOffset = (config_custom['image'] && config_custom['image']['offset']) || (config_default['image'] && config_default['image']['offset'])
|
117
|
+
template.imageWidth = (config_custom['image'] && config_custom['image']['width']) || (config_default['image'] && config_default['image']['width'])
|
118
|
+
template.imageBelow = (config_custom['image'] && config_custom['image']['add_below']) || (config_default['image'] && config_default['image']['add_below']) || false
|
119
|
+
template.imageRotation = (config_custom['image'] && config_custom['image']['rotation']) || (config_default['image'] && config_default['image']['rotation'])
|
120
|
+
|
121
|
+
# set image back
|
122
|
+
template.imagePreviousOffset = (config_custom['image']['previous'] && config_custom['image']['previous']['offset']) || (config_default['image']['previous'] && config_default['image']['previous']['offset'])
|
123
|
+
template.imagePreviousWidth = (config_custom['image']['previous'] && config_custom['image']['previous']['width']) || (config_default['image']['previous'] && config_default['image']['previous']['width'])
|
124
|
+
template.imagePreviousRotation = (config_custom['image']['previous'] && config_custom['image']['previous']['rotation']) || (config_default['image']['previous'] && config_default['image']['previous']['rotation'])
|
125
|
+
|
126
|
+
# set image next
|
127
|
+
template.imageNextOffset = (config_custom['image']['next'] && config_custom['image']['next']['offset']) || (config_default['image']['next'] && config_default['image']['next']['offset'])
|
128
|
+
template.imageNextWidth = (config_custom['image']['next'] && config_custom['image']['next']['width']) || (config_default['image']['next'] && config_default['image']['next']['width'])
|
129
|
+
template.imageNextRotation = (config_custom['image']['next'] && config_custom['image']['next']['rotation']) || (config_default['image']['next'] && config_default['image']['next']['rotation'])
|
130
|
+
|
131
|
+
# set font
|
132
|
+
template.textFont = (config_custom['text'] && config_custom['text']['font']) || (config_default['text'] && config_default['text']['font'])
|
133
|
+
template.textSize = (config_custom['text'] && config_custom['text']['size']) || (config_default['text'] && config_default['text']['size'])
|
134
|
+
template.textWidth = (config_custom['text'] && config_custom['text']['width']) || (config_default['text'] && config_default['text']['width'])
|
135
|
+
template.textHeight = (config_custom['text'] && config_custom['text']['height']) || (config_default['text'] && config_default['text']['height'])
|
136
|
+
template.textPadding = (config_custom['text'] && config_custom['text']['padding']) || (config_default['text'] && config_default['text']['padding']) || 0
|
137
|
+
template.textOffsetX = (config_custom['text'] && config_custom['text']['offset_x']) || (config_default['text'] && config_default['text']['offset_x']) || 0
|
138
|
+
template.textOffsetY = (config_custom['text'] && config_custom['text']['offset_y']) || (config_default['text'] && config_default['text']['offset_y']) || 0
|
103
139
|
|
104
140
|
templates << template
|
105
141
|
end
|
@@ -107,23 +143,29 @@ module Fastlane
|
|
107
143
|
return templates
|
108
144
|
end
|
109
145
|
|
110
|
-
def self.find_template(templates, screenshot_file)
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
146
|
+
def self.find_template(templates, screenshot_file, platform)
|
147
|
+
if [:ios, :mac].include? platform
|
148
|
+
# Read device name from file
|
149
|
+
filename = File.basename(screenshot_file)
|
150
|
+
device = filename.slice(0, filename.rindex('-'))
|
151
|
+
elsif :android == platform
|
152
|
+
# Read device name from path
|
153
|
+
folder = File.basename(File.dirname(screenshot_file))
|
154
|
+
device = folder.slice(0, folder.rindex('S'))
|
155
|
+
else
|
156
|
+
UI.error "Unsupported platform"
|
157
|
+
end
|
115
158
|
|
116
159
|
# Search template that matches that size
|
117
|
-
return templates.find { |template| template.
|
160
|
+
return templates.find { |template| template.name == device }
|
118
161
|
end
|
119
162
|
|
120
163
|
def self.find_text(source_dir, screenshot_file)
|
121
164
|
directory = File.dirname(screenshot_file)
|
122
165
|
strings_path = File.join(directory, "text.json")
|
123
166
|
|
124
|
-
while !File.exist?(strings_path) do
|
167
|
+
while directory.start_with?(source_dir) && !File.exist?(strings_path) do
|
125
168
|
directory = File.dirname(directory)
|
126
|
-
break if directory == source_dir
|
127
169
|
strings_path = File.join(directory, "text.json")
|
128
170
|
end
|
129
171
|
|
@@ -135,6 +177,46 @@ module Fastlane
|
|
135
177
|
return result.last if result
|
136
178
|
end
|
137
179
|
|
180
|
+
def self.find_colors(source_dir, screenshot_file, colors_dir)
|
181
|
+
|
182
|
+
# Default values
|
183
|
+
colors = Colors.new
|
184
|
+
colors.text = "#000000"
|
185
|
+
colors.background = nil
|
186
|
+
|
187
|
+
# Read values from file
|
188
|
+
directory = File.dirname(screenshot_file)
|
189
|
+
colors_path = File.join(colors_dir, "colors.json")
|
190
|
+
|
191
|
+
while directory.start_with?(source_dir) && !File.exist?(colors_path) do
|
192
|
+
directory = File.dirname(directory)
|
193
|
+
colors_path = File.join(directory, "colors.json")
|
194
|
+
end
|
195
|
+
|
196
|
+
if File.exist?(colors_path)
|
197
|
+
config = JSON.parse(File.read(colors_path))
|
198
|
+
|
199
|
+
# Read default values
|
200
|
+
default = Colors.new
|
201
|
+
default.text = config['default']['text']
|
202
|
+
default.background = config['default']['background']
|
203
|
+
colors.merge(default)
|
204
|
+
|
205
|
+
# Read and apply override, if any
|
206
|
+
override = config.select { |k, v| File.basename(screenshot_file).upcase.include? k.upcase }.values.map { |value|
|
207
|
+
c = Colors.new
|
208
|
+
c.text = value['text']
|
209
|
+
c.background = value['background']
|
210
|
+
c
|
211
|
+
}
|
212
|
+
unless override.empty?
|
213
|
+
colors.merge(override.first)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
return colors
|
218
|
+
end
|
219
|
+
|
138
220
|
def self.find_output(source_folder, screenshot_file, output_folder, output_suffix)
|
139
221
|
# Prepare file name
|
140
222
|
if output_suffix.empty?
|
@@ -158,44 +240,149 @@ module Fastlane
|
|
158
240
|
return file_path
|
159
241
|
end
|
160
242
|
|
161
|
-
|
243
|
+
# Magic is HERE
|
244
|
+
def self.combine(screenshot_file, template, colors, text, output_file, list_files, index)
|
245
|
+
|
246
|
+
# Get list lenght
|
247
|
+
list_lenght = list_files.length()
|
248
|
+
|
249
|
+
# Var images
|
250
|
+
screenshot_img_back = nil
|
251
|
+
screenshot_img = nil
|
252
|
+
screenshot_img_next = nil
|
253
|
+
|
254
|
+
# Prepare base image
|
255
|
+
result_img = MiniMagick::Image.open("#{Framer::ROOT}/assets/background.png")
|
256
|
+
result_img.resize "#{template.width}x#{template.height}!" # `!` says it should ignore the ratio
|
257
|
+
|
258
|
+
# Apply background color, if any
|
259
|
+
unless colors.background.nil?
|
260
|
+
result_img.combine_options do |c|
|
261
|
+
c.define "png:color-type=2"
|
262
|
+
c.fill "#{colors.background}"
|
263
|
+
c.draw "rectangle 0,0,#{template.width},#{template.height}"
|
264
|
+
end
|
265
|
+
end
|
162
266
|
|
163
267
|
# Get template image
|
164
268
|
template_img = MiniMagick::Image.open(template.file)
|
269
|
+
|
270
|
+
# Get back screenshot
|
271
|
+
unless template.imagePreviousOffset.nil?
|
272
|
+
if list_lenght >= index -1
|
273
|
+
screenshot_img_back = MiniMagick::Image.open(list_files[index -1]).auto_orient
|
274
|
+
screenshot_img_back.resize "#{template.imagePreviousWidth}x"
|
275
|
+
unless template.imagePreviousRotation.nil?
|
276
|
+
screenshot_img_back.combine_options do |cmd|
|
277
|
+
cmd.background "rgba(255,255,255,0.0)" # transparent
|
278
|
+
cmd.rotate(template.imagePreviousRotation.to_f)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
else
|
282
|
+
UI.error "Unable to find back screenshot index #{index-1} in #{list_lenght}"
|
283
|
+
end
|
284
|
+
end
|
165
285
|
|
166
286
|
# Get screenshot image
|
167
|
-
screenshot_img = MiniMagick::Image.open(screenshot_file)
|
168
|
-
|
287
|
+
screenshot_img = MiniMagick::Image.open(screenshot_file).auto_orient
|
288
|
+
|
169
289
|
# Resize screenshot to fit template
|
170
290
|
screenshot_img.resize "#{template.imageWidth}x"
|
291
|
+
|
292
|
+
# rotate screenshot
|
293
|
+
unless template.imageRotation.nil?
|
294
|
+
screenshot_img.combine_options do |cmd|
|
295
|
+
cmd.background "rgba(255,255,255,0.0)" # transparent
|
296
|
+
cmd.rotate(template.imageRotation.to_f)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Get next screenshot
|
301
|
+
unless template.imageNextOffset.nil?
|
302
|
+
if list_lenght >= index + 1
|
303
|
+
image_path = list_files[index+1]
|
304
|
+
list_files.each_with_index do |_file, _index|
|
305
|
+
if _index === index
|
306
|
+
print("file: ", _file, " index ", _index, " my index ", index)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
# print("aqui jovem: ", image_path, " list_lenght ", list_lenght, " index ", index)
|
310
|
+
screenshot_img_next = MiniMagick::Image.open(list_files[index]).auto_orient
|
311
|
+
screenshot_img_next.resize "#{template.imageNextWidth}x"
|
312
|
+
unless template.imageNextRotation.nil?
|
313
|
+
screenshot_img_next.combine_options do |cmd|
|
314
|
+
cmd.background "rgba(255,255,255,0.0)" # transparent
|
315
|
+
cmd.rotate(template.imageNextRotation.to_f)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
else
|
319
|
+
UI.error "Unable to find next screenshot index #{index+1} in #{list_lenght}"
|
320
|
+
end
|
321
|
+
end
|
171
322
|
|
172
323
|
# Put screenshot over template
|
173
324
|
if template.imageBelow
|
174
|
-
|
175
|
-
#
|
176
|
-
|
177
|
-
|
325
|
+
|
326
|
+
# Screenshot back
|
327
|
+
unless screenshot_img_back.nil?
|
328
|
+
result_img = result_img.composite(screenshot_img_back) do |c|
|
329
|
+
c.compose "Over"
|
330
|
+
c.geometry template.imagePreviousOffset.to_s
|
331
|
+
|
332
|
+
end
|
333
|
+
end
|
178
334
|
|
179
335
|
# Screenshot first
|
180
|
-
|
336
|
+
result_img = result_img.composite(screenshot_img) do |c|
|
181
337
|
c.compose "Over"
|
182
338
|
c.geometry template.imageOffset.to_s
|
339
|
+
|
340
|
+
end
|
341
|
+
|
342
|
+
# Screenshot next
|
343
|
+
unless screenshot_img_next.nil?
|
344
|
+
result_img = result_img.composite(screenshot_img_next) do |c|
|
345
|
+
c.compose "Over"
|
346
|
+
c.geometry template.imageNextOffset.to_s
|
347
|
+
|
348
|
+
end
|
183
349
|
end
|
184
|
-
|
350
|
+
|
185
351
|
# Template second
|
186
|
-
result_img =
|
352
|
+
result_img = result_img.composite(template_img) do |c|
|
187
353
|
c.compose "Over"
|
188
354
|
end
|
189
355
|
|
190
|
-
base_1_img.destroy!
|
191
|
-
base_2_img.destroy!
|
192
|
-
|
193
356
|
else
|
194
357
|
|
195
|
-
#
|
196
|
-
result_img =
|
358
|
+
# Template first
|
359
|
+
result_img = result_img.composite(template_img) do |c|
|
360
|
+
c.compose "Over"
|
361
|
+
end
|
362
|
+
|
363
|
+
# Screenshot back
|
364
|
+
unless screenshot_img_back.nil?
|
365
|
+
result_img = result_img.composite(screenshot_img_back) do |c|
|
366
|
+
c.compose "Over"
|
367
|
+
c.geometry template.imagePreviousOffset.to_s
|
368
|
+
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
# Screenshot first
|
373
|
+
result_img = result_img.composite(screenshot_img) do |c|
|
197
374
|
c.compose "Over"
|
198
375
|
c.geometry template.imageOffset.to_s
|
376
|
+
|
377
|
+
end
|
378
|
+
|
379
|
+
# Screenshot next
|
380
|
+
unless screenshot_img_next.nil?
|
381
|
+
result_img = result_img.composite(screenshot_img_next) do |c|
|
382
|
+
c.compose "Over"
|
383
|
+
c.geometry template.imageNextOffset.to_s
|
384
|
+
|
385
|
+
end
|
199
386
|
end
|
200
387
|
|
201
388
|
end
|
@@ -215,9 +402,9 @@ module Fastlane
|
|
215
402
|
text_img.combine_options do |c|
|
216
403
|
c.font text_font
|
217
404
|
c.pointsize template.textSize.to_s
|
218
|
-
c.gravity "
|
405
|
+
c.gravity "NorthWest"
|
219
406
|
c.draw "text 0,0 '#{text}'"
|
220
|
-
c.fill
|
407
|
+
c.fill colors.text.to_s
|
221
408
|
end
|
222
409
|
text_img.trim # remove white space
|
223
410
|
|
@@ -255,7 +442,7 @@ module Fastlane
|
|
255
442
|
result_img.destroy!
|
256
443
|
screenshot_img.destroy!
|
257
444
|
template_img.destroy!
|
258
|
-
|
445
|
+
|
259
446
|
end
|
260
447
|
|
261
448
|
def self.create_dir_if_not_exists(path)
|
@@ -272,11 +459,11 @@ module Fastlane
|
|
272
459
|
#####################################################
|
273
460
|
|
274
461
|
def self.description
|
275
|
-
"Create images combining app screenshots to templates to make a nice \'screenshot\' to upload in App Store"
|
462
|
+
"Create images combining app screenshots to templates to make a nice \'screenshot\' to upload in App Store and Google Play"
|
276
463
|
end
|
277
464
|
|
278
465
|
def self.authors
|
279
|
-
["DrAL3X"]
|
466
|
+
["DrAL3X", "AzureRodrigo"]
|
280
467
|
end
|
281
468
|
|
282
469
|
def self.available_options
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-framer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DrAL3X
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mini_magick
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.
|
19
|
+
version: 4.10.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 4.
|
26
|
+
version: 4.10.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 1.100.0
|
125
|
-
description:
|
125
|
+
description:
|
126
126
|
email: alessandro.calzavara@gmail.com
|
127
127
|
executables: []
|
128
128
|
extensions: []
|
@@ -139,7 +139,7 @@ homepage: https://github.com/spreaker/fastlane-framer-plugin
|
|
139
139
|
licenses:
|
140
140
|
- MIT
|
141
141
|
metadata: {}
|
142
|
-
post_install_message:
|
142
|
+
post_install_message:
|
143
143
|
rdoc_options: []
|
144
144
|
require_paths:
|
145
145
|
- lib
|
@@ -154,9 +154,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
154
|
- !ruby/object:Gem::Version
|
155
155
|
version: '0'
|
156
156
|
requirements: []
|
157
|
-
|
158
|
-
|
159
|
-
signing_key:
|
157
|
+
rubygems_version: 3.1.2
|
158
|
+
signing_key:
|
160
159
|
specification_version: 4
|
161
160
|
summary: Create images combining app screenshots with templates to make nice pictures
|
162
161
|
for the App Store
|