icon-banner 0.1.0 → 0.1.1
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/README.md +18 -9
- data/lib/icon_banner.rb +4 -1
- data/lib/icon_banner/appiconset.rb +6 -98
- data/lib/icon_banner/ic_launcher.rb +76 -0
- data/lib/icon_banner/process.rb +112 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 77a0db864ce24768bed2ea3922bcd9b663ae016b
|
|
4
|
+
data.tar.gz: b6ae889f7b0e5b270046a8ed9a74725c1a8ad584
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
20
|
+
It allows to create this kind of icons:
|
|
21
|
+
|
|
22
|
+
### 🍏 iOS
|
|
23
|
+
|
|
24
|
+
|Original|Daily|QA|Staging|Production|
|
|
25
|
+
|---|---|---|---|---|
|
|
26
|
+
||||||
|
|
27
|
+
||||||
|
|
28
|
+
||||||
|
|
29
|
+
||||||
|
|
30
|
+
|
|
31
|
+
### 🤖 Android
|
|
23
32
|
|
|
24
33
|
|Original|Daily|QA|Staging|Production|
|
|
25
34
|
|---|---|---|---|---|
|
|
26
|
-
||||||
|
|
36
|
+
||||||
|
|
37
|
+
||||||
|
|
38
|
+
||||||
|
|
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
|
|
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.
|
|
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/*.
|
|
7
|
-
|
|
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
|
-
|
|
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.
|
|
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-
|
|
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
|