woofGeneralManage.ets 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. import linysSymbol from '../../components/texts/linysSymbol';
  2. import linysText from '../../components/texts/linysText';
  3. import linysTextTitle from '../../components/texts/linysTextTitle';
  4. import { animation_default, capsule_bar_height, click_effect_default } from '../../hosts/bunch_of_defaults';
  5. import { bunch_of_settings } from '../../hosts/bunch_of_settings';
  6. import { webview } from '@kit.ArkWeb';
  7. import linysShowButton from '../../components/buttons/linysShowButton';
  8. import linysCapsuleButton from '../../components/buttons/linysCapsuleButton';
  9. import { match_domain } from '../../utils/url_tools';
  10. import woofControlFrame from '../woofControlFrame';
  11. import linysTimeoutButton from '../../components/buttons/linysTimeoutButton';
  12. import linysSwitchWithText from '../../components/toggles/linysSwitchWithText';
  13. @CustomDialog
  14. struct woofGeneralManage {
  15. controller: CustomDialogController;
  16. // Environment and Hosts
  17. @StorageLink('bunch_of_settings') bunch_of_settings: bunch_of_settings = new bunch_of_settings(true);
  18. @StorageLink('tablet_mode') tablet_mode: boolean = false;
  19. @StorageLink('current_url') current_url: string = "= ̄ω ̄=";
  20. @State add_site_edit: string = "";
  21. @State showing_add_panel: boolean = false;
  22. // Generals
  23. @Link general_switch: boolean;
  24. @Link general_sites_list: string[];
  25. @Link general_on_all_sites_switch: boolean;
  26. @State general_descriptions: ResourceStr[] = [
  27. $r('app.string.Settings_js_desc_1'),
  28. $r('app.string.Settings_js_desc_2'),
  29. $r('app.string.Settings_js_desc_3')
  30. ];
  31. @State general_tips: ResourceStr = $r('app.string.Settings_js_already_disabled');
  32. @State general_title: ResourceStr = $r('app.string.Settings_js_manage');
  33. @State general_switch_desc: ResourceStr = $r('app.string.Settings_js_disable_js');
  34. @State general_subtitle_execute_on_these_sites: ResourceStr = $r('app.string.Settings_js_some_sites');
  35. @State general_subtitle_execute_on_all_sites: ResourceStr = $r('app.string.Settings_js_all_sites');
  36. @State general_switch_settings_id: string = 'disable_js';
  37. @State general_sites_list_settings_id: string = 'disable_js_these_sites';
  38. @State general_switch_all_sites_settings_id: string = 'disable_js_all_sites';
  39. // Settings / Accessibility
  40. @StorageLink('preferred_hand_left_or_right') preferred_hand_left_or_right: string = 'right';
  41. // Manage
  42. @State @Watch('on_select_change') selected: boolean[] = this.all_false(this.general_sites_list.length);
  43. @State selecting: boolean = false;
  44. @State selected_number: number = 0;
  45. @State delete_confirm: number = 0;
  46. // alignRules
  47. alignRules_head_non_tablet: AlignRuleOption = {
  48. top: { anchor: "__container__", align: VerticalAlign.Top },
  49. left: { anchor: "__container__", align: HorizontalAlign.Start }
  50. };
  51. alignRules_head_tablet: AlignRuleOption = {
  52. top: { anchor: "__container__", align: VerticalAlign.Top },
  53. bottom: { anchor: "controls", align: VerticalAlign.Top },
  54. left: { anchor: "__container__", align: HorizontalAlign.Start },
  55. };
  56. alignRules_foot: AlignRuleOption = {
  57. bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
  58. left: { anchor: "__container__", align: HorizontalAlign.Start }
  59. };
  60. alignRules_body_tablet: AlignRuleOption = {
  61. top: { anchor: "__container__", align: VerticalAlign.Top },
  62. right: { anchor: "__container__", align: HorizontalAlign.End }
  63. };
  64. alignRules_body_non_tablet: AlignRuleOption = {
  65. top: { anchor: "title", align: VerticalAlign.Bottom },
  66. bottom: { anchor: "controls", align: VerticalAlign.Top },
  67. right: { anchor: "__container__", align: HorizontalAlign.End }
  68. };
  69. // Colors
  70. @StorageProp('color_current_primary') color_current_primary: ResourceColor = $r('app.color.start_window_background');
  71. @StorageProp('color_current_secondary') color_current_secondary: ResourceColor = $r('app.color.block_color');
  72. @StorageProp('color_current_font') color_current_font: ResourceColor = $r('app.color.font_color_title');
  73. // Gateways
  74. @StorageLink('universal_fail_prompt_desc_gateway') uni_fail_prompt_gateway: ResourceStr = "";
  75. build() {
  76. woofControlFrame({
  77. title: this.general_title,
  78. controller: this.controller
  79. }) {
  80. RelativeContainer() {
  81. Scroll() {
  82. Column({ space: 10 }) {
  83. ForEach(this.general_descriptions, (desc: ResourceStr, _index: number) => {
  84. linysText({
  85. text: desc,
  86. max_lines: 10
  87. })
  88. .width("100%")
  89. })
  90. linysText({
  91. text: this.general_tips,
  92. max_lines: 3
  93. })
  94. .width("100%")
  95. .visibility(this.match_this_domain(this.current_url) ? Visibility.None : Visibility.Visible)
  96. .animation(animation_default())
  97. linysText({
  98. text: $r('app.string.Have_a_Nice_Surf'),
  99. max_lines: 2
  100. })
  101. .width("100%")
  102. .opacity(0.9)
  103. } // Title
  104. .width("100%")
  105. }
  106. .align(Alignment.TopStart)
  107. .edgeEffect(EdgeEffect.Spring)
  108. .padding({ bottom: 10, right: 10 })
  109. .width(this.tablet_mode ? "40%" : "100%")
  110. .constraintSize(this.tablet_mode ? {} : { maxHeight: '35%' })
  111. .alignRules(this.tablet_mode ? this.alignRules_head_tablet : this.alignRules_head_non_tablet)
  112. .animation(animation_default())
  113. .id("title")
  114. Column({ space: 10 }) {
  115. linysText({
  116. text: this.general_subtitle_execute_on_these_sites,
  117. max_lines: 3
  118. })
  119. .padding({ top: this.tablet_mode ? 0 : 10 })
  120. .width("100%")
  121. .opacity(this.general_on_all_sites_switch || !this.general_switch ? 0.5 : 1)
  122. .animation(animation_default())
  123. Scroll() {
  124. Column() {
  125. ForEach(this.general_sites_list, (item: string, index: number) => {
  126. Element({
  127. domain: item,
  128. index: index,
  129. selected: this.selected,
  130. selected_number: this.selected_number,
  131. selecting: this.selecting
  132. })
  133. .width("100%")
  134. })
  135. if (this.general_sites_list.length == 0) {
  136. linysTextTitle({
  137. text: "当前数量为空"
  138. })
  139. .margin(30)
  140. .opacity(0.7)
  141. .animation(animation_default())
  142. }
  143. }
  144. .width("100%")
  145. } // domains display list
  146. .scrollable(ScrollDirection.Vertical)
  147. .edgeEffect(EdgeEffect.Spring)
  148. .align(Alignment.Top)
  149. .borderRadius(10)
  150. .backgroundColor(this.color_current_secondary)
  151. .width("100%")
  152. .layoutWeight(1)
  153. .opacity(this.general_on_all_sites_switch || !this.general_switch ? 0.5 : 1)
  154. .animation(animation_default())
  155. linysSwitchWithText({
  156. text: this.general_subtitle_execute_on_all_sites,
  157. toggle_state: this.general_on_all_sites_switch,
  158. onExecution: () => {
  159. this.bunch_of_settings.set(this.general_switch_all_sites_settings_id, this.general_on_all_sites_switch);
  160. }
  161. })// Toggle on all sites
  162. .opacity(!this.general_switch ? 0.5 : 1)
  163. .animation(animation_default())
  164. linysSwitchWithText({
  165. text: this.general_switch_desc,
  166. toggle_state: this.general_switch,
  167. onExecution: () => {
  168. this.bunch_of_settings.set(this.general_switch_settings_id, this.general_switch);
  169. }
  170. }) // Feature enable
  171. } // Whitelist
  172. .width(this.tablet_mode ? "60%" : "100%")
  173. .height(this.tablet_mode ? "100%" : undefined)
  174. .alignRules(this.tablet_mode ? this.alignRules_body_tablet : this.alignRules_body_non_tablet)
  175. .animation(animation_default())
  176. Column() {
  177. linysShowButton({
  178. show: this.showing_add_panel,
  179. symbol_glyph_target: "sys.symbol.plus",
  180. text: $r("app.string.Settings_woof_add_a_domain")
  181. })// Add Button
  182. .onClick(() => {
  183. this.showing_add_panel = !this.showing_add_panel;
  184. })
  185. Scroll() {
  186. Column({ space: 8 }) {
  187. TextInput({ text: this.add_site_edit })// Input domain
  188. .onChange((value) => {
  189. this.add_site_edit = value;
  190. })
  191. .fontWeight(FontWeight.Regular)
  192. .fontColor(this.color_current_font)
  193. .caretColor(this.color_current_font)
  194. .selectedBackgroundColor(this.color_current_font)
  195. .width("100%")
  196. .onSubmit(() => {
  197. this.add_item(this.add_site_edit);
  198. this.add_site_edit = "";
  199. this.showing_add_panel = false;
  200. })
  201. .height(capsule_bar_height())
  202. .animation(animation_default())
  203. linysCapsuleButton({ text: " 󰀓 " })
  204. .animation(animation_default())
  205. .onClick(() => {
  206. this.add_item(this.add_site_edit);
  207. this.add_site_edit = "";
  208. this.showing_add_panel = false;
  209. })
  210. }
  211. .padding({ top: 10 })
  212. .alignItems(this.preferred_hand_left_or_right == 'right' ? HorizontalAlign.End : HorizontalAlign.Start)
  213. .animation(animation_default())
  214. .width("100%")
  215. } // Add
  216. .scrollBar(BarState.Off)
  217. .width("100%")
  218. .height(this.showing_add_panel ? 90 : 0)
  219. .animation(animation_default())
  220. Scroll() {
  221. Column({ space: 10 }) {
  222. Row() {
  223. linysTextTitle({ text: $r("app.string.Settings_edit_selecting") })
  224. linysTextTitle({ text: " " + this.selected_number.toString() + " " })
  225. linysTextTitle({ text: $r("app.string.Settings_edit_selecting_items") })
  226. }
  227. Row() {
  228. linysSymbol({ symbol_glyph_target: 'sys.symbol.list_checkmask' })
  229. .onClick(() => {
  230. this.select_all();
  231. })
  232. Blank()
  233. linysTimeoutButton({
  234. dialogText: "确定是否删除选中内容",
  235. text: " 󰀁 ",
  236. onExecution: () => {
  237. this.delete_selected();
  238. }
  239. }) // Delete
  240. }
  241. .width("100%")
  242. }
  243. .padding({ top: 10 })
  244. .alignItems(HorizontalAlign.Start)
  245. .width("100%")
  246. } // Select controls
  247. .scrollBar(BarState.Off)
  248. .width("100%")
  249. .height(this.selecting ? 80 : 0)
  250. .animation(animation_default())
  251. } // Controls
  252. .padding({ top: 10, right: this.tablet_mode ? 10 : 0 })
  253. .alignItems(this.preferred_hand_left_or_right == 'right' ? HorizontalAlign.End : HorizontalAlign.Start)
  254. .alignRules(this.alignRules_foot)
  255. .opacity(this.general_on_all_sites_switch || !this.general_switch ? 0.5 : 1)
  256. .animation(animation_default())
  257. .width(this.tablet_mode ? "40%" : "100%")
  258. .id("controls")
  259. .onAppear(() => {
  260. setInterval(() => {
  261. if (this.delete_confirm > 0) {
  262. this.delete_confirm -= 1;
  263. }
  264. // Reset delete confirm
  265. }, 10)
  266. })
  267. }.layoutWeight(1)
  268. }
  269. }
  270. all_false(length: number) {
  271. let result: boolean[] = [];
  272. for (let index = 0; index < length; index++) {
  273. result.push(false);
  274. }
  275. return result;
  276. }
  277. on_select_change() {
  278. if (this.selected.includes(true)) {
  279. this.selecting = true;
  280. } else {
  281. this.selecting = false;
  282. }
  283. this.delete_confirm = 0;
  284. }
  285. select_all() {
  286. let new_selected: boolean[] = [];
  287. if (this.selected.includes(false)) {
  288. for (let index = 0; index < this.selected.length; index++) {
  289. new_selected.push(true);
  290. }
  291. this.selected_number = this.selected.length;
  292. } else {
  293. for (let index = 0; index < this.selected.length; index++) {
  294. new_selected.push(false);
  295. }
  296. this.selected_number = 0;
  297. }
  298. this.selected = new_selected;
  299. }
  300. add_item(domain: string) {
  301. if (domain == '') {
  302. this.uni_fail_prompt_gateway = $r('app.string.Fail_desc_no_content');
  303. return;
  304. }
  305. webview.AdsBlockManager.addAdsBlockDisallowedList([domain]);
  306. if (this.general_sites_list.includes(domain)) {
  307. // don't add same domains
  308. this.uni_fail_prompt_gateway = $r('app.string.Fail_desc_duplicate_domain');
  309. return;
  310. }
  311. this.general_sites_list.push(domain);
  312. this.bunch_of_settings.set(this.general_sites_list_settings_id, this.general_sites_list.join("\n"))
  313. }
  314. delete_selected() {
  315. let new_exceptions: string[] = [];
  316. let delete_exceptions: string[] = [];
  317. for (let index = 0; index < this.selected.length; index++) {
  318. if (!this.selected[index]) {
  319. new_exceptions.push(this.general_sites_list[index]);
  320. } else {
  321. delete_exceptions.push(this.general_sites_list[index]);
  322. }
  323. }
  324. this.general_sites_list = new_exceptions;
  325. this.delete_confirm = 0;
  326. this.selecting = false;
  327. this.selected_number = 0;
  328. this.selected = this.all_false(this.general_sites_list.length);
  329. this.bunch_of_settings.set(this.general_sites_list_settings_id, this.general_sites_list.join("\n"))
  330. }
  331. match_this_domain(address: string) {
  332. if (!this.general_switch) {
  333. return true;
  334. }
  335. // Disable toggle ON
  336. if (this.general_on_all_sites_switch) {
  337. // Disable on all sites
  338. return false;
  339. }
  340. // Disable on some sites
  341. if (address && this.general_sites_list.includes(match_domain(address)[1])) {
  342. return false;
  343. }
  344. return true;
  345. }
  346. }
  347. export default woofGeneralManage;
  348. @Component
  349. struct Element {
  350. @State domain: string = "huawei.com";
  351. @Prop index: number;
  352. @Link selected: boolean[];
  353. @Link selected_number: number;
  354. @Prop selecting: boolean;
  355. // Color
  356. @StorageProp('color_current_secondary') color_current_secondary: ResourceColor = $r('app.color.block_color');
  357. @StorageProp('color_current_font') color_current_font: ResourceColor = $r('app.color.font_color_title');
  358. build() {
  359. Column() {
  360. linysText({
  361. color: this.selected[this.index] ? this.color_current_secondary : this.color_current_font,
  362. text: this.domain,
  363. font_weight: this.selected[this.index] ? FontWeight.Bold : FontWeight.Regular
  364. })
  365. }
  366. .alignItems(HorizontalAlign.Start)
  367. .width("100%")
  368. .backgroundColor(this.selected[this.index] ? this.color_current_font : 'transparent')
  369. .animation(animation_default())
  370. .padding({
  371. left: 10,
  372. right: 10,
  373. top: 5,
  374. bottom: 5
  375. })
  376. .clickEffect(click_effect_default())
  377. .onClick(() => {
  378. if (this.selecting) {
  379. // Select
  380. this.select_unselect();
  381. }
  382. })
  383. .width("100%")
  384. .gesture(
  385. LongPressGesture({ repeat: false })
  386. .onAction(() => {
  387. this.select_unselect();
  388. })
  389. )
  390. .onMouse((e) => {
  391. if (e.button == MouseButton.Right && e.action == MouseAction.Press) {
  392. // Right click
  393. this.select_unselect();
  394. }
  395. })
  396. }
  397. select_unselect() {
  398. if (this.selected[this.index]) {
  399. this.selected_number -= 1;
  400. } else {
  401. this.selected_number += 1;
  402. }
  403. this.selected[this.index] = !this.selected[this.index];
  404. }
  405. }