SettingPage.ets 55 KB

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