pindo 5.10.3 → 5.10.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ae55987c0ee58172309287267530b0230d08944f62fb31a8a12d90c877b9424
4
- data.tar.gz: 9641ac39d403ea5977ef81ef8b8aa6f63eb0cb9d04f5b13e3ce9942759a565ff
3
+ metadata.gz: cd33392e14ce3170db5963cd77255bc0b4f2c008c79a01579d726f8ef93037d0
4
+ data.tar.gz: 61fe09946921347ad84bc991512b29a0eb64e23e470961ca579b6247d8bdf166
5
5
  SHA512:
6
- metadata.gz: fb525053b7ddbf51f8135339b8f58b3dcf1415f0e5d6c1c8c58b378aba5f451a88c2a53d63925da9a43ceae4248ba6a57e28699b1c11ae4f4f8f744095a908fd
7
- data.tar.gz: cd69f12b05cb838da9963f059880a8b73f264011cdf3f2b8e5eaa683f6dae2b3a4b2e76f78d752f1455c9fe2ab928c604fa3bb5cbf55ea4e045d883285dd9b7e
6
+ metadata.gz: 9147ffd74728ab059dd4a5dbb760715735c29426c9746826ec65d01a19e411257a9e4b438e9c008bdfc3b757a759713023759fc8d8e23c190dc8f816bc31ec54
7
+ data.tar.gz: '05328944fb21eb8f33617fe20c3eb68992d8eacc29f04d847edcd1f78c0441d61f7120cace4449c898b62fc4c96f264c6390234d8a6e19d71a30e66109cf98b6'
@@ -3,12 +3,14 @@ require 'fileutils'
3
3
  require 'json'
4
4
  require 'xcodeproj'
5
5
  require 'gym'
6
+ require 'pindo/module/xcode/xcodebuildhelper'
6
7
 
7
8
  module Pindo
8
9
  class Command
9
10
  class Deploy < Command
10
11
  class Build < Deploy
11
12
 
13
+ include Pindo::XcodeBuildHelper
12
14
 
13
15
  self.summary = '编译工程'
14
16
 
@@ -22,7 +24,7 @@ module Pindo
22
24
 
23
25
  def self.options
24
26
  [
25
- ['--proj', '指定上传到pgyer对应的项目名称(大小写空格忽略),用法:pindo deploy build --proj=aichatv4'],
27
+ ['--proj', '指定上传到JPS对应的项目名称(大小写空格忽略),用法:pindo deploy build --proj=aichatv4'],
26
28
  ['--upload', '是否上传编译后的ipa(上传成功后会自动发送消息给自己), 用法:pindo deploy build --upload'],
27
29
  ['--send', '发送消息到项目群(注意:不带此参数也会发送给自己),用法:pindo deploy build --send'],
28
30
  ['--resign', '上传到之后是否重签名,用法:pindo deploy build --resign'],
@@ -72,6 +74,9 @@ module Pindo
72
74
  new_project_dir = Dir.pwd
73
75
  project_fullname = Dir.glob(File.join(new_project_dir, "/*.xcodeproj")).max_by {|f| File.mtime(f)}
74
76
 
77
+ # 修复 Xcode 16 链接器兼容性问题
78
+ fix_xcode16_linker_flags(project_dir: new_project_dir)
79
+
75
80
  if File.exist?(File.join(new_project_dir, "build"))
76
81
  FileUtils.rm_rf(File.join(new_project_dir, "build"))
77
82
  end
@@ -52,8 +52,8 @@ module Pindo
52
52
  ['--macos', 'macos平台证书'],
53
53
  ['--clean', '删除本地缓存的证书'],
54
54
  ['--cleangit', '删除远程仓库中的证书'],
55
- ['--upload', '生成上传pgyer的证书'],
56
- ['--match', '生成上传pgyer的证书'],
55
+ ['--upload', '生成上传JPS的证书'],
56
+ ['--match', '生成上传JPS的证书'],
57
57
  ['--renew', '重新生成证书']
58
58
  ].concat(super)
59
59
  end
@@ -53,7 +53,7 @@ module Pindo
53
53
  [
54
54
  ['--deploy', '默认用开发的bundle id,用法:pindo dev autobuild --deploy'],
55
55
  ['--adhoc', '默认用dev证书,使用--adhoc设置使用adhoc证书编译'],
56
- ['--proj', '指定上传到pgyer对应的项目名称(大小写空格忽略)'],
56
+ ['--proj', '指定上传到JPS对应的项目名称(大小写空格忽略)'],
57
57
  ['--upload', '是否上传编译后的ipa'],
58
58
  ['--send', '上传到之后是否发送测试信息'],
59
59
  ].concat(super)
@@ -42,7 +42,7 @@ module Pindo
42
42
 
43
43
  def self.options
