SettingPage.ets 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699
  1. import TitleBar from '../view/TitleBar'
  2. import { promptAction, router } from '@kit.ArkUI'
  3. import { CommonConstants } from '../common/constants/CommonConstants'
  4. import { AppUtil, DeviceUtil, DisplayUtil, FileUtil, MD5, PreferencesUtil, ToastUtil } from '@pura/harmony-utils'
  5. import { CustomContentDialog } from '@kit.ArkUI'
  6. import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant';
  7. import common from '@ohos.app.ability.common';
  8. import { photoAccessHelper } from '@kit.MediaLibraryKit'
  9. import { fileIo, fileUri } from '@kit.CoreFileKit'
  10. import { BusinessError, emitter } from '@kit.BasicServicesKit'
  11. import { BreakpointTypeEnum } from '../common/util/BreakpointSystem'
  12. import { Utility } from '../common/util/Utility'
  13. import { HSBColorPicker } from '@keke/color-picker'
  14. import { DialogHelper } from '@pura/harmony-dialog'
  15. import { bundleManager } from '@kit.AbilityKit'
  16. import { hilog } from '@kit.PerformanceAnalysisKit'
  17. @Preview
  18. // @Entry
  19. @Component
  20. export struct SettingPage {
  21. @Consume isShowDrawer: boolean;
  22. @Consume offsetX: number;
  23. @Consume mType: number;
  24. static readonly THEME_MODE: string = 'themeMode';
  25. static readonly SORT_TYPE: string = 'musicSortType';
  26. static readonly IS_BGPLAY_OPEN: string = 'isBgPlayOpen';
  27. static readonly IS_AUTO_RATATE: string = 'isAutoRatate';
  28. static readonly iS_MEMORY_PLAY: string = 'isMemoryPlay';
  29. static readonly IS_MIDIACODEC_OPEN: string = 'isMediacodec';
  30. static readonly iS_MUSIC_MEMORY_PLAY: string = 'isMusicMemoryPlay';
  31. static readonly iS_MUSIC_BG_COVER: string = 'isMusicBGCover';
  32. static readonly iS_SAVE_PLAY_MODE: string = 'isSavePlayMode';
  33. static readonly IS_COVER_RECTANGLE: string = 'isCoverRectangle'; //封面圆形或者方形
  34. static readonly IS_SHOW_SIMI: string = 'isShowSimi';
  35. static readonly IS_SHOW_FAV: string = 'isShowFAV';
  36. static readonly IS_SHOW_HISTORY: string = 'isShowHistory';
  37. static readonly IS_CUSTOMIZE_BG: string = 'is_customize_bg';
  38. static readonly IS_GRID_MUSIC: string = 'is_grid_music';
  39. static readonly IS_CUSTOMIZE_BG_PATH: string = 'is_customize_bg_path';
  40. static readonly IS_SCROLL_HIDE: string = 'isScrollHide';
  41. static readonly IS_SAMETIME_PLAY: string = 'isSameTimePlay';
  42. static readonly CUSTOMIZE_BG_BLUR: string = 'customize_bg_blur';
  43. static readonly BG_BRIGHTNESS: string = 'bg_brightness';
  44. static readonly IS_SHOW_ALLBAR: string = 'IS_SHOW_ALLBAR';
  45. static readonly IS_SHOW_TITLTBAR: string = 'IS_SHOW_TITLTBAR';
  46. static readonly IS_SHOW_PLAYPAGE_BACK: string = 'IS_SHOW_PLAYPAGE_BACK';
  47. static readonly IS_SHOW_SLLYRIC: string = 'IS_SHOW_SLLYRIC';
  48. static readonly IS_CIRCLE_BTN: string = 'isCircleBtn';
  49. static readonly IS_COVER_TOP: string = 'IS_COVER_TOP';
  50. static readonly IS_COVER_TOP_BIG: string = 'IS_COVER_TOP_BIG';
  51. public static THEME_COLOR_KEY: string = 'THEME_COLOR';
  52. public static TWO_FINGER_TYPE: string = 'twoFingerType';
  53. public static THEME_COLOR_LIST: Array<ThemeColorItem> = [
  54. { name: '玫瑰粉', color: '#FF4081', isVip: false },
  55. { name: '经典蓝', color: '#0A59F7', isVip: false },
  56. { name: '活力黄', color: '#FFC107', isVip: true },
  57. { name: '枫叶红', color: '#F44336', isVip: true },
  58. { name: '幻影紫', color: '#9C27B0', isVip: true },
  59. { name: '翡翠绿', color: '#64BB5C', isVip: true },
  60. { name: '竹青蓝', color: '#00BCD4', isVip: true },
  61. { name: '深空灰', color: '#607D8B', isVip: true },
  62. { name: '橙霞橙', color: '#FF9800', isVip: true },
  63. { name: '湖水蓝', color: '#00BFFF', isVip: true },
  64. { name: '柠檬绿', color: '#C6FF00', isVip: true },
  65. { name: '樱花粉', color: '#FF69B4', isVip: true },
  66. { name: '暮夜蓝', color: '#283593', isVip: true },
  67. { name: '薄荷青', color: '#1DE9B6', isVip: true },
  68. { name: '银沙灰', color: '#B0BEC5', isVip: true },
  69. { name: '自定义', color: '#ffecec', isVip: true }
  70. ];
  71. static readonly iS_START_AUTO_PLAY: string = 'isStartAutoPlay';
  72. static readonly iS_MEMORY_LAST_PLAY: string = 'isMemoryLastPlay';
  73. @State showApiDialog: boolean = false
  74. @State tempApiUrl: string = ''
  75. @State lyricApiUrl: string = PreferencesUtil.getStringSync('LRC_API', '')
  76. @State isBgPlayOpen: boolean = true //是否启用后台播放
  77. @State isAutoRatate: boolean = true //是否启用自动横竖屏
  78. @State isMemoryPlay: boolean = true //是否启用记忆播放
  79. @State isMediacodec: boolean = false //是否启用硬件解码
  80. @State isMusicMemoryPlay: boolean = false //是否启用记忆播放
  81. @State isMusicBGCover: boolean = true //播放背景随封面
  82. @State sortType: number = 4 //默认排序方式
  83. @State isStartAutoPlay: boolean = false //启动后自动播放
  84. @State isMemoryLastPlay: boolean = false //是否启用应用退出记忆最后一首的播放进度
  85. @State isShowSimi: boolean = false //是否显示私密音频
  86. @State isShowFAV: boolean = true //是否显示我的收藏
  87. @State isShowHistory: boolean = true //是否显示最近播放
  88. @State isShowPlayPageBack: boolean = false //是否显示播放页返回键
  89. @State isShowSingleLineLyric: boolean = false //是否显示播放页返回键
  90. @State isCustomizeBg: boolean = false //自定义背景界面
  91. @State isCustomizeBgSheet: boolean = false //自定义背景界面
  92. @State isShowTitleBar: boolean = true //是否显示分类导航条
  93. @State isShowAllBar: boolean = true //是否显示播放全部条
  94. @State blurValue: number = 0 //背景模糊
  95. @State bgBrightness: number = 0 //背景亮度
  96. @State isGridMusic: boolean = true //是否网格布局
  97. @State isCircleBtn: boolean = false //是否圆形播放按钮
  98. @State twoFingerType: number = 3 //双指放大瘦小Grid或list的大小
  99. @State isScrollHide: boolean = false //是否滚动隐藏
  100. @State isSameTimePlay: boolean = false //是否和其他app同时播放
  101. @State isSavePlayMode: boolean = true
  102. @State isCoverTop: boolean = true
  103. @State isCoverTopBig: boolean = false//顶部大封面部分手机显示会和播放控制页重叠
  104. @State customizeBgPath: string | undefined = '';
  105. context = getContext(this);
  106. @State showCoverApiDialog: boolean = false
  107. @State tempCoverApiUrl: string = ''
  108. @State coverApiUrl: string = PreferencesUtil.getStringSync('COVER_API', '')
  109. @State apiDialogType: 'lyric' | 'cover' = 'lyric'
  110. @State themeMode: number = 0 // 0: 跟随系统, 1: 浅色, 2: 深色
  111. @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
  112. ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  113. @StorageLink('isDarkMode') isDarkMode: boolean = false // 是否启用深色模式
  114. /** 当前断点类型(如大屏/小屏) */
  115. @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD;
  116. @State verName: string = ''
  117. @StorageProp('themeColor') themeColor: string =
  118. PreferencesUtil.getStringSync('THEME_COLOR', CommonConstants.DEFAULT_THEME_COLOR);
  119. @State showColorPicker: boolean = false
  120. @State customColor: string = PreferencesUtil.getStringSync('THEME_COLOR', CommonConstants.DEFAULT_THEME_COLOR);
  121. @State isThemeSheet: boolean = false // 主题设置弹窗显示状态
  122. @State colorRows: Array<Array<ThemeColorItem>> = chunkArray(SettingPage.THEME_COLOR_LIST, 2);
  123. @State colorGroup: string = "group"
  124. @StorageProp('topRectHeight') topRectHeight: number = px2vp(AppUtil.getStatusBarHeight());
  125. apiDialogController: CustomDialogController = new CustomDialogController({
  126. builder: CustomContentDialog({
  127. primaryTitle: this.apiDialogType === 'lyric' ? '修改歌词API地址' : '修改封面API地址',
  128. contentBuilder: () => {
  129. this.buildApiDialogContent();
  130. },
  131. buttons: [
  132. {
  133. value: '取消',
  134. action: () => {
  135. this.apiDialogController.close();
  136. }
  137. },
  138. {
  139. value: '保存',
  140. action: () => {
  141. if (this.apiDialogType === 'lyric') {
  142. this.lyricApiUrl = this.tempApiUrl.trim()
  143. PreferencesUtil.put('LRC_API', this.lyricApiUrl)
  144. this.getUIContext().getPromptAction().showToast({
  145. message: '保存成功,当前LRC_API:' + this.lyricApiUrl,
  146. duration: 2000,
  147. showMode: promptAction.ToastShowMode.TOP_MOST,
  148. bottom: 85
  149. })
  150. } else {
  151. this.coverApiUrl = this.tempApiUrl.trim()
  152. PreferencesUtil.put('COVER_API', this.coverApiUrl)
  153. this.getUIContext().getPromptAction().showToast({
  154. message: '保存成功,当前COVER_API:' + this.coverApiUrl,
  155. duration: 2000,
  156. showMode: promptAction.ToastShowMode.TOP_MOST,
  157. bottom: 85
  158. })
  159. }
  160. this.apiDialogController.close();
  161. }
  162. }
  163. ]
  164. }),
  165. autoCancel: true,
  166. alignment: DialogAlignment.Center
  167. })
  168. @Builder
  169. buildApiDialogContent() {
  170. Column() {
  171. TextInput({
  172. text: this.tempApiUrl,
  173. placeholder: this.apiDialogType === 'lyric' ? '请输入歌词API地址' : '请输入封面API地址'
  174. })
  175. .onChange((val: string) => {
  176. this.tempApiUrl = val
  177. })
  178. .width('90%')
  179. .height(60)
  180. }
  181. .width('100%')
  182. }
  183. // 组件生命周期
  184. aboutToAppear() {
  185. this.geIDD()
  186. this.topRectHeight = px2vp(AppUtil.getStatusBarHeight());
  187. this.isBgPlayOpen = PreferencesUtil.getBooleanSync(SettingPage.IS_BGPLAY_OPEN, true)
  188. this.isAutoRatate = PreferencesUtil.getBooleanSync(SettingPage.IS_AUTO_RATATE, true)
  189. this.isMemoryPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MEMORY_PLAY, true)
  190. this.isMediacodec = PreferencesUtil.getBooleanSync(SettingPage.IS_MIDIACODEC_OPEN, false)
  191. this.isMusicMemoryPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_MEMORY_PLAY, false)
  192. this.isMusicBGCover = PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_BG_COVER, true)
  193. this.sortType = PreferencesUtil.getNumberSync(SettingPage.SORT_TYPE, 4)
  194. this.isShowSimi = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_SIMI, false)
  195. this.isShowFAV = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_FAV, true)
  196. this.isShowHistory = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_HISTORY, true)
  197. this.isCustomizeBg = PreferencesUtil.getBooleanSync(SettingPage.IS_CUSTOMIZE_BG, false)
  198. this.customizeBgPath = PreferencesUtil.getStringSync(SettingPage.IS_CUSTOMIZE_BG_PATH, '')
  199. this.isGridMusic = PreferencesUtil.getBooleanSync(SettingPage.IS_GRID_MUSIC, true)
  200. this.isScrollHide = PreferencesUtil.getBooleanSync(SettingPage.IS_SCROLL_HIDE, false)
  201. this.isSameTimePlay = PreferencesUtil.getBooleanSync(SettingPage.IS_SAMETIME_PLAY, false)
  202. this.isSavePlayMode = PreferencesUtil.getBooleanSync(SettingPage.iS_SAVE_PLAY_MODE, true)
  203. this.blurValue = PreferencesUtil.getNumberSync(SettingPage.CUSTOMIZE_BG_BLUR, 0)
  204. this.bgBrightness = PreferencesUtil.getNumberSync(SettingPage.BG_BRIGHTNESS, 0)
  205. this.isStartAutoPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_START_AUTO_PLAY, false)
  206. this.isMemoryLastPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MEMORY_LAST_PLAY, false)
  207. this.twoFingerType = PreferencesUtil.getNumberSync(SettingPage.TWO_FINGER_TYPE, 3)
  208. this.isCircleBtn = PreferencesUtil.getBooleanSync(SettingPage.IS_CIRCLE_BTN, true)
  209. this.isCoverTop = PreferencesUtil.getBooleanSync(SettingPage.IS_COVER_TOP, false)
  210. this.isShowTitleBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_TITLTBAR, true)
  211. this.isShowAllBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_ALLBAR, true)
  212. this.isShowPlayPageBack = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_PLAYPAGE_BACK, false)
  213. this.isShowSingleLineLyric = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_SLLYRIC, false)
  214. this.isCoverTopBig = PreferencesUtil.getBooleanSync(SettingPage.IS_COVER_TOP_BIG, false)
  215. // 只用 themeMode 控制主题
  216. this.themeMode = PreferencesUtil.getNumberSync(SettingPage.THEME_MODE, 0)
  217. this.applyThemeMode(this.themeMode)
  218. let themeColor = PreferencesUtil.getStringSync('THEME_COLOR', CommonConstants.DEFAULT_THEME_COLOR);
  219. AppStorage.setOrCreate('themeColor', themeColor);
  220. this.themeColor = themeColor;
  221. }
  222. // 监听颜色模式变化
  223. onColorModeChange(): void {
  224. this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
  225. AppStorage.setOrCreate('isDarkMode', this.isDarkMode);
  226. }
  227. // 组件生命周期
  228. aboutToDisappear() {
  229. // 无需处理apiDialogController
  230. }
  231. applyThemeMode(mode: number) {
  232. let colorMode = ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET
  233. if (mode === 1) {
  234. colorMode = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT
  235. } else if (mode === 2) {
  236. colorMode = ConfigurationConstant.ColorMode.COLOR_MODE_DARK
  237. }
  238. AppStorage.setOrCreate('currentColorMode', colorMode)
  239. AppStorage.setOrCreate('isDarkMode', colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK)
  240. PreferencesUtil.putSync(SettingPage.THEME_MODE, mode)
  241. AppStorage.setOrCreate('themeMode', mode)
  242. // 只有强制浅色/深色时才主动设置
  243. const context = getContext(this) as common.UIAbilityContext
  244. context.getApplicationContext().setColorMode(colorMode)
  245. }
  246. @Builder
  247. pickerBuilder() {
  248. Column({ space: 20 }) {
  249. HSBColorPicker({
  250. color: this.customColor,
  251. radius: 8,
  252. onChange: (value: string) => {
  253. this.customColor = value
  254. }
  255. })
  256. .layoutWeight(1)
  257. .padding(15)
  258. Row({ space: 10 }) {
  259. Button('取消')
  260. .stateEffect(true)
  261. .backgroundColor(this.themeColor)
  262. .onClick(() => {
  263. this.showColorPicker = false
  264. })
  265. Button('确定')
  266. .stateEffect(true)
  267. .backgroundColor(this.themeColor)
  268. .onClick(() => {
  269. this.themeColor = this.customColor
  270. PreferencesUtil.putSync(SettingPage.THEME_COLOR_KEY, this.customColor)
  271. AppStorage.setOrCreate('themeColor', this.customColor)
  272. this.sendChangeEvent()
  273. this.showColorPicker = false
  274. })
  275. }
  276. }
  277. .padding(20)
  278. .width('80%')
  279. .height(300)
  280. }
  281. @Builder
  282. themeSheetBuilder() {
  283. Column() {
  284. // 颜色模式分组卡片
  285. Column() {
  286. Row() {
  287. Row() {
  288. Image($r('app.media.theme'))
  289. .width(20)
  290. .height(20)
  291. .fillColor(this.themeColor)
  292. Text('颜色模式')
  293. .fontSize(15)
  294. .margin({ left: 6 })
  295. .fontWeight(500)
  296. }
  297. .layoutWeight(1)
  298. Blank()
  299. Row() {
  300. ForEach(['自动', '日间', '夜间'], (item: string, idx: number) => {
  301. Column() {
  302. Radio({
  303. value: idx.toString(),
  304. group: this.colorGroup,
  305. })
  306. .checked(this.themeMode === idx)
  307. .radioStyle({
  308. checkedBackgroundColor: this.themeColor
  309. })
  310. .margin({ left: 3, right: 3 })
  311. .onClick(() => {
  312. this.themeMode = idx
  313. this.applyThemeMode(idx)
  314. this.sendChangeEvent()
  315. })
  316. Text(item)
  317. .fontSize(15)
  318. .fontColor($r('app.color.text_color'))
  319. .margin({ top: 6 })
  320. .onClick(() => {
  321. this.themeMode = idx
  322. this.applyThemeMode(idx)
  323. this.sendChangeEvent()
  324. })
  325. }
  326. .alignItems(HorizontalAlign.Center)
  327. .margin({ left: 12, right: 12 })
  328. })
  329. }
  330. .margin({ left: 12, right: 12 })
  331. }
  332. }
  333. .backgroundColor($r('app.color.settings_background_main'))
  334. .borderRadius(18)
  335. .border({ width: 1, color: '#F0F0F0' })
  336. .shadow({
  337. radius: 12,
  338. color: 0x11000000,
  339. offsetX: 0,
  340. offsetY: 2
  341. })
  342. .margin({
  343. left: 0,
  344. right: 0,
  345. bottom: 20
  346. })
  347. .padding({
  348. top: 18,
  349. bottom: 18,
  350. left: 20,
  351. right: 20
  352. })
  353. .width('90%')
  354. // 主题色分组卡片
  355. Column() {
  356. Row() {
  357. Image($r('app.media.theme'))
  358. .width(20)
  359. .height(20)
  360. .fillColor(this.themeColor)
  361. Text('主题色')
  362. .fontSize(15)
  363. .fontWeight(500)
  364. .margin({ left: 8 })
  365. .layoutWeight(1)
  366. }
  367. .margin({ left: 20, top: 12 })
  368. Row() {
  369. Column() {
  370. ForEach(this.colorRows, (row: Array<ThemeColorItem>, rowIdx: number) => {
  371. Row() {
  372. ForEach(row, (item: ThemeColorItem, colIdx: number) => {
  373. Button() {
  374. Row() {
  375. Blank()
  376. .width(22)
  377. .height(22)
  378. .backgroundColor(item.name === '自定义' && this.isCustomThemeColor() ? this.themeColor :
  379. item.color)
  380. .border({ width: 2, color: $r('app.color.text_color') })
  381. .borderRadius(11)
  382. Text(item.name)
  383. .fontSize(15)
  384. .fontColor($r('app.color.text_color'))
  385. .margin({ left: 10 })
  386. // Text(item.isVip?'VIP':"Free")
  387. // .fontSize(10)
  388. // .fontColor(item.isVip?'#FFD700':"#000000") // 金色
  389. // .backgroundColor('#FFF9E3')
  390. // .borderRadius(6)
  391. // .padding({ left: 4, right: 4, top: 1, bottom: 1 })
  392. // .margin({ left: 4 })
  393. }
  394. .alignItems(VerticalAlign.Center)
  395. .justifyContent(FlexAlign.Start)
  396. .layoutWeight(1)
  397. }
  398. .height(40)
  399. .layoutWeight(1)
  400. .backgroundColor(
  401. (item.name === '自定义' && this.isCustomThemeColor()) || this.themeColor === item.color
  402. ? this.themeColor
  403. : $r('app.color.settings_background_main')
  404. )
  405. .borderRadius(20)
  406. .onClick(() => {
  407. if (item.isVip) {
  408. if (!Utility.isNoble()) {
  409. this.showVipDialog();
  410. return;
  411. }
  412. }
  413. if (item.name === '自定义') {
  414. this.showColorPicker = true
  415. } else {
  416. this.themeColor = item.color
  417. PreferencesUtil.putSync(SettingPage.THEME_COLOR_KEY, item.color)
  418. AppStorage.setOrCreate('themeColor', item.color)
  419. this.sendChangeEvent()
  420. }
  421. })
  422. .margin({ right: colIdx === 0 ? '4%' : 20, bottom: 10, left: 20 })
  423. })
  424. }
  425. .justifyContent(FlexAlign.Start)
  426. })
  427. }
  428. .margin({ left: 12, right: 12, top: 12 })
  429. }
  430. }
  431. .width('90%')
  432. .backgroundColor($r('app.color.settings_background_main'))
  433. .borderRadius(18)
  434. .border({ width: 1, color: '#F0F0F0' })
  435. .shadow({
  436. radius: 12,
  437. color: 0x11000000,
  438. offsetX: 0,
  439. offsetY: 2
  440. })
  441. .margin({
  442. left: 0,
  443. right: 0,
  444. bottom: 18
  445. })
  446. .padding({
  447. top: 18,
  448. bottom: 18,
  449. left: 0,
  450. right: 0
  451. })
  452. .bindPopup(this.showColorPicker, {
  453. builder: this.pickerBuilder(),
  454. placement: Placement.Top,
  455. mask: { color: '#33000000' },
  456. enableArrow: false, //是否显示箭头
  457. showInSubWindow: false,
  458. onStateChange: (e) => {
  459. if (!e.isVisible) {
  460. this.showColorPicker = false
  461. }
  462. }
  463. })
  464. // 主题色自定义弹窗
  465. }
  466. .padding({
  467. top: 8,
  468. bottom: 8,
  469. left: 15,
  470. right: 15
  471. })
  472. .width('100%')
  473. .backgroundColor(Color.Transparent)
  474. .borderRadius(24)
  475. }
  476. build() {
  477. Column() {
  478. Column() {
  479. Line().width('100%').height('100%')
  480. }
  481. .height(this.topRectHeight)
  482. .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
  483. .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
  484. // 自定义标题栏
  485. Stack() {
  486. // 居中标题
  487. Text('通用设置')
  488. .fontSize(20)
  489. .fontColor(Color.White)
  490. .align(Alignment.Center)
  491. // 左侧返回按钮
  492. Row() {
  493. Image($r('app.media.menu'))
  494. .width(29)
  495. .height(29)
  496. .margin({ left: 12, right: 8 })
  497. .onClick(() => {
  498. animateTo({ duration: 555 }, () => {
  499. // 动画闭包内控制Image组件的出现和消失
  500. this.isShowDrawer = !this.isShowDrawer
  501. this.offsetX = 0
  502. })
  503. })
  504. Blank().flexGrow(1)
  505. Blank().width(32)
  506. }
  507. .height(48)
  508. .width('100%')
  509. .alignItems(VerticalAlign.Center)
  510. }
  511. .height(48)
  512. .width('100%')
  513. .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
  514. Scroll() {
  515. Column() {
  516. // 主题设置分组
  517. Column() {
  518. Row() {
  519. Text('个性化')
  520. .margin({ left: 18, right: 20 })
  521. .fontSize(16)
  522. .fontColor(Color.Gray)
  523. .fontWeight(480)
  524. .layoutWeight(1)
  525. }
  526. .height(48)
  527. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  528. // 主题设置弹框入口
  529. Button({ type: ButtonType.Normal, stateEffect: true }) {
  530. Row() {
  531. Text('主题设置')
  532. .margin({ left: 18 })
  533. .fontSize(15)
  534. .fontColor(Color.Gray)
  535. .fontWeight(480)
  536. .layoutWeight(1)
  537. Image($r('app.media.arrow_right'))
  538. .width(22)
  539. .height(22)
  540. .margin({ right: 18 })
  541. }
  542. }
  543. .backgroundColor(Color.Transparent)
  544. .height(55)
  545. .clickEffect({ level: ClickEffectLevel.HEAVY })
  546. .onClick(() => {
  547. this.showColorPicker = false;
  548. this.isThemeSheet = true;
  549. this.customColor = this.themeColor;
  550. })
  551. .bindSheet($$this.isThemeSheet, this.themeSheetBuilder(), {
  552. height: '95%',
  553. dragBar: true,
  554. preferType: this.currentBreakpoint !== BreakpointTypeEnum.SM ? SheetType.CENTER : SheetType.BOTTOM,
  555. showClose: true,
  556. blurStyle: BlurStyle.Thin,
  557. backgroundColor: Color.Transparent,
  558. title: { title: '主题设置' },
  559. shouldDismiss: (SheetDismiss: SheetDismiss) => {
  560. SheetDismiss.dismiss();
  561. this.showColorPicker = false;
  562. }
  563. })
  564. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  565. Button({ type: ButtonType.Normal, stateEffect: true }) {
  566. Row() {
  567. Text('自定义背景')
  568. .margin({ left: 18 })
  569. .fontSize(15)
  570. .fontColor(Color.Gray)
  571. .fontWeight(480)
  572. .layoutWeight(1)
  573. .bindSheet($$this.isCustomizeBgSheet, this.customizeBgSheet(), {
  574. height: '95%',
  575. dragBar: true,
  576. preferType: this.currentBreakpoint !== BreakpointTypeEnum.SM ? SheetType.CENTER : SheetType.BOTTOM,
  577. showClose: true,
  578. blurStyle: BlurStyle.Thin,
  579. backgroundColor: Color.Transparent,
  580. title: { title: '自定义背景' }
  581. })
  582. Blank()
  583. // 右侧箭头
  584. Image($r('app.media.arrow_right'))
  585. .width(22)
  586. .height(22)
  587. .margin({ left: 20, right: 20 })
  588. .align(Alignment.Center)
  589. }
  590. }
  591. .clickEffect({ level: ClickEffectLevel.HEAVY })
  592. .height(55)
  593. .onClick(() => {
  594. if (!Utility.isNoble()) {
  595. this.showVipDialog();
  596. return;
  597. }
  598. this.isCustomizeBgSheet = !this.isCustomizeBgSheet;
  599. })
  600. .backgroundColor(Color.Transparent)
  601. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  602. // 滚动隐藏'
  603. Row() {
  604. Text('滚动隐藏')
  605. .margin({ left: 18 })
  606. .fontSize(15)
  607. .fontColor(Color.Gray)
  608. .fontWeight(480)
  609. .layoutWeight(1)
  610. Toggle({ type: ToggleType.Switch, isOn: this.isScrollHide })
  611. .selectedColor(this.themeColor)
  612. .switchPointColor(Color.White)
  613. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  614. .margin({ right: 18 })
  615. .onChange((checked: boolean) => {
  616. this.isScrollHide = checked;
  617. PreferencesUtil.put(SettingPage.IS_SCROLL_HIDE, this.isScrollHide)
  618. this.sendChangeEvent()
  619. })
  620. .width(50)
  621. .height(30);
  622. }
  623. .height(55)
  624. .clickEffect({ level: ClickEffectLevel.HEAVY })
  625. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  626. // 网格布局
  627. Row() {
  628. Text('网格列表模式')
  629. .margin({ left: 18 })
  630. .fontSize(15)
  631. .fontColor(Color.Gray)
  632. .fontWeight(480)
  633. .layoutWeight(1)
  634. Toggle({ type: ToggleType.Switch, isOn: this.isGridMusic })
  635. .selectedColor(this.themeColor)
  636. .switchPointColor(Color.White)
  637. .margin({ right: 18 })
  638. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  639. .onChange((checked: boolean) => {
  640. this.isGridMusic = checked;
  641. PreferencesUtil.put(SettingPage.IS_GRID_MUSIC, this.isGridMusic)
  642. this.sendChangeEvent()
  643. })
  644. .width(50)
  645. .height(30);
  646. }
  647. .height(55)
  648. .clickEffect({ level: ClickEffectLevel.HEAVY })
  649. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  650. // 网格封面大
  651. Row() {
  652. Text('列表封面大小')
  653. .margin({ left: 18 })
  654. .fontSize(15)
  655. .fontColor(Color.Gray)
  656. .fontWeight(480)
  657. .layoutWeight(1)
  658. Select([
  659. { value: CommonConstants.TWO_FINGER_TYPE[0] },
  660. { value: CommonConstants.TWO_FINGER_TYPE[1] },
  661. { value: CommonConstants.TWO_FINGER_TYPE[2] }])
  662. .font({ size: 15, weight: FontWeight.Medium })
  663. .fontColor(Color.Gray)
  664. .margin({ right: 18 })
  665. .selected(this.twoFingerType - 1)
  666. .value(CommonConstants.TWO_FINGER_TYPE[this.twoFingerType-1])
  667. .onSelect(async (_index: number, text?: string | undefined) => {
  668. _index++;
  669. this.twoFingerType = _index
  670. PreferencesUtil.put(SettingPage.TWO_FINGER_TYPE, this.twoFingerType)
  671. this.sendChangeEvent()
  672. })
  673. }
  674. .height(55)
  675. .clickEffect({ level: ClickEffectLevel.HEAVY })
  676. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  677. // 封面顶部
  678. Row() {
  679. Text('封面顶部')
  680. .margin({ left: 18 })
  681. .fontSize(15)
  682. .fontColor(Color.Gray)
  683. .fontWeight(480)
  684. .layoutWeight(1)
  685. Toggle({ type: ToggleType.Switch, isOn: this.isCoverTop })
  686. .selectedColor(this.themeColor)
  687. .switchPointColor(Color.White)
  688. .margin({ right: 18 })
  689. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  690. .onChange((checked: boolean) => {
  691. this.isCoverTop = checked;
  692. PreferencesUtil.put(SettingPage.IS_COVER_TOP, this.isCoverTop)
  693. this.sendChangeEvent()
  694. })
  695. .width(50)
  696. .height(30);
  697. }
  698. .height(55)
  699. .clickEffect({ level: ClickEffectLevel.HEAVY })
  700. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  701. // 封面顶部
  702. Row() {
  703. Text('顶部大封面')
  704. .margin({ left: 18 })
  705. .fontSize(15)
  706. .fontColor(Color.Gray)
  707. .fontWeight(480)
  708. .layoutWeight(1)
  709. Toggle({ type: ToggleType.Switch, isOn: this.isCoverTopBig })
  710. .selectedColor(this.themeColor)
  711. .switchPointColor(Color.White)
  712. .margin({ right: 18 })
  713. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  714. .onChange((checked: boolean) => {
  715. this.isCoverTopBig = checked;
  716. if(this.isCoverTopBig){
  717. ToastUtil.showToast('启动该开关部分设备封面太大导致和音乐控制重叠!')
  718. }
  719. PreferencesUtil.put(SettingPage.IS_COVER_TOP_BIG, this.isCoverTopBig)
  720. this.sendChangeEvent()
  721. })
  722. .width(50)
  723. .height(30);
  724. }
  725. .height(55)
  726. .clickEffect({ level: ClickEffectLevel.HEAVY })
  727. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  728. // 圆形播放按钮
  729. Row() {
  730. Text('圆形播放按钮')
  731. .margin({ left: 18 })
  732. .fontSize(15)
  733. .fontColor(Color.Gray)
  734. .fontWeight(480)
  735. .layoutWeight(1)
  736. Toggle({ type: ToggleType.Switch, isOn: this.isCircleBtn })
  737. .selectedColor(this.themeColor)
  738. .switchPointColor(Color.White)
  739. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  740. .margin({ right: 18 })
  741. .onChange((checked: boolean) => {
  742. this.isCircleBtn = checked;
  743. PreferencesUtil.put(SettingPage.IS_CIRCLE_BTN, this.isCircleBtn)
  744. this.sendChangeEvent()
  745. })
  746. .width(50)
  747. .height(30);
  748. }
  749. .height(55)
  750. .clickEffect({ level: ClickEffectLevel.HEAVY })
  751. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  752. }
  753. .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
  754. .animation({ duration: 500, curve: Curve.Ease, delay: 200 }))
  755. .backgroundColor($r('app.color.settings_background_main'))
  756. .borderRadius(20)
  757. .margin({
  758. left: 0,
  759. right: 0,
  760. top: 0,
  761. bottom: 10
  762. })
  763. .padding(0)
  764. // 音频设置分组
  765. Column() {
  766. Row() {
  767. Text('音频设置')
  768. .margin({ left: 18, right: 20 })
  769. .fontSize(16)
  770. .fontColor(Color.Gray)
  771. .fontWeight(480)
  772. .layoutWeight(1)
  773. }
  774. .height(48)
  775. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  776. // 启动时播放
  777. Row() {
  778. Text('启动时播放')
  779. .margin({ left: 18 })
  780. .fontSize(15)
  781. .fontColor(Color.Gray)
  782. .fontWeight(480)
  783. .layoutWeight(1)
  784. Toggle({ type: ToggleType.Switch, isOn: this.isStartAutoPlay })
  785. .selectedColor(this.themeColor)
  786. .switchPointColor(Color.White)
  787. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  788. .margin({ right: 18 })
  789. .onChange((checked: boolean) => {
  790. this.isStartAutoPlay = checked;
  791. PreferencesUtil.put(SettingPage.iS_START_AUTO_PLAY, this.isStartAutoPlay)
  792. })
  793. .width(50)
  794. .height(30);
  795. }
  796. .height(55)
  797. .clickEffect({ level: ClickEffectLevel.HEAVY })
  798. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  799. // 记住播放进度
  800. Row() {
  801. Text('记住最后一首进度')
  802. .margin({ left: 18 })
  803. .fontSize(15)
  804. .fontColor(Color.Gray)
  805. .fontWeight(480)
  806. .layoutWeight(1)
  807. Toggle({ type: ToggleType.Switch, isOn: this.isMemoryLastPlay })
  808. .selectedColor(this.themeColor)
  809. .switchPointColor(Color.White)
  810. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  811. .margin({ right: 18 })
  812. .onChange((checked: boolean) => {
  813. this.isMemoryLastPlay = checked;
  814. PreferencesUtil.put(SettingPage.iS_MEMORY_LAST_PLAY, this.isMemoryLastPlay)
  815. this.sendChangeEvent()
  816. })
  817. .width(50)
  818. .height(30);
  819. }
  820. .height(55)
  821. .clickEffect({ level: ClickEffectLevel.HEAVY })
  822. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  823. // 记忆播放
  824. Row() {
  825. Text('记忆播放')
  826. .margin({ left: 18 })
  827. .fontSize(15)
  828. .fontColor(Color.Gray)
  829. .fontWeight(480)
  830. .layoutWeight(1)
  831. Toggle({ type: ToggleType.Switch, isOn: this.isMusicMemoryPlay })
  832. .selectedColor(this.themeColor)
  833. .switchPointColor(Color.White)
  834. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  835. .margin({ right: 18 })
  836. .onChange((checked: boolean) => {
  837. this.isMusicMemoryPlay = checked;
  838. PreferencesUtil.put(SettingPage.iS_MUSIC_MEMORY_PLAY, this.isMusicMemoryPlay)
  839. this.sendChangeEvent()
  840. })
  841. .width(50)
  842. .height(30);
  843. }
  844. .height(55)
  845. .clickEffect({ level: ClickEffectLevel.HEAVY })
  846. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  847. // 默认排序模式
  848. Row() {
  849. Text('默认排序模式')
  850. .margin({ left: 18 })
  851. .fontSize(15)
  852. .fontColor(Color.Gray)
  853. .fontWeight(480)
  854. .layoutWeight(1)
  855. Select([
  856. { value: CommonConstants.SORT_ARRAY[0] },
  857. { value: CommonConstants.SORT_ARRAY[1] },
  858. { value: CommonConstants.SORT_ARRAY[2] },
  859. { value: CommonConstants.SORT_ARRAY[3] },
  860. { value: CommonConstants.SORT_ARRAY[4] },
  861. { value: CommonConstants.SORT_ARRAY[5] },
  862. { value: CommonConstants.SORT_ARRAY[6] },
  863. { value: CommonConstants.SORT_ARRAY[7] }])
  864. .font({ size: 15, weight: FontWeight.Medium })
  865. .fontColor(Color.Gray)
  866. .margin({ right: 18 })
  867. .selected(this.sortType)
  868. .value(CommonConstants.SORT_ARRAY[this.sortType])
  869. .onSelect(async (_index: number, text?: string | undefined) => {
  870. this.sortType = _index
  871. PreferencesUtil.put(SettingPage.SORT_TYPE, this.sortType)
  872. this.sendChangeEvent()
  873. })
  874. }
  875. .height(55)
  876. .clickEffect({ level: ClickEffectLevel.HEAVY })
  877. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  878. // 保存播放模式
  879. Row() {
  880. Text('保存播放模式')
  881. .margin({ left: 18 })
  882. .fontSize(15)
  883. .fontColor(Color.Gray)
  884. .fontWeight(480)
  885. .layoutWeight(1)
  886. Toggle({ type: ToggleType.Switch, isOn: this.isSavePlayMode })
  887. .selectedColor(this.themeColor)
  888. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  889. .switchPointColor(Color.White)
  890. .margin({ right: 18 })
  891. .onChange((checked: boolean) => {
  892. this.isSavePlayMode = checked;
  893. PreferencesUtil.put(SettingPage.iS_SAVE_PLAY_MODE, this.isSavePlayMode)
  894. })
  895. .width(50)
  896. .height(30);
  897. }
  898. .height(55)
  899. .clickEffect({ level: ClickEffectLevel.HEAVY })
  900. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  901. .visibility(Visibility.None)
  902. Row() {
  903. Text('与其他应用同时播放')
  904. .margin({ left: 18 })
  905. .fontSize(15)
  906. .fontColor(Color.Gray)
  907. .fontWeight(480)
  908. .layoutWeight(1)
  909. Toggle({ type: ToggleType.Switch, isOn: this.isSameTimePlay })
  910. .selectedColor(this.themeColor)
  911. .switchPointColor(Color.White)
  912. .margin({ right: 18 })
  913. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  914. .onChange((checked: boolean) => {
  915. this.isSameTimePlay = checked;
  916. PreferencesUtil.put(SettingPage.IS_SAMETIME_PLAY, this.isSameTimePlay)
  917. })
  918. .width(50)
  919. .height(30);
  920. }
  921. .height(55).clickEffect({ level: ClickEffectLevel.HEAVY })
  922. .visibility(Visibility.None)
  923. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  924. // 播放背景随音乐封面
  925. Row() {
  926. Text('播放背景随音乐封面')
  927. .margin({ left: 18 })
  928. .fontSize(15)
  929. .fontColor(Color.Gray)
  930. .fontWeight(480)
  931. .layoutWeight(1)
  932. Toggle({ type: ToggleType.Switch, isOn: this.isMusicBGCover })
  933. .selectedColor(this.themeColor)
  934. .switchPointColor(Color.White)
  935. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  936. .margin({ right: 18 })
  937. .onChange((checked: boolean) => {
  938. this.isMusicBGCover = checked;
  939. PreferencesUtil.put(SettingPage.iS_MUSIC_BG_COVER, this.isMusicBGCover)
  940. })
  941. .width(50)
  942. .height(30);
  943. }
  944. .height(55)
  945. .clickEffect({ level: ClickEffectLevel.HEAVY })
  946. }
  947. .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
  948. .animation({ duration: 500, curve: Curve.Ease, delay: 400 }))
  949. .backgroundColor($r('app.color.settings_background_main'))
  950. .borderRadius(20)
  951. .margin({
  952. left: 0,
  953. right: 0,
  954. top: 10,
  955. bottom: 10
  956. })
  957. .padding(0)
  958. // API设置分组
  959. this.apiBuilder()
  960. //设置教程
  961. this.jcBuilder()
  962. //显示与隐藏设置
  963. this.xsBuilder()
  964. //空白
  965. Column() {
  966. Blank()
  967. .height(88)
  968. }.height(88)
  969. }
  970. .margin({
  971. left: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 35 : 20,
  972. right: this.currentBreakpoint !== BreakpointTypeEnum.SM ? 35 : 20,
  973. top: 20,
  974. bottom: 20
  975. })
  976. .justifyContent(FlexAlign.Start)
  977. }
  978. .scrollBar(BarState.Auto)
  979. .height(px2vp(DisplayUtil.getHeight() - AppUtil.getStatusBarHeight() - AppUtil.getNavigationIndicatorHeight()))
  980. .width('100%')
  981. .margin({ bottom: 10 })
  982. .backgroundColor($r('app.color.settings_background'))
  983. }
  984. .height('100%')
  985. .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
  986. }
  987. @Builder
  988. xsBuilder() {
  989. // 显示和隐藏分组
  990. Column() {
  991. Row() {
  992. Text('显示隐藏')
  993. .margin({ left: 18, right: 20 })
  994. .fontSize(16)
  995. .fontColor(Color.Gray)
  996. .fontWeight(480)
  997. .layoutWeight(1)
  998. }
  999. .onClick(() => {
  1000. ToastUtil.showToast(this.appIdentifier)
  1001. PreferencesUtil.putSync('isShowWX',true)
  1002. })
  1003. .height(48)
  1004. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1005. Row() {
  1006. Text('显示分类导航')
  1007. .margin({ left: 18 })
  1008. .fontSize(15)
  1009. .fontColor(Color.Gray)
  1010. .fontWeight(480)
  1011. .layoutWeight(1)
  1012. Toggle({ type: ToggleType.Switch, isOn: this.isShowTitleBar })
  1013. .selectedColor(this.themeColor)
  1014. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1015. .switchPointColor(Color.White)
  1016. .margin({ right: 18 })
  1017. .onChange((checked: boolean) => {
  1018. this.isShowTitleBar = checked;
  1019. PreferencesUtil.put(SettingPage.IS_SHOW_TITLTBAR, this.isShowTitleBar)
  1020. this.sendChangeEvent()
  1021. })
  1022. .width(50)
  1023. .height(30);
  1024. }
  1025. .height(55)
  1026. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1027. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1028. Row() {
  1029. Text('显示播放全部')
  1030. .margin({ left: 18 })
  1031. .fontSize(15)
  1032. .fontColor(Color.Gray)
  1033. .fontWeight(480)
  1034. .layoutWeight(1)
  1035. Toggle({ type: ToggleType.Switch, isOn: this.isShowAllBar })
  1036. .selectedColor(this.themeColor)
  1037. .switchPointColor(Color.White)
  1038. .margin({ right: 18 })
  1039. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1040. .onChange((checked: boolean) => {
  1041. this.isShowAllBar = checked;
  1042. PreferencesUtil.put(SettingPage.IS_SHOW_ALLBAR, this.isShowAllBar)
  1043. this.sendChangeEvent()
  1044. })
  1045. .width(50)
  1046. .height(30);
  1047. }
  1048. .height(55)
  1049. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1050. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1051. // 显示私密音频
  1052. Row() {
  1053. Text('显示私密音频')
  1054. .margin({ left: 18 })
  1055. .fontSize(15)
  1056. .fontColor(Color.Gray)
  1057. .fontWeight(480)
  1058. .layoutWeight(1)
  1059. Toggle({ type: ToggleType.Switch, isOn: this.isShowSimi })
  1060. .selectedColor(this.themeColor)
  1061. .switchPointColor(Color.White)
  1062. .margin({ right: 18 })
  1063. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1064. .onChange((checked: boolean) => {
  1065. this.isShowSimi = checked;
  1066. PreferencesUtil.put(SettingPage.IS_SHOW_SIMI, this.isShowSimi)
  1067. this.sendChangeEvent()
  1068. })
  1069. .width(50)
  1070. .height(30);
  1071. }
  1072. .height(55)
  1073. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1074. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1075. // 播放页返回键
  1076. Row() {
  1077. Text('播放页单行歌词')
  1078. .margin({ left: 18 })
  1079. .fontSize(15)
  1080. .fontColor(Color.Gray)
  1081. .fontWeight(480)
  1082. .layoutWeight(1)
  1083. Toggle({ type: ToggleType.Switch, isOn: this.isShowSingleLineLyric })
  1084. .selectedColor(this.themeColor)
  1085. .switchPointColor(Color.White)
  1086. .margin({ right: 18 })
  1087. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1088. .onChange((checked: boolean) => {
  1089. this.isShowSingleLineLyric = checked;
  1090. PreferencesUtil.put(SettingPage.IS_SHOW_SLLYRIC, this.isShowSingleLineLyric)
  1091. this.sendChangeEvent()
  1092. })
  1093. .width(50)
  1094. .height(30);
  1095. }
  1096. .height(55)
  1097. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1098. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1099. // 播放页返回键
  1100. Row() {
  1101. Text('显示播放页返回键')
  1102. .margin({ left: 18 })
  1103. .fontSize(15)
  1104. .fontColor(Color.Gray)
  1105. .fontWeight(480)
  1106. .layoutWeight(1)
  1107. Toggle({ type: ToggleType.Switch, isOn: this.isShowPlayPageBack })
  1108. .selectedColor(this.themeColor)
  1109. .switchPointColor(Color.White)
  1110. .margin({ right: 18 })
  1111. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1112. .onChange((checked: boolean) => {
  1113. this.isShowPlayPageBack = checked;
  1114. PreferencesUtil.put(SettingPage.IS_SHOW_PLAYPAGE_BACK, this.isShowPlayPageBack)
  1115. this.sendChangeEvent()
  1116. })
  1117. .width(50)
  1118. .height(30);
  1119. }
  1120. .height(55)
  1121. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1122. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1123. // 显示我的收藏
  1124. Row() {
  1125. Text('显示我的收藏')
  1126. .margin({ left: 18 })
  1127. .fontSize(15)
  1128. .fontColor(Color.Gray)
  1129. .fontWeight(480)
  1130. .layoutWeight(1)
  1131. Toggle({ type: ToggleType.Switch, isOn: this.isShowFAV })
  1132. .selectedColor(this.themeColor)
  1133. .switchPointColor(Color.White)
  1134. .margin({ right: 18 })
  1135. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1136. .onChange((checked: boolean) => {
  1137. this.isShowFAV = checked;
  1138. PreferencesUtil.put(SettingPage.IS_SHOW_FAV, this.isShowFAV)
  1139. this.sendChangeEvent()
  1140. })
  1141. .width(50)
  1142. .height(30);
  1143. }
  1144. .height(55)
  1145. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1146. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1147. // 显示最近播放
  1148. Row() {
  1149. Text('显示最近播放')
  1150. .margin({ left: 18 })
  1151. .fontSize(15)
  1152. .fontColor(Color.Gray)
  1153. .fontWeight(480)
  1154. .layoutWeight(1)
  1155. Toggle({ type: ToggleType.Switch, isOn: this.isShowHistory })
  1156. .selectedColor(this.themeColor)
  1157. .switchPointColor(Color.White)
  1158. .margin({ right: 18 })
  1159. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1160. .onChange((checked: boolean) => {
  1161. this.isShowHistory = checked;
  1162. PreferencesUtil.put(SettingPage.IS_SHOW_HISTORY, this.isShowHistory)
  1163. this.sendChangeEvent()
  1164. })
  1165. .width(50)
  1166. .height(30);
  1167. }
  1168. .height(55)
  1169. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1170. }
  1171. .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
  1172. .animation({ duration: 500, curve: Curve.Ease, delay: 600 }))
  1173. .backgroundColor($r('app.color.settings_background_main'))
  1174. .borderRadius(20)
  1175. .margin({
  1176. left: 0,
  1177. right: 0,
  1178. top: 10,
  1179. bottom: 20
  1180. })
  1181. .padding(0)
  1182. }
  1183. @Builder
  1184. jcBuilder() {
  1185. //设置教程
  1186. Button({ type: ButtonType.Capsule, stateEffect: true }) {
  1187. Column() {
  1188. Row() {
  1189. Text('设置教程:')
  1190. .margin({ left: 18 })
  1191. .fontSize(15)
  1192. .fontColor(Color.Gray)
  1193. .fontWeight(480)
  1194. Text('点击进Q群讨论')
  1195. .margin({ right: 10 })
  1196. .fontSize(15)
  1197. .fontColor(Color.Gray)
  1198. .layoutWeight(1)
  1199. Blank()
  1200. // 右侧箭头
  1201. Image($r('app.media.arrow_right'))
  1202. .width(22)
  1203. .height(22)
  1204. .margin({ left: 20, right: 20 })
  1205. .align(Alignment.Center)
  1206. }
  1207. .height(55)
  1208. }
  1209. }
  1210. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1211. .onClick(() => {
  1212. const qqUrl =
  1213. `mqqapi://card/show_pslcard?src_type=internal&version=1&uin=${CommonConstants.QQ_GROUP}&card_type=group&source=external`
  1214. let context = this.getUIContext().getHostContext() as common.UIAbilityContext
  1215. context.openLink(qqUrl, {})
  1216. })
  1217. .backgroundColor($r('app.color.settings_background_main'))
  1218. .borderRadius(15)
  1219. .margin({ top: 0, bottom: 20 })
  1220. .padding(0)
  1221. }
  1222. @Builder
  1223. apiBuilder() {
  1224. // API设置分组
  1225. Column() {
  1226. Row() {
  1227. Text('API设置')
  1228. .margin({ left: 18, right: 20 })
  1229. .fontSize(16)
  1230. .fontColor(Color.Gray)
  1231. .fontWeight(480)
  1232. .layoutWeight(1)
  1233. }
  1234. .height(48)
  1235. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1236. // 歌词API
  1237. Button({ type: ButtonType.Normal, stateEffect: true }) {
  1238. Row() {
  1239. Text('歌词:')
  1240. .margin({ left: 18, right: 6 })
  1241. .fontSize(15)
  1242. .fontColor(Color.Gray)
  1243. Text(this.lyricApiUrl)
  1244. .margin({ right: 10 })
  1245. .fontSize(15)
  1246. .fontColor(Color.Gray)
  1247. .layoutWeight(1)
  1248. Image(this.isDarkMode ? $r('app.media.rename2') : $r('app.media.rename'))
  1249. .width(20)
  1250. .height(20)
  1251. .margin({ right: 18 })
  1252. }
  1253. }
  1254. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1255. .backgroundColor(Color.Transparent)
  1256. .onClick(() => {
  1257. this.apiDialogType = 'lyric'
  1258. this.tempApiUrl = this.lyricApiUrl
  1259. this.apiDialogController.open()
  1260. })
  1261. .height(55)
  1262. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  1263. // 封面API
  1264. Button({ type: ButtonType.Normal, stateEffect: true }) {
  1265. Row() {
  1266. Text('封面:')
  1267. .margin({ left: 18, right: 6 })
  1268. .fontSize(15)
  1269. .fontColor(Color.Gray)
  1270. Text(this.coverApiUrl)
  1271. .margin({ right: 10 })
  1272. .fontSize(15)
  1273. .fontColor(Color.Gray)
  1274. .layoutWeight(1)
  1275. Image(this.isDarkMode ? $r('app.media.rename2') : $r('app.media.rename'))
  1276. .width(20)
  1277. .height(20)
  1278. .margin({ right: 18 })
  1279. }
  1280. }
  1281. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1282. .backgroundColor(Color.Transparent)
  1283. .onClick(() => {
  1284. this.apiDialogType = 'cover'
  1285. this.tempApiUrl = this.coverApiUrl
  1286. this.apiDialogController.open()
  1287. })
  1288. .height(55)
  1289. }
  1290. .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
  1291. .animation({ duration: 500, curve: Curve.Ease, delay: 600 }))
  1292. .backgroundColor($r('app.color.settings_background_main'))
  1293. .borderRadius(20)
  1294. .margin({
  1295. left: 0,
  1296. right: 0,
  1297. top: 10,
  1298. bottom: 20
  1299. })
  1300. .padding(0)
  1301. }
  1302. //发送广播通知更新UI
  1303. sendChangeEvent() {
  1304. const eventData: emitter.EventData = {};
  1305. emitter.emit({ eventId: 333 }, eventData); // 发送广播通知更新doSwipBack
  1306. }
  1307. goSelectImage() {
  1308. let selectUris: Array<string> = [];
  1309. let photoPicker = new photoAccessHelper.PhotoViewPicker();
  1310. let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
  1311. photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
  1312. photoSelectOptions.maxSelectNumber = 1; // 选择媒体文件的最大数目
  1313. photoPicker.select(photoSelectOptions).then(async (photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
  1314. //用一个全局变量存储返回的uri
  1315. selectUris = photoSelectResult.photoUris;
  1316. console.info('photoViewPicker.select to file succeed and uris are:' + selectUris);
  1317. //使用fs.openSync接口,通过uri打开这个文件得到fd
  1318. let file = fileIo.openSync(selectUris[0], fileIo.OpenMode.READ_ONLY);
  1319. console.info('file fd: ' + file.fd);
  1320. const timestamp: number = Math.floor(Date.now() / 1000);
  1321. let name = timestamp + "_homebg"
  1322. let imagePath = this.context.filesDir + FileUtil.separator + name
  1323. imagePath = fileUri.getUriFromPath(imagePath)
  1324. let file2 = fileIo.openSync(imagePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE)
  1325. fileIo.copyFileSync(file.fd, file2.fd)
  1326. fileIo.closeSync(file);
  1327. fileIo.closeSync(file2);
  1328. this.customizeBgPath = imagePath
  1329. PreferencesUtil.put(SettingPage.IS_CUSTOMIZE_BG_PATH, this.customizeBgPath)
  1330. this.sendChangeEvent()
  1331. }).catch((err: BusinessError) => {
  1332. console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
  1333. })
  1334. }
  1335. @Builder
  1336. customizeBgSheet() {
  1337. Scroll() {
  1338. Column() {
  1339. this.CustomizeBg()
  1340. }
  1341. }
  1342. .width('100%')
  1343. .height('100%')
  1344. }
  1345. @Builder
  1346. CustomizeBg() {
  1347. Column() {
  1348. Image(this.customizeBgPath)
  1349. .height('42%')
  1350. .alt($r('app.color.white'))
  1351. .objectFit(ImageFit.Contain)
  1352. .borderRadius(20)
  1353. .clip(true)
  1354. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1355. .blur(this.blurValue)
  1356. .brightness(this.bgBrightness + 0.8)
  1357. .margin({ left: 30, right: 30, bottom: 20 })
  1358. Row() {
  1359. Row() {
  1360. Button('选择图片')
  1361. .fontColor(Color.White)
  1362. .fontSize(12)
  1363. .height(48)
  1364. .width(100)
  1365. .clickEffect({ level: ClickEffectLevel.HEAVY })
  1366. .backgroundColor(this.themeColor)
  1367. .stateEffect(true)
  1368. .onClick(async () => {
  1369. this.goSelectImage()
  1370. })
  1371. }
  1372. .height('100%')
  1373. .justifyContent(FlexAlign.Center)
  1374. .layoutWeight(1)
  1375. }
  1376. .width('100%')
  1377. .height(58)
  1378. .margin({ bottom: 20 })
  1379. Column() {
  1380. Row() {
  1381. Text('自定义背景:')
  1382. .margin({ left: 18 })
  1383. .fontSize(15)
  1384. .fontColor($r('app.color.text_color'))
  1385. .fontWeight(480)
  1386. .layoutWeight(1)
  1387. Toggle({ type: ToggleType.Switch, isOn: this.isCustomizeBg })
  1388. .selectedColor(this.themeColor)
  1389. .switchPointColor(Color.White)
  1390. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.5})
  1391. .margin({ right: 18 })
  1392. .onChange((checked: boolean) => {
  1393. this.isCustomizeBg = checked;
  1394. PreferencesUtil.put(SettingPage.IS_CUSTOMIZE_BG, this.isCustomizeBg)
  1395. this.sendChangeEvent()
  1396. })
  1397. .width(50)
  1398. .height(30);
  1399. }
  1400. .height(55)
  1401. }
  1402. .backgroundColor($r('app.color.settings_background_main'))
  1403. .borderRadius(15)
  1404. .margin({
  1405. left: 30,
  1406. right: 30,
  1407. top: 0,
  1408. bottom: 20
  1409. })
  1410. .padding(0)
  1411. Column() {
  1412. Row() {
  1413. Text('背景模糊:')
  1414. .margin({ left: 18 })
  1415. .fontSize(15)
  1416. .fontColor($r('app.color.text_color'))
  1417. .fontWeight(480)
  1418. Slider({
  1419. value: this.blurValue,
  1420. min: 0,
  1421. max: 100,
  1422. step: 1,
  1423. style: SliderStyle.OutSet
  1424. })
  1425. .blockColor(this.themeColor)
  1426. .trackColor($r('app.color.speed_text_color'))
  1427. .selectedColor($r('app.color.index_background'))
  1428. .trackThickness(8)
  1429. .onChange((value: number) => {
  1430. this.blurValue = value;
  1431. PreferencesUtil.put(SettingPage.CUSTOMIZE_BG_BLUR, this.blurValue)
  1432. this.sendChangeEvent()
  1433. })
  1434. .layoutWeight(1)
  1435. }
  1436. .height(55)
  1437. }
  1438. .backgroundColor($r('app.color.settings_background_main'))
  1439. .borderRadius(15)
  1440. .margin({
  1441. left: 30,
  1442. right: 30,
  1443. top: 0,
  1444. bottom: 20
  1445. })
  1446. .padding(0)
  1447. Column() {
  1448. Row() {
  1449. Text('背景亮度:')
  1450. .margin({ left: 18 })
  1451. .fontSize(15)
  1452. .fontColor($r('app.color.text_color'))
  1453. .fontWeight(480)
  1454. Slider({
  1455. value: this.bgBrightness,
  1456. min: -0.4,
  1457. max: 0.4,
  1458. step: 0.1,
  1459. style: SliderStyle.OutSet
  1460. })
  1461. .blockColor(this.themeColor)
  1462. .trackColor($r('app.color.speed_text_color'))
  1463. .selectedColor($r('app.color.index_background'))
  1464. .trackThickness(8)
  1465. .onChange((value: number) => {
  1466. this.bgBrightness = value;
  1467. PreferencesUtil.put(SettingPage.BG_BRIGHTNESS, this.bgBrightness)
  1468. this.sendChangeEvent()
  1469. })
  1470. .layoutWeight(1)
  1471. }
  1472. .height(55)
  1473. }
  1474. .backgroundColor($r('app.color.settings_background_main'))
  1475. .borderRadius(15)
  1476. .margin({
  1477. left: 30,
  1478. right: 30,
  1479. top: 0,
  1480. bottom: 20
  1481. })
  1482. .padding(0)
  1483. }
  1484. .margin({ bottom: 30 })
  1485. }
  1486. // 判断当前主题色是否为自定义色
  1487. isCustomThemeColor(): boolean {
  1488. for (let i = 0; i < SettingPage.THEME_COLOR_LIST.length - 1; i++) {
  1489. if (SettingPage.THEME_COLOR_LIST[i].color === this.themeColor) {
  1490. return false;
  1491. }
  1492. }
  1493. return true;
  1494. }
  1495. // 会员功能弹窗
  1496. showVipDialog() {
  1497. DialogHelper.showCustomContentDialog({
  1498. dialogId: 'vip',
  1499. title: "友情提示",
  1500. autoCancel: false,
  1501. backCancel: true,
  1502. contentBuilder: () => {
  1503. this.customVipBuilder("该功能需开通会员,非常感谢您的支持!")
  1504. },
  1505. buttons: [],
  1506. })
  1507. }
  1508. @Builder
  1509. customVipBuilder(content: string) {
  1510. Column() {
  1511. Text(content)
  1512. .fontColor(Color.Gray)
  1513. .fontSize(16)
  1514. .alignSelf(ItemAlign.Start)
  1515. .margin({ bottom: 15 })
  1516. Row() {
  1517. Button('取消')
  1518. .fontColor(Color.White)
  1519. .backgroundColor(this.themeColor)
  1520. .height(50)
  1521. .layoutWeight(1)
  1522. .stateEffect(true)
  1523. .margin({ right: 6 })
  1524. .onClick(() => {
  1525. DialogHelper.closeDialog('vip');
  1526. })
  1527. Button('开通')
  1528. .fontColor(Color.White)
  1529. .layoutWeight(1)
  1530. .height(50)
  1531. .backgroundColor(this.themeColor)
  1532. .stateEffect(true)
  1533. .margin({ left: 6 })
  1534. .onClick(() => {
  1535. this.isThemeSheet = false;
  1536. DialogHelper.closeDialog('vip');
  1537. this.mType = 1//跳转到用户中心
  1538. // router.pushUrl({
  1539. // url: 'pages/UserCenter'
  1540. // }, router.RouterMode.Single);
  1541. })
  1542. }
  1543. }
  1544. .width("100%")
  1545. .padding(10)
  1546. }
  1547. @State appIdentifier:string=''
  1548. geIDD() {
  1549. // 获取应用签名等信息示例代码
  1550. let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION |
  1551. bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO;
  1552. try {
  1553. bundleManager.getBundleInfoForSelf(bundleFlags).then((data) => {
  1554. hilog.info(0x0000, 'testTag11', 'getBundleInfoForSelf successfully. Data: %{public}s', JSON.stringify(data));
  1555. let inde = JSON.stringify(data)
  1556. this.appIdentifier = inde.substring(inde.indexOf('appIdentifier'),inde.indexOf('"certificate'))
  1557. hilog.info(0x0000, 'testTag11', 'appIdentifier Data: %{public}s', this.appIdentifier);
  1558. }).catch((err: BusinessError) => {
  1559. hilog.error(0x0000, 'testTag11', 'getBundleInfoForSelf failed. Cause: %{public}s', err.message);
  1560. });
  1561. } catch (err) {
  1562. let message = (err as BusinessError).message;
  1563. hilog.error(0x0000, 'testTag33', 'getBundleInfoForSelf failed: %{public}s', message);
  1564. }
  1565. }
  1566. }
  1567. // 主题色类型声明
  1568. export interface ThemeColorItem {
  1569. name: string;
  1570. color: string;
  1571. isVip: boolean;
  1572. }
  1573. // 工具函数:将一维数组分成每行2个的二维数组
  1574. function chunkArray<T>(arr: Array<T>, size: number): Array<Array<T>> {
  1575. const result: Array<Array<T>> = [];
  1576. for (let i = 0; i < arr.length; i += size) {
  1577. const row: Array<T> = [];
  1578. for (let j = 0; j < size; j++) {
  1579. if (i + j < arr.length) {
  1580. row.push(arr[i + j]);
  1581. }
  1582. }
  1583. result.push(row);
  1584. }
  1585. return result;
  1586. }