pindo 5.7.1 → 5.8.0

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.
@@ -1,27 +1,34 @@
1
1
  require 'fileutils'
2
2
  require 'xcodeproj'
3
3
  require 'json'
4
+ require 'open-uri'
4
5
  require_relative '../../base/funlog'
5
6
 
6
7
  module Pindo
7
8
 
8
9
  class XcodeBuildConfig
9
10
 
10
- # 使用package_name更新Display Name到iOS工程的Info.plist
11
+ # 使用package_name一次性更新Display Name、Bundle ID和URL Schemes
12
+ # 优化版本:只读写一次plist文件,提高性能
11
13
  # @param project_dir [String] iOS项目目录路径
12
14
  # @param package_name [String] 工作流的package_name(如:"Test Demo")
13
15
  # @return [Boolean] 是否成功更新
14
- def self.update_display_name_with_packagename(project_dir: nil, package_name: nil)
16
+ def self.update_project_with_packagename(project_dir: nil, package_name: nil)
15
17
  raise ArgumentError, "项目目录不能为空" if project_dir.nil?
16
18
  raise ArgumentError, "Package Name不能为空" if package_name.nil?
17
19
 
18
- # 生成 Display Name(去除特殊字符和空格)
20
+ # 生成各种值
19
21
  display_name = package_name.gsub(/[^a-zA-Z0-9\s]/, '').gsub(/\s+/, '')
22
+ bundle_id_suffix = package_name.gsub(/[^a-zA-Z0-9]/, '').downcase
23
+ final_bundle_id = "com.heroneverdie101.#{bundle_id_suffix}"
24
+ package_scheme = package_name.gsub(/[^a-zA-Z0-9]/, '').downcase
25
+ bundle_scheme = final_bundle_id.gsub(/[^a-zA-Z0-9]/, '').downcase
20
26
 
21
27
  project_fullname = Dir.glob(File.join(project_dir, "/*.xcodeproj")).max_by {|f| File.mtime(f)}
22
28
  return false if project_fullname.nil?
23
29
 
24
30
  info_plist_path = nil
31
+ app_target = nil
25
32
 
26
33
  project_obj = Xcodeproj::Project.open(project_fullname)
27
34
  project_obj.targets.each do |target|
@@ -30,59 +37,39 @@ module Pindo
30
37
  if temp_info_file && !temp_info_file.empty?
31
38
  info_plist_path = File.join(project_dir, temp_info_file)
32
39
  end
40
+ app_target = target
33
41
  break # 找到第一个application target即可
34
42
  end
35
43
  end
36
44
 
37
45
  return false unless info_plist_path && File.exist?(info_plist_path)
38
46
 
39
- # 使用Xcodeproj::Plist读写plist
47
+ # 一次性读取plist
40
48
  info_plist_dict = Xcodeproj::Plist.read_from_path(info_plist_path)
41
- info_plist_dict["CFBundleDisplayName"] = display_name
42
- Xcodeproj::Plist.write_to_path(info_plist_dict, info_plist_path)
43
49
 
44
- puts " ✓ Display Name 已更新为: #{display_name} (来自: #{package_name})"
45
- return true
46
- end
47
-
48
- # 使用package_name更新Bundle ID到iOS工程(同时修改plist和xcodeproj)
49
- # @param project_dir [String] iOS项目目录路径
50
- # @param package_name [String] 工作流的package_name(如:"Test Demo")
51
- # @return [Boolean] 是否成功更新
52
- def self.update_bundleid_with_packagename(project_dir: nil, package_name: nil)
53
- raise ArgumentError, "项目目录不能为空" if project_dir.nil?
54
- raise ArgumentError, "Package Name不能为空" if package_name.nil?
55
-
56
- # 从 package_name 生成 Bundle ID
57
- bundle_id_suffix = package_name.gsub(/[^a-zA-Z0-9]/, '').downcase
58
- final_bundle_id = "com.heroneverdie101.#{bundle_id_suffix}"
50
+ # 1. 更新 Display Name
51
+ info_plist_dict["CFBundleDisplayName"] = display_name
59
52
 
60
- project_fullname = Dir.glob(File.join(project_dir, "/*.xcodeproj")).max_by {|f| File.mtime(f)}
61
- return false if project_fullname.nil?
53
+ # 2. 更新 Bundle ID(plist)
54
+ info_plist_dict["CFBundleIdentifier"] = final_bundle_id
62
55
 
63
- info_plist_path = nil
64
- app_target = nil
56
+ # 3. 添加 URL Schemes
57
+ info_plist_dict["CFBundleURLTypes"] ||= []
65
58
 
