icon-banner 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f9efce0274be7532b108c0374f84021b8f5fed3d
4
- data.tar.gz: 2dcc37968b8978d58989627daa69a69899156dbc
3
+ metadata.gz: 77a0db864ce24768bed2ea3922bcd9b663ae016b
4
+ data.tar.gz: b6ae889f7b0e5b270046a8ed9a74725c1a8ad584
5
5
  SHA512:
6
- metadata.gz: 452fa34575ab520f92d453d0740767cbda45152de535e5fc1bb2a7a23e3bd19811bbd40383b7f415c5d63e81d221ccc25c30a2975458180f3e76f95483601088
7
- data.tar.gz: 56234725fd3f474b8ad7c0edd48e454b77cfd2a0051026e5a789afe134b732dc85d5df11f93b55af4c9ea1e61f36fa81a2a344c284de746ad4ba5d611c3d8715
6
+ metadata.gz: ce341e6efcce3f1487415c18391aecbc5eac6c48f0f28250f39cdb57bf0062160a7419ec2f9b6363ab6a675c55fadd15b23d44cb8eb4b9939821b9d0cd996961
7
+ data.tar.gz: 57a2f335650809cf1a80a539952dee4fafbed898d4fc2adb71dc4997370365e94634c6ae4c00fee8df069a5405a420aaf3f3acb3a42d2319c01a7de8870a98ee
data/README.md CHANGED
@@ -13,20 +13,29 @@
13
13
 
14
14
  It is available both as a **command-line tool** and as a **Fastlane plugin**.
15
15
 
16
- > Currently **iOS-only**, but Android is in the works.
17
-
18
16
  ## Introduction
19
17
 