44
44
  [
45
- ['--proj', '指定上传到pgyer对应的项目名称(大小写空格忽略),用法:pindo dev build --proj=aichatv4'],
45
+ ['--proj', '指定上传到JPS对应的项目名称(大小写空格忽略),用法:pindo dev build --proj=aichatv4'],
46
46
  ['--upload', '是否上传编译后的ipa, 用法:pindo dev build --upload'],
47
47
  ['--send', '上传到之后是否发送测试信息,用法:pindo dev build --send'],
48
48
  ].concat(super)
@@ -45,7 +45,7 @@ module Pindo
45
45
  # 命令的选项列表
46
46
  def self.options
47
47
  [
48
- # 指定上传到蒲公英的项目
48
+ # 指定上传到JPS的项目
49
49
  ['--proj', '指定上传到测试平台的项目名称'],
50
50
  # 上传编译包
51
51
  ['--upload', '上传编译后的ipa到测试平台'],
@@ -15,7 +15,7 @@ module Pindo
15
15
 
16
16
  include Appselect
17
17
  include Pindo::Githelper
18
- # 命令的简要说明 - 打包iOS工程并发布到蒲公英
18
+ # 命令的简要说明 - 打包iOS工程并发布到JPS
19
19
  self.summary = '打包iOS工程并发布到测试平台'
20
20
 
21
21
  # 启用缓存机制
@@ -42,7 +42,7 @@ module Pindo
42
42
  ['--deploy', '默认使用开发环境的bundle id,使用此选项切换为发布环境的bundle id'],
43
43
  ['--adhoc', '默认使用开发证书,使用此选项切换为adhoc证书'],
44
44
  ['--macos', '指定为macOS平台的证书'],
45
- ['--upload', '生成用于上传到蒲公英平台的证书'],
45
+ ['--upload', '生成用于上传到JPS平台的证书'],
46
46
  ].concat(super)
47
47
  end
48
48
 