66
- project_obj = Xcodeproj::Project.open(project_fullname)
67
- project_obj.targets.each do |target|
68
- if target.product_type.to_s.eql?("com.apple.product-type.application")
69
- temp_info_file = target.build_configurations.first.build_settings['INFOPLIST_FILE']
70
- if temp_info_file && !temp_info_file.empty?
71
- info_plist_path = File.join(project_dir, temp_info_file)
72
- end
73
- app_target = target
74
- break # 找到第一个application target即可
75
- end
59
+ # 添加基于 package_name 的 URL Scheme
60
+ if add_single_scheme(info_plist_dict, package_scheme)
61
+ puts " ✓ 已添加URL Scheme: #{package_scheme} (基于 Package Name)"
76
62
  end
77
63
 
78
- return false unless info_plist_path && File.exist?(info_plist_path)
64
+ # 添加基于 Bundle ID URL Scheme
65
+ if add_single_scheme(info_plist_dict, bundle_scheme)
66
+ puts " ✓ 已添加URL Scheme: #{bundle_scheme} (基于 Bundle ID)"
67
+ end
79
68
 
80
- # 1. 修改 Info.plist 中的 CFBundleIdentifier
81
- info_plist_dict = Xcodeproj::Plist.read_from_path(info_plist_path)
82
- info_plist_dict["CFBundleIdentifier"] = final_bundle_id
69
+ # 一次性写入plist
83
70
  Xcodeproj::Plist.write_to_path(info_plist_dict, info_plist_path)
84
71
 
85
- # 2. 修改 Xcode 项目中的 PRODUCT_BUNDLE_IDENTIFIER
72
+ # 4. 更新 Xcode 项目中的 PRODUCT_BUNDLE_IDENTIFIER
86
73
  if app_target
87
74
  app_target.build_configurations.each do |config|
88
75
  config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = final_bundle_id
@@ -90,49 +77,8 @@ module Pindo
90
77
  project_obj.save
91
78
  end
92
79
 
93
- puts " ✓ Bundle ID 已更新为: #{final_bundle_id} (来自: #{package_name})"
94
- return true
95
- end
96
-
97
- # 使用package_name添加URL Scheme到iOS工程的Info.plist
98
- # @param project_dir [String] iOS项目目录路径
99
- # @param package_name [String] 工作流的package_name(如:"Test Demo")
100
- # @return [Boolean] 是否成功添加
101
- def self.add_url_scheme_packagename(project_dir: nil, package_name: nil)
102
- raise ArgumentError, "项目目录不能为空" if project_dir.nil?
103
- raise ArgumentError, "Package Name不能为空" if package_name.nil?
104
-
105
- # 从 package_name 生成 URL Scheme(去除特殊字符,转小写)
106
- scheme_value = package_name.to_s.gsub(/[^a-zA-Z0-9]/, '').downcase
107
-
108
- project_fullname = Dir.glob(File.join(project_dir, "/*.xcodeproj")).max_by {|f| File.mtime(f)}
109
- return false if project_fullname.nil?
110
-
111
- info_plist_path = nil
112
-
113
- project_obj = Xcodeproj::Project.open(project_fullname)
114
- project_obj.targets.each do |target|
115
- if target.product_type.to_s.eql?("com.apple.product-type.application")
116
- temp_info_file = target.build_configurations.first.build_settings['INFOPLIST_FILE']
117
- if temp_info_file && !temp_info_file.empty?
118
- info_plist_path = File.join(project_dir, temp_info_file)
119
- end
120
- break # 找到第一个application target即可
121
- end
122
- end
123
-
124
- return false unless info_plist_path && File.exist?(info_plist_path)
125
-
126
- # 使用Xcodeproj::Plist读写plist
127
- info_plist_dict = Xcodeproj::Plist.read_from_path(info_plist_path)
128
- info_plist_dict["CFBundleURLTypes"] ||= []
129
-
130
- # 添加基于package_name的URL Scheme
131
- if add_single_scheme(info_plist_dict, scheme_value)
132
- Xcodeproj::Plist.write_to_path(info_plist_dict, info_plist_path)
133
- puts " ✓ 已添加URL Scheme: #{scheme_value} (来自: #{package_name})"
134
- end
135
-
80
+ puts " ✓ Display Name 已更新为: #{display_name}"
81
+ puts " ✓ Bundle ID 已更新为: #{final_bundle_id}"
136
82
  return true
137
83
  end
138
84
 
