Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image magick replacement + app variants #3691

Merged
merged 2 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
p12-password: ${{ secrets.ALPHA_CERTIFICATES_P12_PASSWORD }}

- name: Build alpha
run: bundle exec fastlane alpha
run: bundle exec fastlane build_alpha
env:
APPSTORECONNECT_KEY_ID: ${{ secrets.APPSTORECONNECT_KEY_ID }}
APPSTORECONNECT_KEY_ISSUER_ID: ${{ secrets.APPSTORECONNECT_KEY_ISSUER_ID }}
Expand Down
67 changes: 67 additions & 0 deletions Tools/Sources/AppIconBanner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import ArgumentParser
import SwiftUI

struct AppIconBanner: AsyncParsableCommand {
static var configuration = CommandConfiguration(
abstract: "A Swift command-line tool to add a banner to an app icons."
)

@Argument(help: "Path to the input image.")
var path: String

@Option(help: "Text for the banner.")
var bannerText: String

@MainActor
func run() async throws {
let currentDirectoryURL = URL(filePath: FileManager.default.currentDirectoryPath)
let pathURL = currentDirectoryURL.appending(path: path)

guard let image = NSImage(contentsOf: pathURL) else {
throw ValidationError("Could not load the image at \(pathURL).")
}

let renderer = ImageRenderer(content: BannerImage(image: image,
text: bannerText))

do {
guard let cgImage = renderer.cgImage else {
throw ValidationError("Couldn't generate CG image.")
}

let bitmap = NSBitmapImageRep(cgImage: cgImage)

guard let pngData = bitmap.representation(using: .png, properties: [:]) else {
throw ValidationError("Couldn't create png data from image.")
}

try pngData.write(to: pathURL)
print("Successfully saved the image with a banner to \(pathURL).")
} catch {
throw ValidationError("Failed to save the image: \(error).")
}
}
}

struct BannerImage: View {
let image: NSImage
let text: String

var body: some View {
ZStack(alignment: .bottom) {
Image(nsImage: image)
.resizable()
.aspectRatio(contentMode: .fit)

Text(text)
.frame(maxWidth: .infinity)
.padding()
.background(Color.black.opacity(0.5))
.foregroundColor(.white)
.font(.system(size: 140))
.lineLimit(1)
.allowsTightening(true)
}
.frame(width: image.size.width, height: image.size.height)
}
}
5 changes: 3 additions & 2 deletions Tools/Sources/Tools.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import ArgumentParser
import Foundation