@@ -41,8 +41,8 @@ module Pindo
41
41
  [
42
42
  ['--ipa', 'iap file name.'],
43
43
  ['--proj', '指定哪个项目(忽略大小写空格等等字符): --proj=\"prancksoundv4\"'],
44
- ['--upload', '编译完成后是否上传ipa到pyger: --upload'],
45
- ['--send', '上传到pgyer之后是否发送测试信息: --send'],
44
+ ['--upload', '编译完成后是否上传ipa到JPS: --upload'],
45
+ ['--send', '上传到JPS之后是否发送测试信息: --send'],
46
46
  ['--ipa', '强制指定重签名的ipa包,用法: --ipa=path/to/demo.ipa'],
47
47
  ['--dev', '使用dev证书,默认使用adhoc证书: --dev'],
48
48
  ['--test', '使用测试的bundle id, 默认是用发布bundle id,用法:--test'],
@@ -50,7 +50,7 @@ module Pindo
50
50
  ['--build', '修改完工程之后直接编译,用法:pindo ipa import --build'],
51
51
  ['--increase', '自动增加编译的app版本号,用法:pindo ipa import --increase'],
52
52
  ['--proj', '指定哪个项目(忽略大小写空格等等字符): --proj=\"prancksoundv4\"'],
53
- ['--upload', '编译完成后是否上传ipa到pyger: 用法:pindo ipa import --upload'],
53
+ ['--upload', '编译完成后是否上传ipa到JPS: 用法:pindo ipa import --upload'],
54
54
  ['--send', '上传到之后是否发送测试信息,用法:pindo ipa import --send'],
55
55
  ['--resign', '上传到之后是否发送测试信息,用法:pindo ipa import --resign'],
56
56
 
@@ -51,7 +51,7 @@ module Pindo
51
51
  def self.options
52
52
  [
53
53
  ['--proj', '指定哪个项目(忽略大小写空格等等字符): --proj=\"prancksoundv4\"'],
54
- ['--upload', '编译完成后是否上传ipa到pyger: 用法:pindo ipa output --upload'],
54
+ ['--upload', '编译完成后是否上传ipa到JPS: 用法:pindo ipa output --upload'],
55
55
  ['--send', '上传到之后是否发送测试信息,用法:pindo ipa output --send'],
56
56
  ['--increase', '自动增加编译的app版本号,用法:pindo ipa output --increase'],
57
57
 
@@ -36,7 +36,7 @@ module Pindo
36
36
 
37
37
  def self.options
38
38
  [
39
- ['--force', '强制重新登录pgyer'],
39
+ ['--force', '强制重新登录JPS'],
40
40
  ].concat(super)
41
41
  end
42
42
 
@@ -19,7 +19,7 @@ module Pindo
19
19
  - 支持iOS和Mac设备管理
20
20
  - 读取本地CSV文件的设备数据
21
21
  - 生成多种格式的设备列表
22
- - 兼容蒲公英平台的设备格式
22
+ - 兼容JPS平台的设备格式
23
23
  - 设备信息统一管理和对比
24
24
 
25
25
  使用示例:
@@ -29,7 +29,7 @@ module Pindo
29
29
  生成文件:
30
30
  - new_devices_list.txt - App Store格式的设备列表
31
31
  - new_user_devices_list.csv - 用户设备列表
32
- - new_pgyer_devices_list.csv - 蒲公英格式设备列表
32
+ - new_jps_devices_list.csv - JPS格式设备列表
33
33
  DESC
34
34
 
35
35
  class DeviceItem
@@ -199,7 +199,7 @@ DESC
199
199
 
200
200
  def write_apppgyer_csv(devices:nil)
201
201
 
202
- device_file = File.join(Dir.pwd, "new_pgyer_devices_list.csv");
202
+ device_file = File.join(Dir.pwd, "new_jps_devices_list.csv");
203
203
 
204
204
  devices.each do |key, item|
205
205
  if item.device_type.to_s.eql?("ipad")
@@ -231,7 +231,7 @@ DESC
231
231
  devices = {}
232
232
 
233
233
 
234
- device_file = File.join(Dir.pwd, "pgyer_devices_list.csv");
234
+ device_file = File.join(Dir.pwd, "jps_devices_list.csv");
235
235
  if File.exist?(device_file)
236
236
  line_num=0
237
237
  CSV.foreach(device_file, headers:false) do |row|
@@ -51,7 +51,7 @@ DESC
51
51
  [
52
52
 
53
53
  ['--fast', '快速更新证书,开发用bundle id只更新dev证书,发布bundle id只更新adhoc证书'],
54
- ['--upload', '生成上传pgyer的证书'],
54
+ ['--upload', '生成上传JPS的证书'],
55
55
  ['--fixedid', '重新更新bundle id的功能,检查bundle id的功能是否更新'],
56
56
  ['--renew', '重新生成证书']
57
57
  ].concat(super)
@@ -53,7 +53,7 @@ module Pindo
53
53
  def self.options
54
54
  [
55
55
  ['--bundleid', '指定打包的bundleID'],
56
- # 指定上传到蒲公英的项目
56
+ # 指定上传到JPS的项目
57
57
  ['--proj', '指定上传到测试平台的项目名称'],
58
58
  # 上传编译包
59
59
  ['--upload', '上传编译后的ipa到测试平台'],
@@ -85,8 +85,8 @@ module Pindo
85
85
  main_module = helper.get_main_module(project_dir)
86
86
 
87
87
  if main_module.nil?
88
- # 如果无法获取主模块,尝试常见的模块名
89
- ["app", "application", "main"].each do |module_name|
88
+ # 如果无法获取主模块,尝试常见的模块名(优先 launcher,支持 Unity 项目)
89
+ ["launcher", "app", "application", "main"].each do |module_name|
90
90
  module_path = File.join(project_dir, module_name)
91
91
  if File.exist?(File.join(module_path, "build.gradle")) ||
92
92
  File.exist?(File.join(module_path, "build.gradle.kts"))
@@ -116,60 +116,57 @@ module Pindo
116
116
 
117
117
  # 读取并更新gradle文件
118
118
  content = File.read(gradle_file)
119
- original_content = content.dup
120
119
 
121
- # 更新versionCode
122
- if content =~ /versionCode\s+\d+/
123
- content.gsub!(/versionCode\s+\d+/, "versionCode #{version_code}")
124
- elsif content =~ /versionCode\s*=\s*\d+/
125
- content.gsub!(/versionCode\s*=\s*\d+/, "versionCode = #{version_code}")
126
- end
120
+ # 第一步:清理所有现有的版本信息(无论在什么位置)
121
+ content.gsub!(/^\s*versionCode\s+\d+\s*$/, '')
122
+ content.gsub!(/^\s*versionCode\s*=\s*\d+\s*$/, '')
123
+ content.gsub!(/^\s*versionName\s+["'][^"']*["']\s*$/, '')
124
+ content.gsub!(/^\s*versionName\s*=\s*["'][^"']*["']\s*$/, '')
125
+
126
+ # 清理多余的空行
127
+ content.gsub!(/\n\n+/, "\n\n")
128
+
129
+ # 第二步:在 defaultConfig 块的正确位置添加版本信息
130
+ if content =~ /defaultConfig\s*\{/
131
+ # 找到 defaultConfig 的起始位置
132
+ start_pos = $~.end(0)
133
+
134
+ # 从起始位置开始,找到匹配的 }
135
+ brace_count = 1
136
+ end_pos = start_pos
137
+
138
+ while end_pos < content.length && brace_count > 0
139
+ if content[end_pos] == '{'
140
+ brace_count += 1
141
+ elsif content[end_pos] == '}'
142
+ brace_count -= 1
143
+ end
144
+ end_pos += 1
145
+ end
127
146
 
128
- # 更新versionName
129
- if content =~ /versionName\s+["'][^"']*["']/
130
- content.gsub!(/versionName\s+["'][^"']*["']/, "versionName \"#{version_name}\"")
131
- elsif content =~ /versionName\s*=\s*["'][^"']*["']/
132
- content.gsub!(/versionName\s*=\s*["'][^"']*["']/, "versionName = \"#{version_name}\"")
133
- end
147
+ if brace_count == 0
148
+ # 成功找到匹配的 }
149
+ # defaultConfig 块的末尾(但在最后的 } 之前)添加版本信息
150
+ insert_pos = end_pos - 1
134
151
 
135
- # 如果内容有变化,写回文件
136
- if content != original_content
137
- File.write(gradle_file, content)
138
- Funlog.instance.fancyinfo_success("Android版本更新完成!")
139
- puts " ✓ versionName已更新: #{version_name}"
140
- puts " ✓ versionCode已更新: #{version_code}"
141
- puts " ✓ 更新的文件: #{gradle_file}"
142
- return true
143
- else
144
- # 如果没有找到版本字段,尝试在defaultConfig块中添加
145
- if content =~ /defaultConfig\s*\{([^}]*)\}/m
146
- default_config = $1
147
- if !default_config.include?("versionCode") || !default_config.include?("versionName")
148
- Funlog.instance.fancyinfo_update("gradle文件中未找到版本字段,尝试添加...")
149
-
150
- # 在defaultConfig块中添加版本信息
151
- new_default_config = default_config
152
- unless default_config.include?("versionCode")
153
- new_default_config += "\n versionCode #{version_code}"
154
- end
155
- unless default_config.include?("versionName")
156
- new_default_config += "\n versionName \"#{version_name}\""
157
- end
152
+ version_lines = [
153
+ " versionCode #{version_code}",
154
+ " versionName \"#{version_name}\""
155
+ ]
158
156
 
159
- content.gsub!(/defaultConfig\s*\{[^}]*\}/m, "defaultConfig {#{new_default_config}\n }")
160
- File.write(gradle_file, content)
157
+ content.insert(insert_pos, "\n" + version_lines.join("\n") + "\n ")
158
+ File.write(gradle_file, content)
161
159
 
162
- Funlog.instance.fancyinfo_success("Android版本更新完成!")
163
- puts " ✓ versionName已添加: #{version_name}"
164
- puts " ✓ versionCode已添加: #{version_code}"
165
- return true
166
- end
160
+ Funlog.instance.fancyinfo_success("Android版本更新完成!")
161
+ puts " ✓ 版本号已更新: #{version_name}"
162
+ puts " ✓ Build号已更新: #{version_code}"
163
+ return true
167
164
  end
168
-
169
- Funlog.instance.fancyinfo_error("无法在gradle文件中找到或添加版本信息")
170
- return false
171
165
  end
172
166
 
167
+ Funlog.instance.fancyinfo_error("无法在gradle文件中找到或添加版本信息")
168
+ return false
169
+
173
170
  rescue StandardError => e
174
171
  Funlog.instance.fancyinfo_error("更新Android版本失败: #{e.message}")
175
172
  return false
@@ -203,7 +200,8 @@ module Pindo
203
200
  main_module = helper.get_main_module(project_dir)
204
201
 
205
202
  if main_module.nil?
206
- ["app", "application", "main"].each do |module_name|
203
+ # 尝试常见的模块名(优先 launcher,支持 Unity 项目)
204
+ ["launcher", "app", "application", "main"].each do |module_name|
207
205
  module_path = File.join(project_dir, module_name)
208
206
  if File.directory?(module_path)
209
207
  main_module = module_path
@@ -260,7 +258,8 @@ module Pindo
260
258
  main_module = helper.get_main_module(project_dir)
261
259
 
262
260
  if main_module.nil?
263
- ["app", "application", "main"].each do |module_name|
261
+ # 尝试常见的模块名(优先 launcher,支持 Unity 项目)
262
+ ["launcher", "app", "application", "main"].each do |module_name|
264
263
  module_path = File.join(project_dir, module_name)
265
264
  if File.exist?(File.join(module_path, "build.gradle")) ||
266
265
  File.exist?(File.join(module_path, "build.gradle.kts"))
@@ -322,19 +321,16 @@ module Pindo
322
321
  end
323
322
 
324
323
  scheme_name = scheme_name.to_s.gsub(/[^a-zA-Z0-9]/, '').downcase
325
- puts "正在为Android项目添加自定义scheme: #{scheme_name}"
326
324
 
327
325
  # 创建helper实例以使用基类方法
328
326
  helper = self.new
329
327
 
330
- # 查找所有可能的模块
328
+ # 查找所有可能的模块(添加 launcher 支持 Unity 项目)
331
329
  main_module = helper.get_main_module(project_dir)
332
- search_modules = ["app", "unityLibrary"]
330
+ search_modules = ["launcher", "app", "unityLibrary"]
333
331
  search_modules << main_module if main_module
334
332
  search_modules = search_modules.compact.uniq
335
333
 
336
- puts "搜索的模块: #{search_modules.join(', ')}"
337
-
338
334
  # 查找所有可能的AndroidManifest.xml文件
339
335
  manifest_candidates = find_manifests(project_dir, search_modules)
340
336
 
@@ -343,8 +339,6 @@ module Pindo
343
339
  return false
344
340
  end
345
341
 
346
- puts "找到#{manifest_candidates.size}个AndroidManifest.xml文件"
347
-
348
342
  # 寻找最佳的AndroidManifest.xml和Activity
349
343
  manifest_path, main_activity, android_prefix = find_best_activity(manifest_candidates)
350
344
 
@@ -353,8 +347,6 @@ module Pindo
353
347
  return false
354
348
  end
355
349
 
356
- puts "已选择 #{manifest_path} 文件中的 #{main_activity['android:name'] || '主Activity'}"
357
-
358
350
  # 检查scheme是否已存在
359
351
  scheme_exists, existing_scheme = check_scheme_exists(main_activity, android_prefix, scheme_name)
360
352
 
@@ -368,8 +360,6 @@ module Pindo
368
360
  else
369
361
  Funlog.instance.fancyinfo_update("scheme已存在: #{existing_scheme}")
370
362
  end
371
- else
372
- puts " ✓ scheme已存在: #{scheme_name}"
373
363
  end
374
364
  return true
375
365
  end
@@ -382,9 +372,7 @@ module Pindo
382
372
  success = add_scheme_with_text_replace(manifest_path, scheme_name)
383
373
  end
384
374
 
385
- if success
386
- puts " ✓ 成功添加scheme: #{scheme_name}"
387
- else
375
+ unless success
388
376
  Funlog.instance.fancyinfo_error("无法添加scheme: #{scheme_name}")
389
377
  end
390
378
 
@@ -106,7 +106,94 @@ module Pindo
106
106
  return success_count > 0 ? all_icons : nil
107
107
  end
108
108
 
109
- # 安装Android icon到项目中
109
+ # 清理所有旧的 icon 文件和自定义配置
110
+ # @param res_dir [String] res 目录路径
111
+ # @return [Boolean] 是否成功清理
112
+ def self.clean_old_icons(res_dir:nil)
113
+ return false unless res_dir && File.directory?(res_dir)
114
+
115
+ begin
116
+ cleaned_items = []
117
+
118
+ # 1. 删除 adaptive icon XML 目录
119
+ adaptive_dir = File.join(res_dir, "mipmap-anydpi-v26")
120
+ if Dir.exist?(adaptive_dir)
121
+ xml_files = Dir.glob(File.join(adaptive_dir, "*.xml"))
122
+ FileUtils.rm_rf(adaptive_dir)
123
+ cleaned_items << "adaptive XML(#{xml_files.size}个)" if xml_files.any?
124
+ end
125
+
126
+ # 2. 删除所有 mipmap 目录中的旧 icon 文件
127
+ old_png_count = 0
128
+ mipmap_dirs = Dir.glob(File.join(res_dir, "mipmap-*"))
129
+
130
+ mipmap_dirs.each do |mipmap_dir|
131
+ next unless File.directory?(mipmap_dir)
132
+
133
+ old_files = [
134
+ 'app_icon.png',
135
+ 'app_icon_round.png',
136
+ 'ic_launcher_foreground.png',
137
+ 'ic_launcher_background.png',
138
+ 'ic_launcher.png',
139
+ 'ic_launcher_round.png'
140
+ ]
141
+
142
+ old_files.each do |filename|
143
+ file_path = File.join(mipmap_dir, filename)
144
+ if File.exist?(file_path)
145
+ File.delete(file_path)
146
+ old_png_count += 1
147
+ end
148
+ end
149
+ end
150
+
151
+ cleaned_items << "旧icon文件(#{old_png_count}个)" if old_png_count > 0
152
+
153
+ if cleaned_items.any?
154
+ puts " ✓ 已清理: #{cleaned_items.join(', ')}"
155
+ end
156
+
157
+ return true
158
+ rescue => e
159
+ Funlog.instance.fancyinfo_error("清理旧 icon 失败: #{e.message}")
160
+ return false
161
+ end
162
+ end
163
+
164
+ # 更新 AndroidManifest.xml 为标准配置
165
+ # @param manifest_path [String] AndroidManifest.xml 文件路径
166
+ # @return [Boolean] 是否成功更新
167
+ def self.update_manifest_to_standard(manifest_path:nil)
168
+ return false unless manifest_path && File.exist?(manifest_path)
169
+
170
+ begin
171
+ require 'nokogiri'
172
+
173
+ content = File.read(manifest_path)
174
+ doc = Nokogiri::XML(content)
175
+
176
+ # 查找 <application> 标签
177
+ app_node = doc.at_xpath('//application')
178
+ return false unless app_node
179
+
180
+ # 设置标准 icon 配置
181
+ app_node['android:icon'] = '@mipmap/ic_launcher'
182
+ app_node['android:roundIcon'] = '@mipmap/ic_launcher_round'
183
+
184
+ # 保存文件
185
+ File.write(manifest_path, doc.to_xml)
186
+
187
+ puts " ✓ AndroidManifest.xml 已更新为标准 icon 配置"
188
+
189
+ return true
190
+ rescue => e
191
+ Funlog.instance.fancyinfo_error("更新 AndroidManifest.xml 失败: #{e.message}")
192
+ return false
193
+ end
194
+ end
195
+
196
+ # 安装Android icon到项目中(完全标准化方案)
110
197
  # @param proj_dir [String] Android项目目录
111
198
  # @param new_icon_dir [String] icon文件目录(包含各密度文件夹)
112
199
  # @return [Boolean] 是否成功安装
@@ -122,21 +209,40 @@ module Pindo
122
209
  end
123
210
 
124
211
  begin
125
- # 查找 res 目录(支持 app/src/main/res 和 unityLibrary/src/main/res
212
+ # 1. 查找 res 目录(支持 launcher、app 和 unityLibrary)
126
213
  possible_res_dirs = [
214
+ File.join(proj_dir, "launcher/src/main/res"),
127
215
  File.join(proj_dir, "app/src/main/res"),
128
216
  File.join(proj_dir, "unityLibrary/src/main/res")
129
217
  ]
130
218
 
131
219
  res_dir = possible_res_dirs.find { |dir| File.directory?(dir) }
132
220
 
221
+ # 如果没找到,创建默认目录
133
222
  unless res_dir
134
- Funlog.instance.fancyinfo_error("未找到Android res目录,检查的路径:\n#{possible_res_dirs.join("\n")}")
135
- return false
223
+ res_dir = File.join(proj_dir, "launcher/src/main/res")
224
+ FileUtils.mkdir_p(res_dir)
136
225
  end
137
226
 
227
+ # 2. 清理所有旧的 icon 资源
228
+ clean_old_icons(res_dir: res_dir)
229
+
230
+ # 3. 查找并更新 AndroidManifest.xml
231
+ manifest_paths = [
232
+ File.join(proj_dir, "launcher/src/main/AndroidManifest.xml"),
233
+ File.join(proj_dir, "app/src/main/AndroidManifest.xml"),
234
+ File.join(proj_dir, "src/main/AndroidManifest.xml")
235
+ ]
236
+
237
+ manifest_path = manifest_paths.find { |path| File.exist?(path) }
238
+
239
+ if manifest_path
240
+ update_manifest_to_standard(manifest_path: manifest_path)
241
+ end
242
+
243
+ # 4. 安装标准 icon 文件
138
244
  success_count = 0
139
- total_files = 0
245
+ densities_installed = []
140
246
 
141
247
  ANDROID_ICON_DENSITIES.keys.each do |density|
142
248
  source_dir = File.join(new_icon_dir, "mipmap-#{density}")
@@ -147,23 +253,35 @@ module Pindo
147
253
  # 创建目标目录
148
254
  FileUtils.mkdir_p(target_dir) unless File.directory?(target_dir)
149
255
 
150
- # 复制两个图标文件
151
- ['ic_launcher.png', 'ic_launcher_round.png'].each do |filename|
152
- source_file = File.join(source_dir, filename)
153
- target_file = File.join(target_dir, filename)
256
+ # 标准配置:只复制 ic_launcher.png 和 ic_launcher_round.png
257
+ files_to_copy = [
258
+ { source: 'ic_launcher.png', target: 'ic_launcher.png' },
259
+ { source: 'ic_launcher_round.png', target: 'ic_launcher_round.png' }
260
+ ]
261
+
262
+ density_success = 0
263
+ files_to_copy.each do |file_map|
264
+ source_file = File.join(source_dir, file_map[:source])
265
+ target_file = File.join(target_dir, file_map[:target])
154
266
 
155
267
  if File.exist?(source_file)
156
268
  FileUtils.cp(source_file, target_file)
157
269
  success_count += 1
158
- total_files += 1
159
- puts " ✓ 已安装 mipmap-#{density}/#{filename}"
270
+ density_success += 1
271
+ else
272
+ Funlog.instance.fancyinfo_error("源文件不存在: #{file_map[:source]}")
160
273
  end
161
274
  end
275
+
276
+ densities_installed << density if density_success > 0
162
277
  end
163
278
 
164
- puts "\n总计安装 #{success_count}/#{total_files} 个图标文件"
279
+ if success_count > 0
280
+ puts " ✓ 已安装标准 icon: #{densities_installed.join(', ')} (共#{success_count}个文件)"
281
+ end
165
282
 
166
283
  return success_count > 0
284
+
167
285
  rescue => e
168
286
  Funlog.instance.fancyinfo_error("安装icon时出错: #{e.message}")
169
287
  puts e.backtrace
@@ -292,20 +292,21 @@ module Pindo
292
292
  info_plist_dict = Xcodeproj::Plist.read_from_path(plist_file_name)
293
293
 
294
294
  if !icloud_id.nil?
295
-
295
+ # 需要设置 iCloud
296
296
  temp_value = {}
297
297
  if !info_plist_dict['NSUbiquitousContainers'].nil? && info_plist_dict['NSUbiquitousContainers'].is_a?(Hash)
298
298
  info_plist_dict['NSUbiquitousContainers'].each do |key, value|
299
299
  if key.include?("iCloud.")
300
300
  temp_value = value
301
- break;
301
+ break
302
302
  end
303
303
  end
304
304
  end
305
305
  info_plist_dict['NSUbiquitousContainers'] = {}
306
306
  info_plist_dict['NSUbiquitousContainers'][icloud_id] = temp_value || {}
307
307
  else
308
- info_plist_dict['NSUbiquitousContainers'] = nil
308
+ # 不需要 iCloud,删除键(如果存在)
309
+ info_plist_dict.delete('NSUbiquitousContainers')
309
310
  end
310
311
 
311
312
  Xcodeproj::Plist.write_to_path(info_plist_dict, plist_file_name)
@@ -346,7 +346,7 @@ module Pindo
346
346
  end
347
347
 
348
348
  proj_name_array.uniq
349
- proj_name_array << "自定义输入Pyger上的App代号"
349
+ proj_name_array << "自定义输入JPS上的项目名称"
350
350
 
351
351
  # 如果环境变量已经设置了项目名,跳过选择逻辑
352
352
  if !(env_project_name && !env_project_name.empty?)
@@ -356,7 +356,7 @@ module Pindo
356
356
  cached_app_key = context.get_selection(Pindo::PindoContext::SelectionKey::PROJECT_NAME)
357
357
 
358
358
  if cached_app_key && proj_name_array.include?(cached_app_key)
359
- puts "\n使用之前选择的App代号: #{cached_app_key}"
359
+ puts "\n使用之前选择的JPS项目: #{cached_app_key}"
360
360
  upload_proj_name = cached_app_key
361
361
  # 直接使用缓存的选择,跳过后续选择逻辑
362
362
  end
@@ -369,15 +369,15 @@ module Pindo
369
369
  if proj_name_array.size > 1
370
370
  cli = HighLine.new
371
371
  upload_proj_name = cli.choose do |menu|
372
- menu.prompt = "请选择Pgyer上的App代号:"
372
+ menu.prompt = "请选择JPS上的项目:"
373
373
  menu.choices(*proj_name_array)
374
374
  end
375
375
  if upload_proj_name.include?("自定义输入")
376
- upload_proj_name = ask('请输入Pyger上的App代号(大小写空格忽略):') || nil
376
+ upload_proj_name = ask('请输入JPS上的项目名称(大小写空格忽略):') || nil
377
377
  upload_proj_name = upload_proj_name.strip if upload_proj_name
378
378
  end
379
379
  else
380
- upload_proj_name = ask('请输入Pyger上的App代号(大小写空格忽略):') || nil
380
+ upload_proj_name = ask('请输入JPS上的项目名称(大小写空格忽略):') || nil
381
381
  upload_proj_name = upload_proj_name.strip if upload_proj_name
382
382
  end
383
383
 
@@ -391,13 +391,13 @@ module Pindo
391
391
  app_info_obj = PgyerHelper.share_instace.find_app_info_with_obj_list(proj_name:upload_proj_name)
392
392
 
393
393
  if app_info_obj.nil?
394
- upload_proj_name = ask('没有找到结果,请重新输入Pyger上的App代号(大小写空格忽略):') || nil
394
+ upload_proj_name = ask('没有找到结果,请重新输入JPS上的项目名称(大小写空格忽略):') || nil
395
395
  upload_proj_name = upload_proj_name.strip if upload_proj_name
396
396
  app_info_obj = PgyerHelper.share_instace.find_app_info_with_obj_list(proj_name:upload_proj_name)
397
397
  end
398
398
 
399
399
  if app_info_obj.nil?
400
- raise Informative, "#{upload_proj_name} 名称错误, 请输入正确的App代号,Pgyer网站没有该App!!!"
400
+ raise Informative, "#{upload_proj_name} 名称错误, 请输入正确的项目名称,JPS网站没有该项目!!!"
401
401
  else
402
402
  # 记录上次上传的项目
403
403
  PindoUserLocalConfig.instance.write_last_work_project(proj_name:app_info_obj["projectName"])
@@ -424,7 +424,7 @@ module Pindo
424
424
 
425
425
 
426
426
  else
427
- raise Informative, "请先登录Pgyer网站"
427
+ raise Informative, "请先登录JPS网站"
428
428
  end
429
429
  @proj_name = upload_proj_name
430
430
  app_info_obj
@@ -893,7 +893,7 @@ module Pindo
893
893
 
894
894
  if app_info_list.nil?
895
895
  Funlog.instance.fancyinfo_error("拉取app信息列表失败!")
896
- raise Informative, "Pgyer网络数据异常!!!"
896
+ raise Informative, "JPS网络数据异常!!!"
897
897
  end
898
898
 
899
899
 
@@ -1061,11 +1061,11 @@ module Pindo
1061
1061
  puts
1062
1062
 
1063
1063
  if comment_str.nil? || comment_str.empty?
1064
- Funlog.instance.fancyinfo_error("没有找到git备注信息,无法修改pgyer备注!")
1064
+ Funlog.instance.fancyinfo_error("没有找到git备注信息,无法修改JPS备注!")
1065
1065
  else
1066
- Funlog.instance.fancyinfo_start("开始修复pgyer备注...")
1066
+ Funlog.instance.fancyinfo_start("开始修复JPS备注...")
1067
1067
  @pgyer_client.update_project_package(projectId:app_info_obj["id"], id:version_item_obj["id"], comment:comment_str.strip)
1068
- Funlog.instance.fancyinfo_start("pgyer备注已经修改!")
1068
+ Funlog.instance.fancyinfo_start("JPS备注已经修改!")
1069
1069
  end
1070
1070
 
1071
1071
 
@@ -318,6 +318,87 @@ module Pindo
318
318
 
319
319
  end
320
320
 
321
+ # 修复 Xcode 16 链接器兼容性问题
322
+ # 自动移除 -ld_classic 和 -ld64 标志
323
+ def fix_xcode16_linker_flags(project_dir: nil)
324
+ begin
325
+ # 查找所有 xcodeproj 文件
326
+ workspace_file = Dir.glob(File.join(project_dir, "*.xcworkspace")).first
327
+ project_files = []
328
+
329
+ if workspace_file && File.exist?(workspace_file)
330
+ # 如果存在 workspace,从中提取所有项目
331
+ workspace_data_file = File.join(workspace_file, "contents.xcworkspacedata")
332
+ if File.exist?(workspace_data_file)
333
+ require 'rexml/document'
334
+ doc = REXML::Document.new(File.read(workspace_data_file))
335
+ doc.elements.each('Workspace/FileRef') do |file_ref|
336
+ location = file_ref.attributes['location']
337
+ if location && location.start_with?('group:')
338
+ relative_path = location.sub('group:', '')
339
+ if relative_path.end_with?('.xcodeproj')
340
+ full_path = File.join(project_dir, relative_path)
341
+ project_files << full_path if File.exist?(full_path)
342
+ end
343
+ end
344
+ end
345
+ end
346
+ else
347
+ # 直接查找项目文件
348
+ project_files = Dir.glob(File.join(project_dir, "**/*.xcodeproj"))
349
+ end
350
+
351
+ return if project_files.empty?
352
+
353
+ fixed_count = 0
354
+
355
+ project_files.each do |project_path|
356
+ begin
357
+ project = Xcodeproj::Project.open(project_path)
358
+ project_modified = false
359
+
360
+ project.targets.each do |target|
361
+ target.build_configurations.each do |config|
362
+ ldflags = config.build_settings['OTHER_LDFLAGS']
363
+ next unless ldflags
364
+
365
+ original_flags = ldflags.dup
366
+
367
+ # 移除过时的链接器标志
368
+ if ldflags.is_a?(Array)
369
+ ldflags.delete('-ld_classic')
370
+ ldflags.delete('-ld64')
371
+ elsif ldflags.is_a?(String)
372
+ ldflags = ldflags.gsub(/-ld_classic|-ld64/, '').strip
373
+ end
374
+
375
+ if original_flags != ldflags
376
+ config.build_settings['OTHER_LDFLAGS'] = ldflags
377
+ project_modified = true
378
+ end
379
+ end
380
+ end
381
+
382
+ if project_modified
383
+ project.save
384
+ fixed_count += 1
385
+ end
386
+
387
+ rescue => e
388
+ # 静默处理错误,不中断构建
389
+ end
390
+ end
391
+
392
+ if fixed_count > 0
393
+ puts "✅ 修复 Xcode 16 链接器兼容性配置".green
394
+ end
395
+
396
+ rescue => error
397
+ puts "⚠️ 修复链接器标志时出现错误: #{error.message}".yellow
398
+ # 不中断构建流程
399
+ end
400
+ end
401
+
321
402
 
322
403
  end
323
404
 
data/lib/pindo/version.rb CHANGED
@@ -6,7 +6,7 @@ require 'time'
6
6
 
7
7
  module Pindo
8
8
 
9
- VERSION = "5.10.3"
9
+ VERSION = "5.10.6"
10
10
 
11
11
  class VersionCheck
12
12
  RUBYGEMS_API = 'https://rubygems.org/api/v1/gems/pindo.json'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pindo
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.10.3
4
+ version: 5.10.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - wade