fastlane 2.141.0 → 2.146.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +82 -82
- data/credentials_manager/lib/credentials_manager/appfile_config.rb +4 -0
- data/deliver/lib/deliver/app_screenshot.rb +1 -0
- data/deliver/lib/deliver/options.rb +30 -1
- data/deliver/lib/deliver/setup.rb +4 -4
- data/fastlane/lib/fastlane/actions/.update_code_signing_settings.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/README.md +2 -0
- data/fastlane/lib/fastlane/actions/app_store_build_number.rb +13 -5
- data/fastlane/lib/fastlane/actions/automatic_code_signing.rb +7 -1
- data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +3 -0
- data/fastlane/lib/fastlane/actions/cocoapods.rb +2 -2
- data/fastlane/lib/fastlane/actions/crashlytics.rb +14 -2
- data/fastlane/lib/fastlane/actions/create_pull_request.rb +7 -1
- data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +10 -4
- data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +22 -6
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +23 -7
- data/fastlane/lib/fastlane/actions/ensure_git_branch.rb +1 -1
- data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +35 -7
- data/fastlane/lib/fastlane/actions/frame_screenshots.rb +2 -1
- data/fastlane/lib/fastlane/actions/get_github_release.rb +3 -0
- data/fastlane/lib/fastlane/actions/get_version_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +9 -3
- data/fastlane/lib/fastlane/actions/notarize.rb +183 -0
- data/fastlane/lib/fastlane/actions/pod_lib_lint.rb +7 -1
- data/fastlane/lib/fastlane/actions/s3.rb +5 -291
- data/fastlane/lib/fastlane/actions/setup_ci.rb +1 -1
- data/fastlane/lib/fastlane/actions/setup_jenkins.rb +11 -2
- data/fastlane/lib/fastlane/actions/slather.rb +1 -1
- data/fastlane/lib/fastlane/actions/spm.rb +8 -0
- data/fastlane/lib/fastlane/actions/swiftlint.rb +45 -9
- data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +198 -0
- data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +14 -4
- data/fastlane/lib/fastlane/actions/verify_build.rb +1 -1
- data/fastlane/lib/fastlane/helper/adb_helper.rb +1 -1
- data/fastlane/lib/fastlane/helper/s3_client_helper.rb +61 -0
- data/fastlane/lib/fastlane/plugins/plugin_manager.rb +1 -1
- data/fastlane/lib/fastlane/server/socket_server_action_command_executor.rb +1 -1
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/Fastlane.swift +201 -13
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +17 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/RubyCommand.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +9 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +9 -0
- data/fastlane_core/lib/fastlane_core/device_manager.rb +3 -3
- data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +1 -0
- data/fastlane_core/lib/fastlane_core/keychain_importer.rb +2 -0
- data/fastlane_core/lib/fastlane_core/project.rb +4 -0
- data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +15 -2
- data/frameit/lib/frameit/commands_generator.rb +25 -0
- data/frameit/lib/frameit/config_parser.rb +31 -9
- data/frameit/lib/frameit/device.rb +90 -0
- data/frameit/lib/frameit/device_types.rb +121 -5
- data/frameit/lib/frameit/editor.rb +29 -41
- data/frameit/lib/frameit/offsets.rb +8 -1
- data/frameit/lib/frameit/options.rb +81 -54
- data/frameit/lib/frameit/runner.rb +17 -7
- data/frameit/lib/frameit/screenshot.rb +39 -47
- data/frameit/lib/frameit/template_finder.rb +15 -12
- data/gym/lib/gym/generators/package_command_generator.rb +4 -0
- data/gym/lib/gym/generators/package_command_generator_xcode7.rb +5 -0
- data/gym/lib/gym/runner.rb +16 -2
- data/match/lib/match/change_password.rb +1 -1
- data/match/lib/match/encryption.rb +4 -0
- data/match/lib/match/importer.rb +37 -20
- data/match/lib/match/module.rb +1 -1
- data/match/lib/match/nuke.rb +5 -1
- data/match/lib/match/options.rb +18 -0
- data/match/lib/match/runner.rb +4 -0
- data/match/lib/match/setup.rb +1 -1
- data/match/lib/match/storage.rb +4 -0
- data/match/lib/match/storage/google_cloud_storage.rb +2 -2
- data/match/lib/match/storage/s3_storage.rb +167 -0
- data/pilot/lib/pilot/build_manager.rb +24 -7
- data/pilot/lib/pilot/options.rb +8 -0
- data/produce/lib/produce/developer_center.rb +11 -2
- data/produce/lib/produce/itunes_connect.rb +11 -3
- data/produce/lib/produce/options.rb +12 -0
- data/scan/lib/scan/options.rb +10 -0
- data/scan/lib/scan/runner.rb +9 -7
- data/scan/lib/scan/test_command_generator.rb +11 -4
- data/screengrab/lib/screengrab/runner.rb +32 -19
- data/snapshot/lib/snapshot/fixes/simulator_shared_pasteboard.rb +16 -0
- data/snapshot/lib/snapshot/reports_generator.rb +4 -0
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +2 -0
- data/spaceship/lib/spaceship/connect_api/models/app.rb +11 -0
- data/spaceship/lib/spaceship/connect_api/models/build.rb +1 -2
- data/spaceship/lib/spaceship/connect_api/models/certificate.rb +2 -0
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +23 -0
- data/spaceship/lib/spaceship/portal/app_service.rb +2 -2
- data/spaceship/lib/spaceship/portal/portal_client.rb +13 -0
- data/spaceship/lib/spaceship/tunes/app_version.rb +6 -1
- data/spaceship/lib/spaceship/tunes/application.rb +2 -1
- data/spaceship/lib/spaceship/tunes/tunes_client.rb +2 -2
- data/spaceship/lib/spaceship/two_step_or_factor_client.rb +52 -16
- data/supply/lib/supply/client.rb +4 -4
- data/supply/lib/supply/setup.rb +5 -3
- metadata +37 -16
@@ -63,6 +63,18 @@ protocol MatchfileProtocol: class {
|
|
63
63
|
/// ID of the Google Cloud project to use for authentication
|
64
64
|
var googleCloudProjectId: String? { get }
|
65
65
|
|
66
|
+
/// Name of the S3 region
|
67
|
+
var s3Region: String? { get }
|
68
|
+
|
69
|
+
/// S3 access key
|
70
|
+
var s3AccessKey: String? { get }
|
71
|
+
|
72
|
+
/// S3 secret access key
|
73
|
+
var s3SecretAccessKey: String? { get }
|
74
|
+
|
75
|
+
/// Name of the S3 bucket
|
76
|
+
var s3Bucket: String? { get }
|
77
|
+
|
66
78
|
/// Keychain the items should be imported to
|
67
79
|
var keychainName: String { get }
|
68
80
|
|
@@ -116,6 +128,10 @@ extension MatchfileProtocol {
|
|
116
128
|
var googleCloudBucketName: String? { return nil }
|
117
129
|
var googleCloudKeysFile: String? { return nil }
|
118
130
|
var googleCloudProjectId: String? { return nil }
|
131
|
+
var s3Region: String? { return nil }
|
132
|
+
var s3AccessKey: String? { return nil }
|
133
|
+
var s3SecretAccessKey: String? { return nil }
|
134
|
+
var s3Bucket: String? { return nil }
|
119
135
|
var keychainName: String { return "login.keychain" }
|
120
136
|
var keychainPassword: String? { return nil }
|
121
137
|
var force: Bool { return false }
|
@@ -130,4 +146,4 @@ extension MatchfileProtocol {
|
|
130
146
|
|
131
147
|
// Please don't remove the lines below
|
132
148
|
// They are used to detect outdated files
|
133
|
-
// FastlaneRunnerAPIVersion [0.9.
|
149
|
+
// FastlaneRunnerAPIVersion [0.9.15]
|
@@ -42,6 +42,9 @@ protocol ScanfileProtocol: class {
|
|
42
42
|
/// Array of strings matching Test Bundle/Test Suite/Test Cases to skip
|
43
43
|
var skipTesting: String? { get }
|
44
44
|
|
45
|
+
/// The testplan associated with the scheme that should be used for testing
|
46
|
+
var testplan: String? { get }
|
47
|
+
|
45
48
|
/// Run tests using the provided `.xctestrun` file
|
46
49
|
var xctestrun: String? { get }
|
47
50
|
|
@@ -102,6 +105,9 @@ protocol ScanfileProtocol: class {
|
|
102
105
|
/// Generate the json compilation database with clang naming convention (compile_commands.json)
|
103
106
|
var useClangReportName: Bool { get }
|
104
107
|
|
108
|
+
/// Specify the exact number of test runners that will be spawned during parallel testing. Equivalent to -parallel-testing-worker-count
|
109
|
+
var concurrentWorkers: Int? { get }
|
110
|
+
|
105
111
|
/// Constrain the number of simulator devices on which to test concurrently. Equivalent to -maximum-concurrent-test-simulator-destinations
|
106
112
|
var maxConcurrentSimulators: Int? { get }
|
107
113
|
|
@@ -190,6 +196,7 @@ extension ScanfileProtocol {
|
|
190
196
|
var appIdentifier: String? { return nil }
|
191
197
|
var onlyTesting: String? { return nil }
|
192
198
|
var skipTesting: String? { return nil }
|
199
|
+
var testplan: String? { return nil }
|
193
200
|
var xctestrun: String? { return nil }
|
194
201
|
var toolchain: String? { return nil }
|
195
202
|
var clean: Bool { return false }
|
@@ -210,6 +217,7 @@ extension ScanfileProtocol {
|
|
210
217
|
var shouldZipBuildProducts: Bool { return false }
|
211
218
|
var resultBundle: Bool { return false }
|
212
219
|
var useClangReportName: Bool { return false }
|
220
|
+
var concurrentWorkers: Int? { return nil }
|
213
221
|
var maxConcurrentSimulators: Int? { return nil }
|
214
222
|
var disableConcurrentTesting: Bool { return false }
|
215
223
|
var skipBuild: Bool { return false }
|
@@ -238,4 +246,4 @@ extension ScanfileProtocol {
|
|
238
246
|
|
239
247
|
// Please don't remove the lines below
|
240
248
|
// They are used to detect outdated files
|
241
|
-
// FastlaneRunnerAPIVersion [0.9.
|
249
|
+
// FastlaneRunnerAPIVersion [0.9.27]
|
@@ -2,6 +2,7 @@ require_relative '../ui/ui'
|
|
2
2
|
require_relative '../ui/errors/fastlane_error'
|
3
3
|
require_relative '../helper'
|
4
4
|
require_relative '../module'
|
5
|
+
require 'json'
|
5
6
|
|
6
7
|
module FastlaneCore
|
7
8
|
class ConfigItem
|
@@ -227,6 +228,7 @@ module FastlaneCore
|
|
227
228
|
true
|
228
229
|
end
|
229
230
|
|
231
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
230
232
|
# Returns an updated value type (if necessary)
|
231
233
|
def auto_convert_value(value)
|
232
234
|
return nil if value.nil?
|
@@ -240,6 +242,12 @@ module FastlaneCore
|
|
240
242
|
elsif allow_shell_conversion
|
241
243
|
return value.shelljoin if value.kind_of?(Array)
|
242
244
|
return value.map { |k, v| "#{k.to_s.shellescape}=#{v.shellescape}" }.join(' ') if value.kind_of?(Hash)
|
245
|
+
elsif data_type == Hash && value.kind_of?(String)
|
246
|
+
begin
|
247
|
+
parsed = JSON.parse(value)
|
248
|
+
return parsed if parsed.kind_of?(Hash)
|
249
|
+
rescue JSON::ParserError
|
250
|
+
end
|
243
251
|
elsif data_type != String
|
244
252
|
# Special treatment if the user specified true, false or YES, NO
|
245
253
|
# There is no boolean type, so we just do it here
|
@@ -249,6 +257,7 @@ module FastlaneCore
|
|
249
257
|
return false
|
250
258
|
end
|
251
259
|
end
|
260
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
252
261
|
|
253
262
|
return value # fallback to not doing anything
|
254
263
|
end
|
@@ -49,8 +49,8 @@ module FastlaneCore
|
|
49
49
|
|
50
50
|
# " iPad (5th generation) (852A5796-63C3-4641-9825-65EBDC5C4259) (Shutdown)"
|
51
51
|
# This line will turn the above string into
|
52
|
-
# ["iPad
|
53
|
-
matches = line.strip.scan(
|
52
|
+
# ["iPad (5th generation)", "(852A5796-63C3-4641-9825-65EBDC5C4259)", "(Shutdown)"]
|
53
|
+
matches = line.strip.scan(/^(.*?) (\([^)]*?\)) (\([^)]*?\))$/).flatten.reject(&:empty?)
|
54
54
|
state = matches.pop.to_s.delete('(').delete(')')
|
55
55
|
udid = matches.pop.to_s.delete('(').delete(')')
|
56
56
|
name = matches.join(' ')
|
@@ -223,7 +223,7 @@ module FastlaneCore
|
|
223
223
|
plist_buddy_cmd = "-c \"Add :KeyboardContinuousPathEnabled bool false\""
|
224
224
|
plist_path = File.expand_path("~/Library/Developer/CoreSimulator/Devices/#{self.udid}/data/Library/Preferences/com.apple.keyboard.ContinuousPath.plist")
|
225
225
|
|
226
|
-
Helper.backticks("#{plist_buddy} #{plist_buddy_cmd} #{plist_path}")
|
226
|
+
Helper.backticks("#{plist_buddy} #{plist_buddy_cmd} #{plist_path} >/dev/null 2>&1")
|
227
227
|
end
|
228
228
|
end
|
229
229
|
end
|
@@ -37,6 +37,7 @@ module FastlaneCore
|
|
37
37
|
|
38
38
|
def self.fetch_info_plist_file(path)
|
39
39
|
UI.user_error!("Could not find file at path '#{path}'") unless File.exist?(path)
|
40
|
+
Zip.validate_entry_sizes = true # https://github.com/rubyzip/rubyzip/releases/tag/v2.0.0
|
40
41
|
Zip::File.open(path, "rb") do |zipfile|
|
41
42
|
file = zipfile.glob('**/Payload/*.app/Info.plist').first
|
42
43
|
return nil unless file
|
@@ -10,6 +10,7 @@ module FastlaneCore
|
|
10
10
|
command << " -P #{certificate_password.shellescape}"
|
11
11
|
command << " -T /usr/bin/codesign" # to not be asked for permission when running a tool like `gym` (before Sierra)
|
12
12
|
command << " -T /usr/bin/security"
|
13
|
+
command << " -T /usr/bin/productbuild" # to not be asked for permission when using an installer cert for macOS
|
13
14
|
command << " 1> /dev/null" unless output
|
14
15
|
|
15
16
|
UI.command(command) if output
|
@@ -37,6 +38,7 @@ module FastlaneCore
|
|
37
38
|
if Helper.backticks('security -h | grep set-key-partition-list', print: false).length > 0
|
38
39
|
command = "security set-key-partition-list"
|
39
40
|
command << " -S apple-tool:,apple:"
|
41
|
+
command << " -s" # This is a needed in Catalina to prevent "security: SecKeychainItemCopyAccess: A missing value was detected."
|
40
42
|
command << " -k #{keychain_password.to_s.shellescape}"
|
41
43
|
command << " #{keychain_path.shellescape}"
|
42
44
|
command << " 1> /dev/null" # always disable stdout. This can be very verbose, and leak potentially sensitive info
|
@@ -294,6 +294,10 @@ module FastlaneCore
|
|
294
294
|
supported_platforms.include?(:iOS)
|
295
295
|
end
|
296
296
|
|
297
|
+
def watchos?
|
298
|
+
supported_platforms.include?(:watchOS)
|
299
|
+
end
|
300
|
+
|
297
301
|
def supported_platforms
|
298
302
|
supported_platforms = build_settings(key: "SUPPORTED_PLATFORMS")
|
299
303
|
if supported_platforms.nil?
|
@@ -44,16 +44,29 @@ module FastlaneCore
|
|
44
44
|
parse(path, keychain_path).fetch("Name")
|
45
45
|
end
|
46
46
|
|
47
|
+
def bundle_id(path, keychain_path = nil)
|
48
|
+
profile = parse(path, keychain_path)
|
49
|
+
app_id_prefix = profile["ApplicationIdentifierPrefix"].first
|
50
|
+
bundle_id = profile["Entitlements"]["application-identifier"].gsub("#{app_id_prefix}.", "")
|
51
|
+
bundle_id
|
52
|
+
rescue
|
53
|
+
UI.error("Unable to extract the Bundle Id from the provided provisioning profile '#{path}'.")
|
54
|
+
end
|
55
|
+
|
47
56
|
def mac?(path, keychain_path = nil)
|
48
57
|
parse(path, keychain_path).fetch("Platform", []).include?('OSX')
|
49
58
|
end
|
50
59
|
|
51
60
|
def profile_filename(path, keychain_path = nil)
|
52
61
|
basename = uuid(path, keychain_path)
|
62
|
+
basename + profile_extension(path, keychain_path)
|
63
|
+
end
|
64
|
+
|
65
|
+
def profile_extension(path, keychain_path = nil)
|
53
66
|
if mac?(path, keychain_path)
|
54
|
-
|
67
|
+
".provisionprofile"
|
55
68
|
else
|
56
|
-
|
69
|
+
".mobileprovision"
|
57
70
|
end
|
58
71
|
end
|
59
72
|
|
@@ -7,6 +7,7 @@ require_relative 'device_types'
|
|
7
7
|
require_relative 'runner'
|
8
8
|
require_relative 'options'
|
9
9
|
require_relative 'dependency_checker'
|
10
|
+
require_relative 'device'
|
10
11
|
|
11
12
|
HighLine.track_eof = false
|
12
13
|
|
@@ -80,6 +81,30 @@ module Frameit
|
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
84
|
+
command :android do |c|
|
85
|
+
c.syntax = 'fastlane frameit android'
|
86
|
+
c.description = "Adds Android frames around all screenshots"
|
87
|
+
|
88
|
+
FastlaneCore::CommanderGenerator.new.generate(Frameit::Options.available_options, command: c)
|
89
|
+
|
90
|
+
c.action do |args, options|
|
91
|
+
load_config(options)
|
92
|
+
Frameit::Runner.new.run('.', nil, Platform::ANDROID)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
command :ios do |c|
|
97
|
+
c.syntax = 'fastlane frameit ios'
|
98
|
+
c.description = "Adds iOS frames around all screenshots"
|
99
|
+
|
100
|
+
FastlaneCore::CommanderGenerator.new.generate(Frameit::Options.available_options, command: c)
|
101
|
+
|
102
|
+
c.action do |args, options|
|
103
|
+
load_config(options)
|
104
|
+
Frameit::Runner.new.run('.', nil, Platform::IOS)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
83
108
|
command :setup do |c|
|
84
109
|
c.syntax = 'fastlane frameit setup'
|
85
110
|
c.description = "Downloads and sets up the latest device frames"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'device_types'
|
2
2
|
|
3
3
|
module Frameit
|
4
4
|
class ConfigParser
|
@@ -79,13 +79,7 @@ module Frameit
|
|
79
79
|
when 'font'
|
80
80
|
UI.user_error!("Could not find font at path '#{File.expand_path(value)}'") unless File.exist?(value)
|
81
81
|
when 'fonts'
|
82
|
-
|
83
|
-
|
84
|
-
value.each do |current|
|
85
|
-
UI.user_error!("You must specify a font path") if current.fetch('font', '').length == 0
|
86
|
-
UI.user_error!("Could not find font at path '#{File.expand_path(current.fetch('font'))}'") unless File.exist?(current.fetch('font'))
|
87
|
-
UI.user_error!("`supported` must be an array") unless current.fetch('supported', []).kind_of?(Array)
|
88
|
-
end
|
82
|
+
check_fonts(value)
|
89
83
|
when 'background'
|
90
84
|
UI.user_error!("Could not find background image at path '#{File.expand_path(value)}'") unless File.exist?(value)
|
91
85
|
when 'color'
|
@@ -103,12 +97,40 @@ module Frameit
|
|
103
97
|
when 'font_scale_factor'
|
104
98
|
UI.user_error!("font_scale_factor must be numeric") unless value.kind_of?(Numeric)
|
105
99
|
when 'frame'
|
106
|
-
UI.user_error!("
|
100
|
+
UI.user_error!("Invalid frame color '#{value}'. Frame color must be one of " + Color.all_colors.join(', ')) unless ConfigParser.supported_color?(value)
|
101
|
+
when 'use_platform'
|
102
|
+
UI.user_error!("Invalid platform type '#{value}'. Available values are " + Platform.all_platforms.join(', ') + ".") unless ConfigParser.supported_platform?(value)
|
103
|
+
when 'force_device_type'
|
104
|
+
UI.user_error!("Invalid device type '#{value}'. Available values: " + Devices.all_device_names_without_apple.join(', ')) unless ConfigParser.supported_device?(value)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def check_fonts(value)
|
109
|
+
UI.user_error!("`fonts` must be an array") unless value.kind_of?(Array)
|
110
|
+
|
111
|
+
value.each do |current|
|
112
|
+
UI.user_error!("You must specify a font path") if current.fetch('font', '').length == 0
|
113
|
+
UI.user_error!("Could not find font at path '#{File.expand_path(current.fetch('font'))}'") unless File.exist?(current.fetch('font'))
|
114
|
+
UI.user_error!("`supported` must be an array") unless current.fetch('supported', []).kind_of?(Array)
|
107
115
|
end
|
108
116
|
end
|
109
117
|
|
110
118
|
def integer_or_percentage(value)
|
111
119
|
value.kind_of?(Integer) || (value.end_with?('%') && value.to_f > 0)
|
112
120
|
end
|
121
|
+
|
122
|
+
def self.supported_color?(value)
|
123
|
+
return false if value.nil?
|
124
|
+
Color.all_colors.any? { |c| c == value }
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.supported_platform?(value)
|
128
|
+
return false if value.nil?
|
129
|
+
Platform.all_platforms.any? { |c| c == value }
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.supported_device?(value)
|
133
|
+
return !Device.find_device_by_id_or_name(value).nil?
|
134
|
+
end
|
113
135
|
end
|
114
136
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'fastimage'
|
2
|
+
require_relative 'module'
|
3
|
+
|
4
|
+
module Frameit
|
5
|
+
class Device
|
6
|
+
REQUIRED_PRIORITY = 999
|
7
|
+
|
8
|
+
attr_reader :id
|
9
|
+
attr_reader :deliver_screen_id
|
10
|
+
attr_reader :formatted_name
|
11
|
+
attr_reader :resolutions
|
12
|
+
attr_reader :density_ppi
|
13
|
+
attr_reader :default_color
|
14
|
+
attr_reader :platform
|
15
|
+
attr_reader :priority_config_key
|
16
|
+
|
17
|
+
def initialize(id, formatted_name, priority, resolutions, density_ppi, default_color, platform = Platform::IOS, deliver_screen_id = nil, priority_config_key = nil)
|
18
|
+
Raise("Priority mustn't be higher than #{REQUIRED_PRIORITY}") if priority > REQUIRED_PRIORITY
|
19
|
+
@id = id
|
20
|
+
@deliver_screen_id = deliver_screen_id
|
21
|
+
@formatted_name = formatted_name
|
22
|
+
@priority = priority
|
23
|
+
@resolutions = resolutions
|
24
|
+
@density_ppi = density_ppi
|
25
|
+
@default_color = default_color
|
26
|
+
@platform = platform
|
27
|
+
@priority_config_key = priority_config_key
|
28
|
+
end
|
29
|
+
|
30
|
+
def priority
|
31
|
+
if !priority_config_key.nil? && Frameit.config[priority_config_key]
|
32
|
+
REQUIRED_PRIORITY
|
33
|
+
else
|
34
|
+
@priority
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def is_chosen_platform?(platform)
|
39
|
+
@platform == platform || platform == Platform::ANY
|
40
|
+
end
|
41
|
+
|
42
|
+
def formatted_name_without_apple
|
43
|
+
formatted_name.gsub("Apple", "").strip.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.detect_device(path, platform)
|
47
|
+
size = FastImage.size(path)
|
48
|
+
|
49
|
+
UI.user_error!("Could not find or parse file at path '#{path}'") if size.nil? || size.count == 0
|
50
|
+
|
51
|
+
found_device = nil
|
52
|
+
filename_device = nil
|
53
|
+
filename = Pathname.new(path).basename.to_s
|
54
|
+
Devices.constants.each do |c|
|
55
|
+
device = Devices.const_get(c)
|
56
|
+
next unless device.resolutions.include?(size)
|
57
|
+
# assign to filename_device if the filename contains the formatted name / id and its priority is higher than the current filename_device
|
58
|
+
filename_device = device if (filename.include?(device.formatted_name_without_apple) || filename.include?(device.id)) && (filename_device.nil? || filename_device.priority < device.priority)
|
59
|
+
next unless device.is_chosen_platform?(platform) && (found_device.nil? || device.priority > found_device.priority)
|
60
|
+
found_device = device
|
61
|
+
end
|
62
|
+
|
63
|
+
# prefer filename
|
64
|
+
return filename_device if filename_device
|
65
|
+
|
66
|
+
# return found_device which was detected according to platform & priority & settings if found
|
67
|
+
return found_device if found_device
|
68
|
+
|
69
|
+
# no device detected - show error and return nil
|
70
|
+
UI.user_error!("Unsupported screen size #{size} for path '#{path}'")
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# Previously ENV[FRAMEIT_FORCE_DEVICE_TYPE] was matched to Deliver::AppScreenshot::ScreenSize constants. However,
|
75
|
+
# options.rb defined a few Apple devices with unspecified IDs, this option was never read from Frameit.config.
|
76
|
+
# Therefore this function matches both ScreenSize constants and formatted names to maintain backward compatibility.
|
77
|
+
def self.find_device_by_id_or_name(id)
|
78
|
+
return nil if id.nil?
|
79
|
+
found_device = nil
|
80
|
+
# multiple devices can be matched to the same deliver_screen_id constant -> we return the one with the highest priority
|
81
|
+
Devices.constants.each do |c|
|
82
|
+
device = Devices.const_get(c)
|
83
|
+
if (device.id == id || device.deliver_screen_id == id || device.formatted_name_without_apple == id) && (found_device.nil? || device.priority > found_device.priority)
|
84
|
+
found_device = device
|
85
|
+
end
|
86
|
+
end
|
87
|
+
return found_device
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -1,18 +1,134 @@
|
|
1
|
+
require_relative 'device'
|
2
|
+
require_relative 'module'
|
3
|
+
require 'deliver/app_screenshot'
|
4
|
+
|
1
5
|
module Frameit
|
2
6
|
module Color
|
3
|
-
|
4
|
-
|
7
|
+
MATTE_BLACK = "Matte Black"
|
8
|
+
SPACE_GRAY = "Space Gray"
|
5
9
|
ROSE_GOLD = "Rose Gold"
|
10
|
+
CLEARLY_WHITE = "Clearly White"
|
11
|
+
JUST_BLACK = "Just Black"
|
12
|
+
NOT_PINK = "Not Pink"
|
13
|
+
SILVER_TITANIUM = "Silver Titanium"
|
14
|
+
ARCTIC_SILVER = "Arctic Silver"
|
15
|
+
CORAL_BLUE = "Coral Blue"
|
16
|
+
MAPLE_GOLD = "Maple Gold"
|
17
|
+
MIDNIGHT_BLACK = "Midnight Black"
|
18
|
+
MIDNIGHT_GREEN = "Midnight Green"
|
19
|
+
ORCHID_GRAY = "Orchid Gray"
|
20
|
+
BURGUNDY_RED = "Burgundy Red"
|
21
|
+
LILAC_PURPLE = "Lilac Purple"
|
22
|
+
SUNRISE_GOLD = "Sunrise Gold"
|
23
|
+
TITANIUM_GRAY = "Titanium Gray"
|
24
|
+
FLAMINGO_PINK = "Flamingo Pink"
|
25
|
+
PRISM_BLACK = "Prism Black"
|
26
|
+
PRISM_BLUE = "Prism Blue"
|
27
|
+
PRISM_GREEN = "Prism Green"
|
28
|
+
PRISM_WHITE = "Prism White"
|
29
|
+
CERAMIC_WHITE = "Ceramic White"
|
30
|
+
OH_SO_ORANGE = "Oh So Orange"
|
31
|
+
AURA_BLACK = "Aura Black"
|
32
|
+
AURA_GLOW = "Aura Glow"
|
33
|
+
AURA_PINK = "Aura Pink"
|
34
|
+
AURA_RED = "Aura Red"
|
35
|
+
AURA_WHITE = "Aura White"
|
36
|
+
AURA_BLUE = "Aura Blue"
|
37
|
+
CORAL = "Coral"
|
38
|
+
BLACK = "Black"
|
39
|
+
WHITE = "White"
|
6
40
|
GOLD = "Gold"
|
41
|
+
SILVER = "Silver"
|
42
|
+
BLUE = "Blue"
|
7
43
|
RED = "Red"
|
8
44
|
YELLOW = "Yellow"
|
9
|
-
|
10
|
-
|
11
|
-
|
45
|
+
GREEN = "Green"
|
46
|
+
PINK = "Pink"
|
47
|
+
PURPLE = "Purple"
|
48
|
+
|
49
|
+
def self.all_colors
|
50
|
+
Color.constants.map { |c| Color.const_get(c).upcase.gsub(' ', '_') }
|
51
|
+
end
|
12
52
|
end
|
13
53
|
|
14
54
|
module Orientation
|
15
55
|
PORTRAIT = "PORTRAIT"
|
16
56
|
LANDSCAPE = "LANDSCAPE"
|
17
57
|
end
|
58
|
+
|
59
|
+
module Platform
|
60
|
+
ANDROID = "ANDROID"
|
61
|
+
IOS = "IOS"
|
62
|
+
ANY = "ANY"
|
63
|
+
|
64
|
+
def self.all_platforms
|
65
|
+
Platform.constants.map { |c| Platform.const_get(c) }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module Devices
|
70
|
+
GOOGLE_PIXEL_3 = Frameit::Device.new("google-pixel-3", "Google Pixel 3", 7, [[1080, 2160], [2160, 1080]], 443, Color::JUST_BLACK, Platform::ANDROID)
|
71
|
+
GOOGLE_PIXEL_3_XL = Frameit::Device.new("google-pixel-3-xl", "Google Pixel 3 XL", 7, [[1440, 2960], [2960, 1440]], 523, Color::JUST_BLACK, Platform::ANDROID)
|
72
|
+
# Google Pixel 4's priority should be higher than Samsung Galaxy S10+ (priority 8):
|
73
|
+
GOOGLE_PIXEL_4 = Frameit::Device.new("google-pixel-4", "Google Pixel 4", 9, [[1080, 2280], [2280, 1080]], 444, Color::JUST_BLACK, Platform::ANDROID)
|
74
|
+
GOOGLE_PIXEL_4_XL = Frameit::Device.new("google-pixel-4-xl", "Google Pixel 4 XL", 9, [[1440, 3040], [3040, 1440]], 537, Color::JUST_BLACK, Platform::ANDROID)
|
75
|
+
HTC_ONE_A9 = Frameit::Device.new("htc-one-a9", "HTC One A9", 6, [[1080, 1920], [1920, 1080]], 441, Color::BLACK, Platform::ANDROID)
|
76
|
+
HTC_ONE_M8 = Frameit::Device.new("htc-one-m8", "HTC One M8", 3, [[1080, 1920], [1920, 1080]], 441, Color::BLACK, Platform::ANDROID)
|
77
|
+
HUAWEI_P8 = Frameit::Device.new("huawei-p8", "Huawei P8", 5, [[1080, 1920], [1920, 1080]], 424, Color::BLACK, Platform::ANDROID)
|
78
|
+
MOTOROLA_MOTO_E = Frameit::Device.new("motorola-moto-e", "Motorola Moto E", 3, [[540, 960], [960, 540]], 245, Color::BLACK, Platform::ANDROID)
|
79
|
+
MOTOROLA_MOTO_G = Frameit::Device.new("motorola-moto-g", "Motorola Moto G", 4, [[1080, 1920], [1920, 1080]], 401, nil, Platform::ANDROID, nil)
|
80
|
+
NEXUS_4 = Frameit::Device.new("nexus-4", "Nexus 4", 7, [[768, 1280], [1820, 768]], 318, nil, Platform::ANDROID)
|
81
|
+
NEXUS_5X = Frameit::Device.new("nexus-5x", "Nexus 5X", 7, [[1080, 1920], [1920, 1080]], 423, nil, Platform::ANDROID)
|
82
|
+
NEXUS_6P = Frameit::Device.new("nexus-6p", "Nexus 6P", 7, [[1440, 2560], [2560, 1440]], 518, nil, Platform::ANDROID)
|
83
|
+
NEXUS_9 = Frameit::Device.new("nexus-9", "Nexus 9", 7, [[1536, 2048], [2048, 1536]], 281, nil, Platform::ANDROID)
|
84
|
+
SAMSUNG_GALAXY_GRAND_PRIME = Frameit::Device.new("samsung-galaxy-grand-prime", "Samsung Galaxy Grand Prime", 5, [[540, 960], [960, 540]], 220, Color::BLACK, Platform::ANDROID)
|
85
|
+
SAMSUNG_GALAXY_NOTE_5 = Frameit::Device.new("samsung-galaxy-note-5", "Samsung Galaxy Note 5", 5, [[1440, 2560], [2560, 1440]], 518, Color::BLACK, Platform::ANDROID)
|
86
|
+
SAMSUNG_GALAXY_NOTE_10 = Frameit::Device.new("samsung-galaxy-note-10", "Samsung Galaxy Note 10", 6, [[1080, 2280], [2280, 1080]], 401, Color::AURA_BLACK, Platform::ANDROID)
|
87
|
+
SAMSUNG_GALAXY_NOTE_10_PLUS = Frameit::Device.new("samsung-galaxy-note-10-plus", "Samsung Galaxy Note 10+", 7, [[1440, 3040], [3040, 1440]], 498, Color::AURA_BLACK, Platform::ANDROID)
|
88
|
+
SAMSUNG_GALAXY_S_DUOS = Frameit::Device.new("samsung-galaxy-s-duos", "Samsung Galaxy S Duos", 3, [[480, 800], [800, 480]], 233, nil, Platform::ANDROID)
|
89
|
+
SAMSUNG_GALAXY_S3 = Frameit::Device.new("samsung-galaxy-s3", "Samsung Galaxy S3", 3, [[720, 1280], [1280, 720]], 306, nil, Platform::ANDROID)
|
90
|
+
SAMSUNG_GALAXY_S5 = Frameit::Device.new("samsung-galaxy-s5", "Samsung Galaxy S5", 3, [[1080, 1920], [1920, 1080]], 432, Color::BLACK, Platform::ANDROID)
|
91
|
+
SAMSUNG_GALAXY_S7 = Frameit::Device.new("samsung-galaxy-s7", "Samsung Galaxy S7", 4, [[1440, 2560], [2560, 1440]], 577, Color::BLACK, Platform::ANDROID)
|
92
|
+
SAMSUNG_GALAXY_S8 = Frameit::Device.new("samsung-galaxy-s8", "Samsung Galaxy S8", 5, [[1440, 2960], [2960, 1440]], 570, Color::MIDNIGHT_BLACK, Platform::ANDROID)
|
93
|
+
SAMSUNG_GALAXY_S9 = Frameit::Device.new("samsung-galaxy-s9", "Samsung Galaxy S9", 6, [[1440, 2960], [2960, 1440]], 570, Color::MIDNIGHT_BLACK, Platform::ANDROID)
|
94
|
+
SAMSUNG_GALAXY_S10 = Frameit::Device.new("samsung-galaxy-s10", "Samsung Galaxy S10", 7, [[1440, 3040], [3040, 1440]], 550, Color::PRISM_BLACK, Platform::ANDROID)
|
95
|
+
SAMSUNG_GALAXY_S10_PLUS = Frameit::Device.new("samsung-galaxy-s10-plus", "Samsung Galaxy S10+", 8, [[1440, 3040], [3040, 1440]], 522, Color::PRISM_BLACK, Platform::ANDROID)
|
96
|
+
XIAOMI_MI_MIX_ALPHA = Frameit::Device.new("xiaomi-mi-mix-alpha", "Xiaomi Mi Mix Alpha", 1, [[2088, 2250], [2250, 2088]], 388, nil, Platform::ANDROID)
|
97
|
+
IPHONE_5S = Frameit::Device.new("iphone-5s", "Apple iPhone 5s", 2, [[640, 1096], [640, 1136], [1136, 600], [1136, 640]], 326, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_40, :use_legacy_iphone5s)
|
98
|
+
IPHONE_5C = Frameit::Device.new("iphone-5c", "Apple iPhone 5c", 2, [[640, 1136], [1136, 640]], 326, Color::WHITE)
|
99
|
+
IPHONE_SE = Frameit::Device.new("iphone-se", "Apple iPhone SE", 3, [[640, 1096], [640, 1136], [1136, 600], [1136, 640]], 326, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_40)
|
100
|
+
IPHONE_6S = Frameit::Device.new("iphone-6s", "Apple iPhone 6s", 4, [[750, 1334], [1334, 750]], 326, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_47, :use_legacy_iphone6s)
|
101
|
+
IPHONE_6S_PLUS = Frameit::Device.new("iphone-6s-plus", "Apple iPhone 6s Plus", 4, [[1242, 2208], [2208, 1242]], 401, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_55, :use_legacy_iphone6s)
|
102
|
+
IPHONE_7 = Frameit::Device.new("iphone-7", "Apple iPhone 7", 5, [[750, 1334], [1334, 750]], 326, Color::MATTE_BLACK, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_47, :use_legacy_iphone7)
|
103
|
+
IPHONE_7_PLUS = Frameit::Device.new("iphone-7-plus", "Apple iPhone 7 Plus", 5, [[1242, 2208], [2208, 1242]], 401, Color::MATTE_BLACK, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_55, :use_legacy_iphone7)
|
104
|
+
IPHONE_8 = Frameit::Device.new("iphone-8", "Apple iPhone 8", 6, [[750, 1334], [1334, 750]], 326, Color::SPACE_GRAY)
|
105
|
+
IPHONE_8_PLUS = Frameit::Device.new("iphone-8-plus", "Apple iPhone 8 Plus", 6, [[1080, 1920], [1920, 1080]], 401, Color::SPACE_GRAY)
|
106
|
+
IPHONE_X = Frameit::Device.new("iphone-X", "Apple iPhone X", 7, [[1125, 2436], [2436, 1125]], 458, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_58, :use_legacy_iphonex)
|
107
|
+
IPHONE_XS = Frameit::Device.new("iphone-XS", "Apple iPhone XS", 8, [[1125, 2436], [2436, 1125]], 458, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_58, :use_legacy_iphonexs)
|
108
|
+
IPHONE_XR = Frameit::Device.new("iphone-XR", "Apple iPhone XR", 8, [[828, 1792], [1792, 828]], 326, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_61, :use_legacy_iphonexr)
|
109
|
+
IPHONE_XS_MAX = Frameit::Device.new("iphone-XS-Max", "Apple iPhone XS Max", 8, [[1242, 2688], [2688, 1242]], 458, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_65, :use_legacy_iphonexsmax)
|
110
|
+
IPHONE_11 = Frameit::Device.new("iphone-11", "Apple iPhone 11", 9, [[828, 1792], [1792, 828]], 326, Color::BLACK, Platform::IOS)
|
111
|
+
IPHONE_11_PRO = Frameit::Device.new("iphone-11-pro", "Apple iPhone 11 Pro", 9, [[1125, 2436], [2436, 1125]], 458, Color::SPACE_GRAY, Platform::IOS)
|
112
|
+
IPHONE_11_PRO_MAX = Frameit::Device.new("iphone11-pro-max", "Apple iPhone 11 Pro Max", 9, [[1242, 2688], [2688, 1242]], 458, Color::SPACE_GRAY, Platform::IOS)
|
113
|
+
IPAD_10_2 = Frameit::Device.new("ipad-10-2", "Apple iPad 10.2", 1, [[1620, 2160], [2160, 1620]], 264, Color::SPACE_GRAY, Platform::IOS)
|
114
|
+
IPAD_AIR_2 = Frameit::Device.new("ipad-air-2", "Apple iPad Air 2", 1, [[1536, 2048], [2048, 1536]], 264, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_IPAD)
|
115
|
+
IPAD_AIR_2019 = Frameit::Device.new("ipad-air-2019", "Apple iPad Air (2019)", 2, [[1668, 2224], [2224, 1668]], 265, Color::SPACE_GRAY, Platform::IOS)
|
116
|
+
IPAD_MINI_4 = Frameit::Device.new("ipad-mini-4", "Apple iPad Mini 4", 2, [[1536, 2048], [2048, 1536]], 324, Color::SPACE_GRAY)
|
117
|
+
IPAD_MINI_2019 = Frameit::Device.new("ipad-mini-2019", "Apple iPad Mini (2019)", 3, [[1536, 2048], [2048, 1536]], 324, Color::SPACE_GRAY)
|
118
|
+
# this is 1st or 2nd gen of iPad Pro 12.9:
|
119
|
+
IPAD_PRO = Frameit::Device.new("ipad-pro", "Apple iPad Pro", 3, [[2048, 2732], [2732, 2048]], 264, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_IPAD_PRO)
|
120
|
+
# 3rd generation:
|
121
|
+
IPAD_PRO_12_9 = Frameit::Device.new("ipadPro129", "Apple iPad Pro (12.9-inch) (3rd generation)", 4, [[2048, 2732], [2732, 2048]], 264, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_IPAD_PRO_12_9)
|
122
|
+
# iPad Pro (10.5-inch) is not in frameit-frames repo, but must be included so that we are backward compatible with PR #15373
|
123
|
+
# priority must be lower so that users who didn't copy the frame to their frameit frames folder will not get an error
|
124
|
+
# ID and formatted name must be exactly as specified so that device.detect_device() will select this device if the filename includes them
|
125
|
+
IPAD_PRO_10_5 = Frameit::Device.new("ipad105", "Apple iPad Pro (10.5-inch)", 1, [[1668, 2224], [2224, 1668]], 265, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_IPAD_10_5)
|
126
|
+
IPAD_PRO_11 = Frameit::Device.new("ipadPro11", "Apple iPad Pro (11-inch)", 1, [[1668, 2388], [2388, 1668]], 265, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_IPAD_11)
|
127
|
+
|
128
|
+
MAC = Frameit::Device.new("mac", "Apple MacBook", 0, [[1280, 800], [1440, 900], [2560, 1600], [2880, 1800]], nil, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::MAC)
|
129
|
+
|
130
|
+
def self.all_device_names_without_apple
|
131
|
+
Devices.constants.map { |c| Devices.const_get(c).formatted_name_without_apple }
|
132
|
+
end
|
133
|
+
end
|
18
134
|
end
|