@main
struct Tools: ParsableCommand {
struct Tools: AsyncParsableCommand {
static var configuration = CommandConfiguration(abstract: "A collection of command line tools for ElementX",
subcommands: [BuildSDK.self,
SetupProject.self,
OutdatedPackages.self,
DownloadStrings.self,
Locheck.self,
GenerateSDKMocks.self,
GenerateSAS.self])
GenerateSAS.self,
AppIconBanner.self])
stefanceriu marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"images" : [
{
"filename" : "AppIcon.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions Variants/Alpha/Resources/Alpha.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
11 changes: 11 additions & 0 deletions Variants/Alpha/alpha.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
settings:
BASE_APP_GROUP_IDENTIFIER: io.element.pr
BASE_BUNDLE_IDENTIFIER: io.element.elementx.pr

targets:
ElementX:
settings:
base:
ASSETCATALOG_COMPILER_APPICON_NAME: AlphaAppIcon
sources:
- path: Resources
6 changes: 6 additions & 0 deletions Variants/Nightly/Resources/Nightly.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"images" : [
{
"filename" : "AppIcon.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
11 changes: 11 additions & 0 deletions Variants/Nightly/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
settings:
BASE_APP_GROUP_IDENTIFIER: io.element.nightly
BASE_BUNDLE_IDENTIFIER: io.element.elementx.nightly

targets:
ElementX:
settings:
base:
ASSETCATALOG_COMPILER_APPICON_NAME: NightlyAppIcon
sources:
- path: Resources
10 changes: 0 additions & 10 deletions ci_scripts/ci_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ setup_xcode_cloud_environment () {

install_xcode_cloud_brew_dependencies () {
brew update && brew install xcodegen

if [ "$CI_WORKFLOW" = "Nightly" ]; then
brew install imagemagick@6
brew link imagemagick@6 # imagemagick@6 is keg-only, which means it was not symlinked into /usr/local,
fi
}

setup_github_actions_environment() {
Expand All @@ -44,11 +39,6 @@ setup_github_actions_environment() {

brew update && brew install xcodegen swiftformat git-lfs a7ex/homebrew-formulae/xcresultparser

if [ "$CI_WORKFLOW" = "PR_BUILD" ]; then
brew install imagemagick@6
brew link imagemagick@6 # imagemagick@6 is keg-only, which means it was not symlinked into /usr/local,
fi

# brew "swiftlint" # Fails on the CI: `Target /usr/local/bin/swiftlint Target /usr/local/bin/swiftlint already exists`. Installed through https://github.com/actions/virtual-environments/blob/main/images/macos/macos-12-Readme.md#linters

bundle config path vendor/bundle
Expand Down
38 changes: 11 additions & 27 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ before_all do
ENV["SENTRY_LOG_LEVEL"] = "DEBUG"
end

lane :alpha do
lane :build_alpha do
app_store_connect_api_key(
key_id: ENV["APPSTORECONNECT_KEY_ID"],
issuer_id: ENV["APPSTORECONNECT_KEY_ISSUER_ID"],
key_content: ENV["APPSTORECONNECT_KEY_CONTENT"]
)

config_xcodegen_alpha()
config_alpha()

code_signing_identity = "Apple Distribution: Vector Creations Limited (7J4U792NQT)"

Expand Down Expand Up @@ -170,7 +170,7 @@ lane :config_nightly do |options|

target_file_path = "../project.yml"
data = YAML.load_file target_file_path
data["include"].append({ "path" => "fastlane/nightly.yml" })
data["include"].append({ "path" => "Variants/Nightly/nightly.yml" })

config_secrets()

Expand All @@ -184,7 +184,9 @@ lane :config_nightly do |options|

release_version = get_version_number(target: "ElementX")

update_app_icon(caption_text: "#{release_version} (#{build_number})", modulate: "100,20,100")
Dir.chdir ".." do
sh("swift run tools app-icon-banner Variants/Nightly/Resources/Nightly.xcassets/NightlyAppIcon.appiconset/AppIcon.png --banner-text '#{release_version} (#{build_number})'")
end
end

$sentry_retry=0
Expand Down Expand Up @@ -311,17 +313,19 @@ private_lane :git_push do |options|
sh("git push https://#{api_token}@#{repo_url}")
end

private_lane :config_xcodegen_alpha do
lane :config_alpha do
target_file_path = "../project.yml"
data = YAML.load_file target_file_path
data["include"].append({ "path" => "fastlane/alpha.yml" })
data["include"].append({ "path" => "Variants/Alpha/alpha.yml" })
File.open(target_file_path, 'w') { |f| YAML.dump(data, f) }

xcodegen(spec: "project.yml")

version = ENV["GITHUB_PR_NUMBER"]

update_app_icon(caption_text: "PR #{version}", modulate: "100,100,200")
Dir.chdir ".." do
sh("swift run tools app-icon-banner Variants/Alpha/Resources/Alpha.xcassets/AlphaAppIcon.appiconset/AppIcon.png --banner-text 'PR #{version}'")
end

bump_build_number()
end
Expand Down Expand Up @@ -371,26 +375,6 @@ private_lane :bump_build_number do
increment_build_number(build_number: build_number)
end

private_lane :update_app_icon do |options|
caption_text = options[:caption_text]
UI.user_error!("Invalid caption text.") unless !caption_text.to_s.empty?

modulate = options[:modulate]
UI.user_error!("Invalid icon modulate parameters.") unless !modulate.to_s.empty?

Dir.glob("../ElementX/Resources/Assets.xcassets/AppIcon.appiconset/**/*.png") do |file_name|
# Change the icons color
sh("convert '#{file_name}' -modulate #{modulate} '#{file_name}'")

image_width = sh("identify -format %w '#{file_name}'")
image_height = sh("identify -format %h '#{file_name}'").to_i
caption_height = image_height / 5

# Add a label on top
sh("convert -background '#0008' -fill white -gravity center -size '#{image_width}'x'#{caption_height}' caption:'#{caption_text}' '#{file_name}' +swap -gravity south -composite '#{file_name}'")
end
end

private_lane :create_simulator_if_necessary do |options|
simulator_name = options[:name]
UI.user_error!("Invalid simulator name") unless !simulator_name.to_s.empty?
Expand Down
3 changes: 0 additions & 3 deletions fastlane/alpha.yml

This file was deleted.

3 changes: 0 additions & 3 deletions fastlane/nightly.yml

This file was deleted.

Loading