@@ -368,6 +314,78 @@ module Pindo
368
314
  return false
369
315
  end
370
316
 
317
+ # 从URL下载Icon并替换iOS工程的Icon
318
+ # @param project_dir [String] iOS项目目录路径
319
+ # @param icon_url [String] Icon的下载URL地址
320
+ # @return [Boolean] 是否成功下载并替换Icon
321
+ def self.download_and_replace_icon_from_url(project_dir: nil, icon_url: nil)
322
+ # 参数校验 - 不抛出异常,返回 false
323
+ if project_dir.nil?
324
+ Funlog.instance.fancyinfo_error("Icon 替换失败: 项目目录不能为空")
325
+ return false
326
+ end
327
+
328
+ if icon_url.nil? || icon_url.empty?
329
+ Funlog.instance.fancyinfo_error("Icon 替换失败: Icon URL不能为空")
330
+ return false
331
+ end
332
+
333
+ puts "\n检测到项目 Icon URL: #{icon_url}"
334
+
335
+ # 创建临时目录(所有 icon 处理都在此目录内完成)
336
+ temp_icon_dir = File.join(project_dir, ".pindo_temp_icon")
337
+ icon_download_path = nil
338
+ replace_success = false
339
+
340
+ begin
341
+ FileUtils.mkdir_p(temp_icon_dir) unless File.exist?(temp_icon_dir)
342
+ icon_download_path = File.join(temp_icon_dir, "downloaded_icon.png")
343
+
344
+ # 下载 icon
345
+ Funlog.instance.fancyinfo_start("正在从 JPS 下载项目 Icon...")
346
+ URI.open(icon_url) do |file|
347
+ File.binwrite(icon_download_path, file.read)
348
+ end
349
+ Funlog.instance.fancyinfo_success("Icon 下载成功!")
350
+
351
+ # 验证文件已下载
352
+ unless File.exist?(icon_download_path)
353
+ Funlog.instance.fancyinfo_error("Icon 下载失败: 文件未创建")
354
+ return false
355
+ end
356
+
357
+ # 生成新的 icon 目录(放在临时目录内部)
358
+ new_icon_dir = File.join(temp_icon_dir, "generated_icons")
359
+
360
+ # 创建各种尺寸的 icon
361
+ Funlog.instance.fancyinfo_start("正在创建 icon...")
362
+ XcodeResHelper.create_icons(
363
+ icon_name: icon_download_path,
364
+ new_icon_dir: new_icon_dir
365
+ )
366
+ Funlog.instance.fancyinfo_success("创建 icon 完成!")
367
+
368
+ # 替换工程中的 icon
369
+ Funlog.instance.fancyinfo_start("正在替换 icon...")
370
+ XcodeResHelper.install_icon(
371
+ proj_dir: project_dir,
372
+ new_icon_dir: new_icon_dir
373
+ )
374
+ Funlog.instance.fancyinfo_success("替换 icon 完成!")
375
+ replace_success = true
376
+
377
+ rescue => e
378
+ Funlog.instance.fancyinfo_error("Icon 处理失败: #{e.message}")
379
+ puts e.backtrace
380
+ replace_success = false
381
+ ensure
382
+ # 清理临时文件(无论成功失败都清理)
383
+ FileUtils.rm_rf(temp_icon_dir) if temp_icon_dir && File.exist?(temp_icon_dir)
384
+ end
385
+
386
+ return replace_success
387
+ end
388
+
371
389
  end
372
390
 
373
391
  end
data/lib/pindo/version.rb CHANGED
@@ -6,7 +6,7 @@ require 'time'
6
6
 
7
7
  module Pindo
8
8
 
9
- VERSION = "5.7.1"
9
+ VERSION = "5.8.0"
10
10
 
11
11
  class VersionCheck
12
12
  RUBYGEMS_API = 'https://rubygems.org/api/v1/gems/pindo.json'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pindo
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.7.1
4
+ version: 5.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - wade
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-10-20 00:00:00.000000000 Z
10
+ date: 2025-10-22 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: claide
@@ -421,6 +421,7 @@ files:
421
421
  - lib/pindo/config/pindoconfig.rb
422
422
  - lib/pindo/config/pindouserlocalconfig.rb
423
423
  - lib/pindo/module/android/android_build_config_helper.rb
424
+ - lib/pindo/module/android/androidreshelper.rb
424
425
  - lib/pindo/module/android/apk_helper.rb
425
426
  - lib/pindo/module/android/base_helper.rb
426
427
  - lib/pindo/module/android/build_helper.rb