20
18
  **IconBanner** is inspired by the great [HazAT/badge](https://github.com/HazAT/badge). It provides custom banner creation on-the-fly, allowing to create different text banners for different build contexts.
21
19
 
22
- It allows to create these kind of icons:
20
+ It allows to create this kind of icons:
21
+
22
+ ### 🍏 iOS
23
+
24
+ |Original|Daily|QA|Staging|Production|
25
+ |---|---|---|---|---|
26
+ |![FaceTime Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/facetime.png)|![FaceTime Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/facetime_Daily.png)|![FaceTime QA](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/facetime_QA.png)|![FaceTime Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/facetime_Staging.png)|![FaceTime Production](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/facetime_Production.png)|
27
+ |![iBooks Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/ibooks.png)|![iBooks Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/ibooks_Daily.png)|![iBooks QA](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/ibooks_QA.png)|![iBooks Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/ibooks_Staging.png)|![iBooks Production](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/ibooks_Production.png)|
28
+ |![Podcasts Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/podcasts.png)|![Podcasts Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/podcasts_Daily.png)|![Podcasts QA](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/podcasts_QA.png)|![Podcasts Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/podcasts_Staging.png)|![Podcasts Production](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/podcasts_Production.png)|
29
+ |![TestFlight Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/testflight.png)|![TestFlight Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/testflight_Daily.png)|![TestFlight QA](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/testflight_QA.png)|![TestFlight Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/testflight_Staging.png)|![TestFlight Production](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.reference/testflight_Production.png)|
30
+
31
+ ### 🤖 Android
23
32
 
24
33
  |Original|Daily|QA|Staging|Production|
25
34
  |---|---|---|---|---|
26
- |![FaceTime Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/facetime.png)|![FaceTime Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/facetime_Daily.png)|![FaceTime QA](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/facetime_QA.png)|![FaceTime Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/facetime_Staging.png)|![FaceTime Production](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/facetime_Production.png)|
27
- |![iBooks Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/ibooks.png)|![iBooks Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/ibooks_Daily.png)|![iBooks QA](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/ibooks_QA.png)|![iBooks Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/ibooks_Staging.png)|![iBooks Production](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/ibooks_Production.png)|
28
- |![Podcasts Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/podcasts.png)|![Podcasts Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/podcasts_Daily.png)|![Podcasts QA](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/podcasts_QA.png)|![Podcasts Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/podcasts_Staging.png)|![Podcasts Production](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/podcasts_Production.png)|
29
- |![TestFlight Regular](https://github.com/ebelair/icon-banner/raw/master/spec/Sample.appiconset/testflight.png)|![TestFlight Daily](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/testflight_Daily.png)|![TestFlight QA](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/testflight_QA.png)|![TestFlight Staging](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/testflight_Staging.png)|![TestFlight Production](https://github.com/ebelair/icon-banner/raw/master/spec/Reference/testflight_Production.png)|
35
+ |![Calender Regular](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_icons/calendar/ic_launcher.png)|![Calender Daily](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/calendar/ic_launcher_Daily.png)|![Calender QA](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/calendar/ic_launcher_QA.png)|![Calender Staging](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/calendar/ic_launcher_Staging.png)|![Calender Production](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/calendar/ic_launcher_Production.png)|
36
+ |![Games Regular](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_icons/games/ic_launcher.png)|![Games Daily](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/games/ic_launcher_Daily.png)|![Games QA](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/games/ic_launcher_QA.png)|![Games Staging](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/games/ic_launcher_Staging.png)|![Games Production](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/games/ic_launcher_Production.png)|
37
+ |![Mail Regular](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_icons/mail/ic_launcher.png)|![Mail Daily](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/mail/ic_launcher_Daily.png)|![Mail QA](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/mail/ic_launcher_QA.png)|![Mail Staging](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/mail/ic_launcher_Staging.png)|![Mail Production](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/mail/ic_launcher_Production.png)|
38
+ |![Movies Regular](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_icons/movies/ic_launcher.png)|![Movies Daily](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/movies/ic_launcher_Daily.png)|![Movies QA](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/movies/ic_launcher_QA.png)|![Movies Staging](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/movies/ic_launcher_Staging.png)|![Movies Production](https://github.com/ebelair/icon-banner/raw/master/spec/ic_launcher_reference/movies/ic_launcher_Production.png)|
30
39
 
31
40
  ## Setup
32
41
 
@@ -35,7 +44,7 @@ It allows to create these kind of icons:
35
44
  Start by running this command in your project repository:
36
45
 
37
46
  ```bash
38
- fastlane add_plugin fastlane-plugin-icon_banner
47
+ fastlane add_plugin icon_banner
39
48
  ```
40
49
 
41
50
  Then simply add the following actions in your Fastfile:
@@ -58,7 +67,7 @@ First install the gem:
58
67
  gem install icon-banner
59
68
  ```
60
69
 
61
- Then use it directly:
70
+ Then use it directly from the root of your app repository:
62
71
 
63
72
  ```bash
64
73
  icon-banner generate [options]
data/lib/icon_banner.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'icon_banner/appiconset'
2
+ require 'icon_banner/ic_launcher'
2
3
  require 'commander'
3
4
 
4
5
  module IconBanner
5
- VERSION = '0.1.0'
6
+ VERSION = '0.1.1'
6
7
  DESCRIPTION = 'IconBanner adds custom nice-looking banners over your mobile app icons'
7
8
 
8
9
  UI = FastlaneCore::UI
@@ -48,10 +49,12 @@ module IconBanner
48
49
 
49
50
  def self.generate(path, options)
50
51
  AppIconSet.new.generate(path, options)
52
+ IcLauncher.new.generate(path, options)
51
53
  end
52
54
 
53
55
  def self.restore(path)
54
56
  AppIconSet.new.restore(path)
57
+ IcLauncher.new.restore(path)
55
58
  end
56
59
 
57
60
  def self.available_options
@@ -1,82 +1,14 @@
1
+ require 'icon_banner/process'
2
+
1
3
  require 'fastlane_core'
2
4
  require 'mini_magick'
3
5
 
4
6
  module IconBanner
5
- class AppIconSet
6
- BASE_ICON_PATH = '/**/*.appiconset/*.{png,PNG}'
7
- BACKUP_EXTENSION = '.bak'
8
-
9
- def generate(path, options)
10
- IconBanner.validate_libs!
11
-
12
- restore(path) # restore in case it was already run before
13
-
14
- app_icons = get_app_icons(path)
15
-
16
- label = options[:label]
17
- font = options[:font] || IconBanner.font_path
18
-
19
- if app_icons.count > 0
20
- UI.message 'Starting banner process...'
21
-
22
- app_icons.each do |icon_path|
23
- UI.verbose "Processing #{icon_path}"
24
- create_backup icon_path if options[:backup]
25
-
26
- color = options[:color]
27
- begin
28
- color = find_base_color(icon_path)
29
- UI.verbose "Color: #{color}"
30
- end unless color
31
-
32
- banner_file = Tempfile.new %w[banner .png]
33
- generate_banner banner_file.path, color, label, font
34
- process_icon icon_path, banner_file.path
35
- banner_file.close
7
+ class AppIconSet < Process
8
+ BASE_ICON_PATH = '/**/*.appiconset/*.png'
9
+ PLATFORM = 'iOS'
36
10
 
37
- UI.verbose "Completed processing #{File.basename icon_path}"
38
- UI.verbose ''
39
- end
40
-
41
- UI.message 'Completed banner process.'
42
- else
43
- UI.error('No icon found.')
44
- end
45
- end
46
-
47
- def restore(path)
48
- app_icons = get_app_icons(path)
49
-
50
- if app_icons.count > 0
51
- UI.message 'Starting restore...'
52
-
53
- app_icons.each do |icon_path|
54
- UI.verbose "Restoring #{icon_path}"
55
- restore_backup icon_path
56
- end
57
-
58
- UI.message 'Completed restore.'
59
- end
60
- end
61
-
62
- def get_app_icons(path)
63
- app_icons = Dir.glob("#{path}#{BASE_ICON_PATH}")
64
- app_icons.reject { |i| i[/\/Carthage\//] || i[/\/Pods\//] ||i[/\/Releases\//] }
65
- end
66
-
67
- def find_base_color(path)
68
- color = MiniMagick::Tool::Convert.new do |convert|
69
- convert << path
70
- convert.colors 3
71
- convert << '-unique-colors'
72
- convert.format '%[pixel:u]'
73
- convert << 'xc:transparent'
74
- convert << 'info:-'
75
- end
76
- color[/rgba?\([^)]*\)/]
77
- end
78
-
79
- def generate_banner(path, color, label, font)
11
+ def generate_banner(path, label, color, font)
80
12
  MiniMagick::Tool::Convert.new do |convert|
81
13
  convert.size '1024x1024'
82
14
  convert << 'xc:transparent'
@@ -104,29 +36,5 @@ module IconBanner
104
36
  combine.draw "affine 0.5,-0.5,0.5,0.5,-286,-286 text 0,0 \"#{label}\""
105
37
  end
106
38
  end
107
-
108
- def process_icon(icon_path, banner_path)
109
- icon = MiniMagick::Image.open(icon_path)
110
- banner = MiniMagick::Image.open(banner_path)
111
- banner.resize "#{icon.width}x#{icon.height}"
112
- icon.composite(banner).write(icon_path)
113
- end
114
-
115
- def create_backup(icon_path)
116
- FileUtils.cp(icon_path, backup_path(icon_path))
117
- end
118
-
119
- def restore_backup(icon_path)
120
- restore_path = backup_path(icon_path)
121
- if File.exists?(restore_path)
122
- FileUtils.cp(restore_path, icon_path)
123
- File.delete restore_path
124
- end
125
- end
126
-
127
- def backup_path(path)
128
- ext = File.extname path
129
- path.gsub(ext, BACKUP_EXTENSION + ext)
130
- end
131
39
  end
132
40
  end
@@ -0,0 +1,76 @@
1
+ require 'icon_banner/process'
2
+
3
+ require 'fastlane_core'
4
+ require 'mini_magick'
5
+
6
+ module IconBanner
7
+ class IcLauncher < Process
8
+ BASE_ICON_PATH = '/**/ic_launcher*.png'
9
+ PLATFORM = 'Android (Legacy)'
10
+
11
+ def generate_banner(path, label, color, font)
12
+ size = 1024
13
+ font_size = 140 - ([label.length - 12, 0].max * 12)
14
+
15
+ # Start by computing the text
16
+ MiniMagick::Tool::Convert.new do |convert|
17
+ convert.size '1024x1024'
18
+ convert << 'xc:transparent'
19
+ convert << path
20
+ end
21
+
22
+ banner = MiniMagick::Image.new path
23
+
24
+ banner.combine_options do |combine|
25
+ combine.font font
26
+ combine.fill color
27
+ combine.gravity 'Center'
28
+ combine.pointsize font_size
29
+ combine.draw "text 0,0 \"#{label}\""
30
+ combine.trim
31
+ end
32
+
33
+ margin = 20
34
+ padding = 60
35
+ radius = 25
36
+ width = banner.width + padding * 2
37
+ height = 262
38
+
39
+ # Then restart the image and apply the banner
40
+ MiniMagick::Tool::Convert.new do |convert|
41
+ convert.size "#{size}x#{size}"
42
+ convert << 'xc:transparent'
43
+ convert << path
44
+ end
45
+
46
+ banner = MiniMagick::Image.new path
47
+
48
+ x_start = size - margin * 2 - width
49
+ x_end = size - margin
50
+ y_start = size - margin - height
51
+ y_end = size - margin
52
+ polygon = "roundRectangle #{x_start},#{y_start} #{x_end},#{y_end} #{radius},#{radius}"
53
+
54
+ banner.combine_options do |combine|
55
+ combine.fill 'rgba(0,0,0,0.25)'
56
+ combine.draw polygon
57
+ combine.blur '0x10'
58
+ end
59
+
60
+ banner.combine_options do |combine|
61
+ combine.fill 'white'
62
+ combine.draw polygon
63
+ end
64
+
65
+ x_middle = x_start + (x_end - x_start) / 2
66
+ y_middle = y_start + (y_end - y_start) / 2
67
+ banner.combine_options do |combine|
68
+ combine.font font
69
+ combine.fill color
70
+ combine.gravity 'Center'
71
+ combine.pointsize font_size
72
+ combine.draw "text #{x_middle - size / 2},#{y_middle - size / 2} \"#{label}\""
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,112 @@
1
+ require 'fastlane_core'
2
+ require 'mini_magick'
3
+
4
+ module IconBanner
5
+ class Process
6
+ BASE_ICON_PATH = '__TO OVERRIDE__'
7
+ PLATFORM = '__TO OVERRIDE__'
8
+
9
+ BACKUP_EXTENSION = '.bak'
10
+
11
+ def generate(path, options)
12
+ IconBanner.validate_libs!
13
+
14
+ restore(path) # restore in case it was already run before
15
+
16
+ app_icons = get_app_icons(path)
17
+
18
+ label = options[:label]
19
+ font = options[:font] || IconBanner.font_path
20
+
21
+ if app_icons.count > 0
22
+ UI.message "Generating #{self.class::PLATFORM} banners..."
23
+
24
+ app_icons.each do |icon_path|
25
+ UI.verbose "Processing #{icon_path}"
26
+ create_backup icon_path if options[:backup]
27
+
28
+ color = options[:color]
29
+ begin
30
+ color = find_base_color(icon_path)
31
+ UI.verbose "Color: #{color}"
32
+ end unless color
33
+
34
+ banner_file = Tempfile.new %w[banner .png]
35
+ generate_banner banner_file.path, label, color, font
36
+ process_icon icon_path, banner_file.path
37
+ banner_file.close
38
+
39
+ UI.verbose "Completed processing #{File.basename icon_path}"
40
+ UI.verbose ''
41
+ end
42
+
43
+ UI.message "Completed #{self.class::PLATFORM} generation."
44
+ else
45
+ UI.error('No icon found.')
46
+ UI.message self.class::BASE_ICON_PATH
47
+ end
48
+ end
49
+
50
+ def restore(path)
51
+ app_icons = get_app_icons(path)
52
+
53
+ if app_icons.count > 0
54
+ UI.message "Restoring #{self.class::PLATFORM} icons..."
55
+
56
+ app_icons.each do |icon_path|
57
+ UI.verbose "Restoring #{icon_path}"
58
+ restore_backup icon_path
59
+ end
60
+
61
+ UI.message "Completed #{self.class::PLATFORM} restore."
62
+ end
63
+ end
64
+
65
+ def get_app_icons(path)
66
+ app_icons = Dir.glob("#{path}#{self.class::BASE_ICON_PATH}")
67
+ app_icons.reject { |i| i[/\/Carthage\//] || i[/\/Pods\//] ||i[/\/Releases\//] }
68
+ end
69
+
70
+ def find_base_color(path)
71
+ color = MiniMagick::Tool::Convert.new do |convert|
72
+ convert << path
73
+ convert.colors 3
74
+ convert.background 'white'
75
+ convert.alpha 'remove'
76
+ convert << '-unique-colors'
77
+ convert.format '%[pixel:u]'
78
+ convert << 'xc:transparent'
79
+ convert << 'info:-'
80
+ end
81
+ color[/rgba?\([^)]*\)/]
82
+ end
83
+
84
+ def generate_banner(path, label, color, font)
85
+ UI.error 'Should not be run on base class'
86
+ end
87
+
88
+ def process_icon(icon_path, banner_path)
89
+ icon = MiniMagick::Image.open(icon_path)
90
+ banner = MiniMagick::Image.open(banner_path)
91
+ banner.resize "#{icon.width}x#{icon.height}"
92
+ icon.composite(banner).write(icon_path)
93
+ end
94
+
95
+ def create_backup(icon_path)
96
+ FileUtils.cp(icon_path, backup_path(icon_path))
97
+ end
98
+
99
+ def restore_backup(icon_path)
100
+ restore_path = backup_path(icon_path)
101
+ if File.exists?(restore_path)
102
+ FileUtils.cp(restore_path, icon_path)
103
+ File.delete restore_path
104
+ end
105
+ end
106
+
107
+ def backup_path(path)
108
+ ext = File.extname path
109
+ path.gsub(ext, BACKUP_EXTENSION + ext)
110
+ end
111
+ end
112
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icon-banner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Émile Bélair
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-21 00:00:00.000000000 Z
11
+ date: 2019-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fastlane
@@ -66,6 +66,8 @@ files:
66
66
  - bin/icon-banner
67
67
  - lib/icon_banner.rb
68
68
  - lib/icon_banner/appiconset.rb
69
+ - lib/icon_banner/ic_launcher.rb
70
+ - lib/icon_banner/process.rb
69
71
  homepage: https://github.com/ebelair/icon-banner
70
72
  licenses:
71
73
  - MIT