icon-banner 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9efce0274be7532b108c0374f84021b8f5fed3d
4
+ data.tar.gz: 2dcc37968b8978d58989627daa69a69899156dbc
5
+ SHA512:
6
+ metadata.gz: 452fa34575ab520f92d453d0740767cbda45152de535e5fc1bb2a7a23e3bd19811bbd40383b7f415c5d63e81d221ccc25c30a2975458180f3e76f95483601088
7
+ data.tar.gz: 56234725fd3f474b8ad7c0edd48e454b77cfd2a0051026e5a789afe134b732dc85d5df11f93b55af4c9ea1e61f36fa81a2a344c284de746ad4ba5d611c3d8715
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Émile Bélair
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,133 @@
1
+ <h3 align="center">
2
+ <a href="https://github.com/ebelair/icon-banner/blob/master/.assets/icon_banner.png">
3
+ <img src="https://github.com/ebelair/icon-banner/blob/master/.assets/icon_banner.png?raw=true" alt="IconBanner" width="400">
4
+ </a>
5
+ </h3>
6
+
7
+ [![GitHub: @ebelair](https://img.shields.io/badge/author-@ebelair-blue.svg?style=flat)](https://github.com/ebelair)
8
+ [![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/fastlane/fastlane/blob/master/LICENSE)
9
+ [![Gem](https://img.shields.io/gem/v/icon-banner.svg?style=flat)](https://rubygems.org/gems/icon-banner)
10
+ [![Fastlane](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-icon_banner)
11
+
12
+ **IconBanner** adds custom nice-looking banners over your mobile app icons.
13
+
14
+ It is available both as a **command-line tool** and as a **Fastlane plugin**.
15
+
16
+ > Currently **iOS-only**, but Android is in the works.
17
+
18
+ ## Introduction
19
+
20
+ **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
+
22
+ It allows to create these kind of icons:
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/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)|
30
+
31
+ ## Setup
32
+
33
+ ### 🚀 Fastlane
34
+
35
+ Start by running this command in your project repository:
36
+
37
+ ```bash
38
+ fastlane add_plugin fastlane-plugin-icon_banner
39
+ ```
40
+
41
+ Then simply add the following actions in your Fastfile:
42
+
43
+ ```ruby
44
+ lane :sample do
45
+ icon_banner([options])
46
+ # [build_ios_app and other actions]
47
+ icon_banner_restore()
48
+ end
49
+ ```
50
+
51
+ For more details, see the [Usage](https://github.com/ebelair/icon-banner#options) section below.
52
+
53
+ ### 💻 Standalone
54
+
55
+ First install the gem:
56
+
57
+ ```bash
58
+ gem install icon-banner
59
+ ```
60
+
61
+ Then use it directly:
62
+
63
+ ```bash
64
+ icon-banner generate [options]
65
+ icon-banner restore
66
+ ```
67
+
68
+ For more details, see the [Usage](https://github.com/ebelair/icon-banner#options) section below.
69
+
70
+ ## Usage
71
+
72
+ ### Generate
73
+
74
+ Generates banners and adds them to app icons. Available via:
75
+
76
+ - The `icon_banner()` Fastlane action
77
+ - The `icon-banner generate` terminal command
78
+
79
+ | Key | Description | Default |
80
+ |--------|------------------------------------|---------|
81
+ | label | Sets the text to display inside the banner | BETA |
82
+ | color | Sets the text color (when not set, the script uses the dominant icon color) | |
83
+ | font | Sets the text font with a _direct link_ to a TTF file (when not set, the script uses the embedded LilitaOne font) | |
84
+ | backup | Creates a backup of icons before applying banners (only set to `false` if you are under source-control) | true |
85
+
86
+ Sample usages:
87
+
88
+ ```ruby
89
+ # fastlane
90
+ icon_banner(label: 'QA')
91
+ icon_banner(label: 'QA', color: '#ff000088', font: '/Users/johndoe/Documents/mybestfont.ttf')
92
+ ```
93
+
94
+ ```bash
95
+ # command-line
96
+ icon-banner generate --label QA
97
+ icon-banner generate --label QA --color '#ff000088' --font '/Users/johndoe/Documents/mybestfont.ttf'
98
+ ```
99
+
100
+ ### Restore
101
+
102
+ Restores app icons without banners (if backups are available). Available via:
103
+
104
+ - The `icon_banner_restore()` Fastlane action
105
+ - The `icon-banner restore` terminal command
106
+
107
+ No options are required – if backup files are available, they are automatically restored.
108
+
109
+ Sample usage:
110
+
111
+ ```ruby
112
+ # fastlane
113
+ icon_banner_restore()
114
+ ```
115
+
116
+ ```bash
117
+ # command-line
118
+ icon-banner restore
119
+ ```
120
+
121
+ ## Contributing
122
+
123
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ebelair/icon-banner.
124
+
125
+ ## License
126
+
127
+ IconBanner is ©2019 [ebelair](https://github.com/ebelair) and may be freely distributed under the [MIT license](https://opensource.org/licenses/MIT). See the [`LICENSE`](https://github.com/ebelair/icon-banner/blob/master/LICENSE.md) file.
128
+
129
+ The project is highly inspired by [`badge` by HazAT](https://github.com/HazAT/badge). Used also under the [MIT license](https://opensource.org/licenses/MIT). Thanks again. 🙏
130
+
131
+ ## About ebelair
132
+
133
+ [Émile Bélair](https://github.com/ebelair) acts as a Product Owner @ [Mirego](https://www.mirego.com). He enjoys creating great products and works hard with his team to deliver some of the greatest.
Binary file
data/bin/icon-banner ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $:.push File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'icon_banner'
5
+
6
+ IconBanner::IconBanner.start
@@ -0,0 +1,96 @@
1
+ require 'icon_banner/appiconset'
2
+ require 'commander'
3
+
4
+ module IconBanner
5
+ VERSION = '0.1.0'
6
+ DESCRIPTION = 'IconBanner adds custom nice-looking banners over your mobile app icons'
7
+
8
+ UI = FastlaneCore::UI
9
+
10
+ class IconBanner
11
+ include Commander::Methods
12
+
13
+ def self.start
14
+ self.new.run
15
+ end
16
+
17
+ def run
18
+ program :name, 'IconBanner'
19
+ program :version, VERSION
20
+ program :description, DESCRIPTION
21
+
22
+ global_option('--verbose', 'Shows a more verbose output') { FastlaneCore::Globals.verbose = true }
23
+
24
+ command :generate do |c|
25
+ c.syntax = 'icon-banner generate [path] [options]'
26
+ c.description = 'Generates banners and adds them to app icons'
27
+ FastlaneCore::CommanderGenerator.new.generate(IconBanner::available_options, command: c)
28
+
29
+ c.action do |args, options|
30
+ path = args[0] || '.'
31
+ options = FastlaneCore::Configuration.create(IconBanner::available_options, options.__hash__)
32
+ IconBanner.generate(path, options)
33
+ end
34
+ end
35
+
36
+ command :restore do |c|
37
+ c.syntax = 'icon-banner restore [path]'
38
+ c.description = 'Restores app icons without banners (if backups are available)'
39
+
40
+ c.action do |args|
41
+ path = args[0] || '.'
42
+ IconBanner.restore(path)
43
+ end
44
+ end
45
+
46
+ run!
47
+ end
48
+
49
+ def self.generate(path, options)
50
+ AppIconSet.new.generate(path, options)
51
+ end
52
+
53
+ def self.restore(path)
54
+ AppIconSet.new.restore(path)
55
+ end
56
+
57
+ def self.available_options
58
+ [
59
+ FastlaneCore::ConfigItem.new(key: :label,
60
+ description: 'Sets the text to display inside the banner',
61
+ default_value: 'BETA',
62
+ optional: true),
63
+
64
+ FastlaneCore::ConfigItem.new(key: :color,
65
+ description: 'Sets the text color (when not set, the script uses the dominant icon color)',
66
+ optional: true),
67
+
68
+ FastlaneCore::ConfigItem.new(key: :font,
69
+ description: 'Sets the text font with a _direct link_ to a TTF file (when not set, the script uses the embedded LilitaOne font)',
70
+ optional: true),
71
+
72
+ FastlaneCore::ConfigItem.new(key: :backup,
73
+ description: 'Creates a backup of icons before applying banners (only set to `false` if you are under source-control)',
74
+ is_string: false,
75
+ default_value: true,
76
+ optional: true)
77
+ ]
78
+ end
79
+
80
+ def self.validate_libs!
81
+ begin
82
+ UI.error('ImageMagick was not found on your system. To install it, run the following command:')
83
+ UI.command('brew install imagemagick')
84
+ UI.user_error!('IconBanner is missing requirements.')
85
+ end unless `which convert`.include?('convert')
86
+ end
87
+
88
+ def self.base_path
89
+ File.dirname __dir__ + '/../../'
90
+ end
91
+
92
+ def self.font_path
93
+ File.join base_path, 'assets', 'LilitaOne.ttf'
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,132 @@
1
+ require 'fastlane_core'
2
+ require 'mini_magick'
3
+
4
+ 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
36
+
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)
80
+ MiniMagick::Tool::Convert.new do |convert|
81
+ convert.size '1024x1024'
82
+ convert << 'xc:transparent'
83
+ convert << path
84
+ end
85
+
86
+ banner = MiniMagick::Image.new path
87
+
88
+ banner.combine_options do |combine|
89
+ combine.fill 'rgba(0,0,0,0.25)'
90
+ combine.draw 'polygon 0,306 0,590 590,0 306,0'
91
+ combine.blur '0x10'
92
+ end
93
+
94
+ banner.combine_options do |combine|
95
+ combine.fill 'white'
96
+ combine.draw 'polygon 0,306 0,590 590,0 306,0'
97
+ end
98
+
99
+ banner.combine_options do |combine|
100
+ combine.font font
101
+ combine.fill color
102
+ combine.gravity 'Center'
103
+ combine.pointsize 150 - ([label.length - 8, 0].max * 8)
104
+ combine.draw "affine 0.5,-0.5,0.5,0.5,-286,-286 text 0,0 \"#{label}\""
105
+ end
106
+ 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
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: icon-banner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Émile Bélair
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fastlane
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.100'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.100'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mini_magick
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.4'
55
+ description: IconBanner adds custom nice-looking banners over your mobile app icons
56
+ email:
57
+ - ebelair@me.com
58
+ executables:
59
+ - icon-banner
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - LICENSE
64
+ - README.md
65
+ - assets/LilitaOne.ttf
66
+ - bin/icon-banner
67
+ - lib/icon_banner.rb
68
+ - lib/icon_banner/appiconset.rb
69
+ homepage: https://github.com/ebelair/icon-banner
70
+ licenses:
71
+ - MIT
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.6.11
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Banners for your app icons
93
+ test_files: []