SettingPage.ets 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. import TitleBar from '../view/TitleBar'
  2. import { promptAction, router } from '@kit.ArkUI'
  3. import { CommonConstants } from '../common/constants/CommonConstants'
  4. import { AppUtil, PreferencesUtil } 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. @Preview
  9. @Entry
  10. @Component
  11. export struct SettingPage {
  12. @State showApiDialog: boolean = false
  13. @State tempApiUrl: string = ''
  14. @State lyricApiUrl: string = PreferencesUtil.getStringSync('LRC_API', '')
  15. @State isBgPlayOpen: boolean = true //是否启用后台播放
  16. @State isAutoRatate: boolean = true //是否启用自动横竖屏
  17. @State isMemoryPlay: boolean = true //是否启用记忆播放
  18. @State isMediacodec: boolean = false //是否启用硬件解码
  19. @State isMusicMemoryPlay: boolean = false //是否启用记忆播放
  20. @State isMusicBGCover: boolean = true //播放背景随封面
  21. @State sortType: number = 4 //默认排序方式
  22. @State showCoverApiDialog: boolean = false
  23. @State tempCoverApiUrl: string = ''
  24. @State coverApiUrl: string = PreferencesUtil.getStringSync('COVER_API', '')
  25. @State apiDialogType: 'lyric' | 'cover' = 'lyric'
  26. static readonly SORT_TYPE: string = 'musicSortType';
  27. @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  28. @StorageLink('isDarkMode') isDarkMode: boolean = false // 是否启用深色模式
  29. static readonly IS_BGPLAY_OPEN: string = 'isBgPlayOpen';
  30. static readonly IS_AUTO_RATATE: string = 'isAutoRatate';
  31. static readonly iS_MEMORY_PLAY: string = 'isMemoryPlay';
  32. static readonly IS_MIDIACODEC_OPEN: string = 'isMediacodec';
  33. static readonly iS_MUSIC_MEMORY_PLAY: string = 'isMusicMemoryPlay';
  34. static readonly iS_MUSIC_BG_COVER: string = 'isMusicBGCover';
  35. static readonly iS_SAVE_PLAY_MODE: string = 'isSavePlayMode';
  36. static readonly IS_COVER_RECTANGLE: string = 'isCoverRectangle'; //封面圆形或者方形
  37. static readonly IS_DARK_MODE: string = 'isDarkMode'; // 深色模式设置
  38. @State titleBarModel: TitleBar.Model = new TitleBar.Model()
  39. .setTitleTextStyle(FontStyle.Normal)
  40. .setTitleBarStyle(TitleBar.BarStyle.TRANSPARENT)
  41. .setLeftIcon($r('app.media.left_back_white'))
  42. .setTitleName('通用设置')
  43. .setTitleFontColor(Color.White)
  44. .setTitleBarBackground($r('app.color.title_bar_bg'))
  45. .setLeftTitleBackground($r('app.color.title_bar_bg'))
  46. .setTitleBarBottomLineColor($r('app.color.title_bar_bg'))
  47. .setOnLeftClickListener(() => {
  48. router.back()
  49. })
  50. @State verName: string = ''
  51. apiDialogController: CustomDialogController = new CustomDialogController({
  52. builder: CustomContentDialog({
  53. primaryTitle: this.apiDialogType === 'lyric' ? '修改歌词API地址' : '修改封面API地址',
  54. contentBuilder: () => {
  55. this.buildApiDialogContent();
  56. },
  57. buttons: [
  58. {
  59. value: '取消',
  60. action: () => {
  61. this.apiDialogController.close();
  62. }
  63. },
  64. {
  65. value: '保存',
  66. action: () => {
  67. if (this.apiDialogType === 'lyric') {
  68. this.lyricApiUrl = this.tempApiUrl
  69. PreferencesUtil.put('LRC_API', this.lyricApiUrl)
  70. this.getUIContext().getPromptAction().showToast({
  71. message: '保存成功,当前LRC_API:' + this.lyricApiUrl,
  72. duration: 2000,
  73. showMode: promptAction.ToastShowMode.TOP_MOST,
  74. bottom: 85
  75. })
  76. } else {
  77. this.coverApiUrl = this.tempApiUrl
  78. PreferencesUtil.put('COVER_API', this.coverApiUrl)
  79. this.getUIContext().getPromptAction().showToast({
  80. message: '保存成功,当前COVER_API:' + this.coverApiUrl,
  81. duration: 2000,
  82. showMode: promptAction.ToastShowMode.TOP_MOST,
  83. bottom: 85
  84. })
  85. }
  86. this.apiDialogController.close();
  87. }
  88. }
  89. ]
  90. }),
  91. autoCancel: true,
  92. alignment: DialogAlignment.Center
  93. })
  94. @Builder
  95. buildApiDialogContent() {
  96. Column() {
  97. TextInput({ text: this.tempApiUrl, placeholder: this.apiDialogType === 'lyric' ? '请输入歌词API地址' : '请输入封面API地址' })
  98. .onChange((val: string) => {
  99. this.tempApiUrl = val
  100. })
  101. .width('90%')
  102. .height(60)
  103. }
  104. .width('100%')
  105. }
  106. // 组件生命周期
  107. aboutToAppear() {
  108. this.isBgPlayOpen = PreferencesUtil.getBooleanSync(SettingPage.IS_BGPLAY_OPEN, true)
  109. this.isAutoRatate = PreferencesUtil.getBooleanSync(SettingPage.IS_AUTO_RATATE, true)
  110. this.isMemoryPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MEMORY_PLAY, true)
  111. this.isMediacodec = PreferencesUtil.getBooleanSync(SettingPage.IS_MIDIACODEC_OPEN, false)
  112. this.isMusicMemoryPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_MEMORY_PLAY, false)
  113. this.isMusicBGCover = PreferencesUtil.getBooleanSync(SettingPage.iS_MUSIC_BG_COVER, true)
  114. // 从持久化存储中读取深色模式设置
  115. const savedDarkMode = PreferencesUtil.getBooleanSync(SettingPage.IS_DARK_MODE, false);
  116. this.isDarkMode = savedDarkMode;
  117. this.currentMode = savedDarkMode ? ConfigurationConstant.ColorMode.COLOR_MODE_DARK : ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  118. AppStorage.setOrCreate('currentColorMode', this.currentMode);
  119. AppStorage.setOrCreate('isDarkMode', this.isDarkMode);
  120. }
  121. // 监听颜色模式变化
  122. onColorModeChange(): void {
  123. this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
  124. AppStorage.setOrCreate('isDarkMode', this.isDarkMode);
  125. // 保存深色模式设置到持久化存储
  126. PreferencesUtil.putSync(SettingPage.IS_DARK_MODE, this.isDarkMode);
  127. }
  128. // 切换深色模式
  129. async toggleDarkMode(checked: boolean) {
  130. try {
  131. const newMode = checked ? ConfigurationConstant.ColorMode.COLOR_MODE_DARK : ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  132. // 更新 AppStorage 中的颜色模式
  133. AppStorage.setOrCreate('currentColorMode', newMode);
  134. AppStorage.setOrCreate('isDarkMode', checked);
  135. // 保存深色模式设置到持久化存储
  136. PreferencesUtil.putSync(SettingPage.IS_DARK_MODE, checked);
  137. // 通知系统更新颜色模式
  138. const context = getContext(this) as common.UIAbilityContext;
  139. context.getApplicationContext().setColorMode(newMode);
  140. // 显示提示
  141. this.getUIContext().getPromptAction().showToast({
  142. message: checked ? '已切换到深色模式' : '已切换到浅色模式',
  143. duration: 2000,
  144. showMode: promptAction.ToastShowMode.TOP_MOST,
  145. bottom: 85
  146. });
  147. } catch (err) {
  148. console.error('Failed to update color mode:', err);
  149. }
  150. }
  151. // 组件生命周期
  152. aboutToDisappear() {
  153. // 无需处理apiDialogController
  154. }
  155. build() {
  156. Column() {
  157. TitleBar({ model: $titleBarModel })
  158. Scroll() {
  159. Column() {
  160. // 主题设置
  161. Row() {
  162. Text('主题设置')
  163. .margin({ left: 38, right: 20 })
  164. .fontSize(16)
  165. .fontColor(Color.Gray)
  166. .fontWeight(480)
  167. Blank()
  168. }
  169. .width('100%')
  170. .height(55)
  171. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  172. // 深色模式开关
  173. Row() {
  174. Image($r('app.media.kp_music_nor'))
  175. .width(22)
  176. .height(22)
  177. .alignSelf(ItemAlign.Center)
  178. .margin({ left: 28 })
  179. Text('深色模式')
  180. .margin({ left: 10, right: 20 })
  181. .fontSize(15)
  182. .fontColor(Color.Gray)
  183. .fontWeight(480)
  184. Blank()
  185. Toggle({ type: ToggleType.Switch, isOn: this.isDarkMode })
  186. .selectedColor($r('app.color.title_bar_bg'))
  187. .switchPointColor(Color.White)
  188. .margin({ right: 28 })
  189. .onChange((checked: boolean) => {
  190. this.toggleDarkMode(checked);
  191. })
  192. .width(50)
  193. .height(30);
  194. }
  195. .width('100%')
  196. .height(55)
  197. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  198. //音频设置
  199. Row() {
  200. Text('音频设置')
  201. .margin({ left: 38, right: 20 })
  202. .fontSize(16)
  203. .fontColor(Color.Gray)
  204. .fontWeight(480)
  205. Blank()
  206. }
  207. .width('100%')
  208. .height(55)
  209. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  210. Row() {
  211. Image($r('app.media.kp_music_nor'))
  212. .width(22)
  213. .height(22)
  214. .alignSelf(ItemAlign.Center)
  215. .margin({ left: 28 })
  216. Text('记忆播放')
  217. .margin({ left: 10, right: 20 })
  218. .fontSize(15)
  219. .fontColor(Color.Gray)
  220. .fontWeight(480)
  221. Blank()
  222. Toggle({ type: ToggleType.Switch, isOn: this.isMusicMemoryPlay })
  223. .selectedColor($r('app.color.title_bar_bg'))// 设置开关打开时的背景颜色为蓝色
  224. .switchPointColor(Color.White)// 设置开关关闭时的滑块颜色为白色
  225. .margin({ right: 28 })
  226. .onChange((checked: boolean) => { // 选择开关状态变化时触发事件
  227. this.isMusicMemoryPlay = checked;
  228. PreferencesUtil.put(SettingPage.iS_MUSIC_MEMORY_PLAY, this.isMusicMemoryPlay)
  229. })
  230. .width(50)
  231. .height(30);
  232. }
  233. .width('100%')
  234. .height(55)
  235. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  236. Row() {
  237. Image($r('app.media.kp_music_nor'))
  238. .width(22)
  239. .height(22)
  240. .alignSelf(ItemAlign.Center)
  241. .margin({ left: 28 })
  242. Text('播放背景随音乐封面')
  243. .margin({ left: 10, right: 20 })
  244. .fontSize(15)
  245. .fontColor(Color.Gray)
  246. .fontWeight(480)
  247. Blank()
  248. Toggle({ type: ToggleType.Switch, isOn: this.isMusicBGCover })
  249. .selectedColor($r('app.color.title_bar_bg'))// 设置开关打开时的背景颜色为蓝色
  250. .switchPointColor(Color.White)// 设置开关关闭时的滑块颜色为白色
  251. .margin({ right: 28 })
  252. .onChange((checked: boolean) => { // 选择开关状态变化时触发事件
  253. this.isMusicBGCover = checked;
  254. PreferencesUtil.put(SettingPage.iS_MUSIC_BG_COVER, this.isMusicBGCover)
  255. })
  256. .width(50)
  257. .height(30);
  258. }
  259. .width('100%')
  260. .height(55)
  261. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  262. // API设置(合并标题)
  263. Row() {
  264. Text('API设置')
  265. .margin({ left: 38, right: 20 })
  266. .fontSize(16)
  267. .fontColor(Color.Gray)
  268. .fontWeight(480)
  269. }
  270. .width('100%')
  271. .height(55)
  272. Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  273. // 歌词API地址展示
  274. Row() {
  275. Text('歌词:')
  276. .margin({ left: 38, right: 6 })
  277. .fontSize(15)
  278. .fontColor(Color.Gray)
  279. Text(this.lyricApiUrl)
  280. .margin({ right: 10 })
  281. .fontSize(15)
  282. .fontColor(Color.Gray)
  283. .layoutWeight(1)
  284. // 编辑图标按钮
  285. Image($r('app.media.edit'))
  286. .width(28)
  287. .height(28)
  288. .margin({ right: 18 })
  289. .onClick(() => {
  290. this.apiDialogType = 'lyric'
  291. this.tempApiUrl = this.lyricApiUrl
  292. this.apiDialogController.open()
  293. })
  294. Blank()
  295. }
  296. .width('100%')
  297. .margin({ top: 8, bottom: 12 })
  298. // 封面API地址展示
  299. Row() {
  300. Text('封面:')
  301. .margin({ left: 38, right: 6 })
  302. .fontSize(15)
  303. .fontColor(Color.Gray)
  304. Text(this.coverApiUrl)
  305. .margin({ right: 10 })
  306. .fontSize(15)
  307. .fontColor(Color.Gray)
  308. .layoutWeight(1)
  309. // 编辑图标按钮
  310. Image($r('app.media.edit'))
  311. .width(28)
  312. .height(28)
  313. .margin({ right: 18 })
  314. .onClick(() => {
  315. this.apiDialogType = 'cover'
  316. this.tempApiUrl = this.coverApiUrl
  317. this.apiDialogController.open()
  318. })
  319. Blank()
  320. }
  321. .width('100%')
  322. .margin({ top: 8, bottom: 12 })
  323. }
  324. .backgroundColor(this.isDarkMode ? '#1E1E1E' : Color.White)
  325. .margin({
  326. left: 25,
  327. right: 25,
  328. top: 20,
  329. bottom: 50
  330. })
  331. .layoutWeight(1)
  332. .justifyContent(FlexAlign.Start) // Align items to the start
  333. .borderRadius(30)
  334. }
  335. .scrollBar(BarState.Auto)
  336. .height('100%')
  337. .width('100%')
  338. .margin({bottom:18})
  339. }
  340. .backgroundColor(this.isDarkMode ? '#121212' : $r('app.color.index_background'))
  341. .height('100%')
  342. .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
  343. }
  344. }