Sonnat Project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
6.5 KiB

  1. import 'package:flutter/material.dart';
  2. import 'package:sonnat/core/extensions/number_extension.dart';
  3. import 'package:sonnat/core/theme/app_colors.dart';
  4. import 'package:sonnat/core/theme/app_theme.dart';
  5. import 'package:sonnat/core/theme/reader_theme.dart';
  6. import 'package:sonnat/core/utils/app_utils.dart';
  7. import 'package:sonnat/core/widgets/custom_rich_text.dart';
  8. class QHeaderTextShower extends StatelessWidget {
  9. final String title;
  10. final bool hasFullWidth;
  11. final double fontSizeFactor;
  12. final String? searchHighLight;
  13. const QHeaderTextShower({
  14. super.key,
  15. required this.title,
  16. this.hasFullWidth = true,
  17. this.fontSizeFactor = 1,
  18. this.searchHighLight,
  19. });
  20. @override
  21. Widget build(BuildContext context) {
  22. return Container(
  23. width: hasFullWidth ? 1.sw : null,
  24. margin: Utils.instance.singleMargin(top: 7, bottom: 7),
  25. child: Container(
  26. padding: const EdgeInsets.all(8),
  27. decoration: const BoxDecoration(
  28. color: AppColors.ahkamBlue2,
  29. borderRadius: BorderRadius.all(
  30. Radius.circular(8),
  31. ),
  32. ),
  33. child: HighlightRichText(
  34. text: title.replaceAll(':', '').trim(),
  35. highlight: searchHighLight,
  36. style: AppTheme.instance.fontCreator(fontSizeFactor * 15, FontWeights.bold, AppColors.white),
  37. textAlign: TextAlign.center,
  38. ),
  39. ),
  40. );
  41. }
  42. }
  43. class QAnswerShower extends StatelessWidget {
  44. final String title;
  45. final bool hasFullWidth;
  46. final ReaderTheme? theme;
  47. final double fontSizeFactor;
  48. final String? searchHighLight;
  49. const QAnswerShower({
  50. super.key,
  51. required this.title,
  52. this.hasFullWidth = true,
  53. this.theme = ReaderTheme.light,
  54. this.fontSizeFactor = 1,
  55. this.searchHighLight,
  56. });
  57. @override
  58. Widget build(BuildContext context) {
  59. return Container(
  60. width: hasFullWidth ? 1.sw : null,
  61. margin: Utils.instance.singleMargin(bottom: 7),
  62. child: Container(
  63. padding: const EdgeInsets.all(16),
  64. decoration: BoxDecoration(
  65. boxShadow: [
  66. BoxShadow(
  67. offset: Offset(0.w, 3.h),
  68. blurRadius: 6,
  69. color: AppColors.shadowHomeIcon,
  70. ),
  71. ],
  72. borderRadius: const BorderRadius.all(Radius.circular(8)),
  73. ),
  74. child: HighlightRichText(
  75. text: title.trim(),
  76. highlight: searchHighLight,
  77. style: AppTheme.instance.fontCreator(
  78. fontSizeFactor * 15,
  79. FontWeights.medium,
  80. theme!.isDarkMode ? AppColors.darkModeGreyText : AppColors.ahkamBlue3,
  81. ),
  82. textAlign: Directionality.of(context) == TextDirection.rtl ? TextAlign.right : TextAlign.left,
  83. ),
  84. ),
  85. );
  86. }
  87. }
  88. class QTextShower extends StatelessWidget {
  89. final String title;
  90. final bool hasFullWidth;
  91. final ReaderTheme? theme;
  92. final double fontSizeFactor;
  93. final String? searchHighLight;
  94. const QTextShower({
  95. super.key,
  96. required this.title,
  97. this.hasFullWidth = true,
  98. this.theme = ReaderTheme.light,
  99. this.fontSizeFactor = 1,
  100. this.searchHighLight,
  101. });
  102. @override
  103. Widget build(BuildContext context) {
  104. return SizedBox(
  105. width: hasFullWidth ? 1.sw : null,
  106. child: Container(
  107. decoration: const BoxDecoration(
  108. borderRadius: BorderRadius.all(Radius.circular(8)),
  109. ),
  110. child: HighlightRichText(
  111. text: title.trim(),
  112. highlight: searchHighLight,
  113. style: AppTheme.instance.fontCreator(
  114. fontSizeFactor * 15,
  115. FontWeights.medium,
  116. theme!.color.red,
  117. ),
  118. textAlign: Directionality.of(context) == TextDirection.rtl ? TextAlign.right : TextAlign.left,
  119. ),
  120. ),
  121. );
  122. }
  123. }
  124. class THeaderTextShower extends StatelessWidget {
  125. final String title;
  126. final bool hasFullWidth;
  127. final ReaderTheme? theme;
  128. final double fontSizeFactor;
  129. final String? searchHighLight;
  130. const THeaderTextShower({
  131. super.key,
  132. required this.title,
  133. this.hasFullWidth = true,
  134. this.theme = ReaderTheme.light,
  135. this.fontSizeFactor = 1,
  136. this.searchHighLight,
  137. });
  138. @override
  139. Widget build(BuildContext context) {
  140. return SizedBox(
  141. width: hasFullWidth ? 1.sw : null,
  142. child: Container(
  143. decoration: const BoxDecoration(
  144. borderRadius: BorderRadius.all(Radius.circular(8)),
  145. ),
  146. child: HighlightRichText(
  147. text: title.trim(),
  148. highlight: searchHighLight,
  149. style: AppTheme.instance.fontCreator(
  150. fontSizeFactor * 18,
  151. FontWeights.bold,
  152. theme!.isDarkMode ? AppColors.white : AppColors.ahkamBlue3,
  153. ),
  154. textAlign: Directionality.of(context) == TextDirection.rtl ? TextAlign.right : TextAlign.left,
  155. ),
  156. ),
  157. );
  158. }
  159. }
  160. extension ReplaceTag on String {
  161. String replaceTHeader() {
  162. return replaceAllMapped(
  163. RegExp(r'<([a-z]+)[^>]*t-header[^>]*>(?:(?:<([a-z]+)[^>]*>[^><]*<\/(\2)>)|\n|[^><])*?<\/(\1)>'), (match) {
  164. String result = match.group(0) ?? '';
  165. result = result.replaceFirst(match.group(4).toString(), 't_header');
  166. result = result.replaceAll('${match.group(4)}>', 't_header>');
  167. return result;
  168. });
  169. }
  170. String replaceQHeader() {
  171. return replaceAllMapped(
  172. RegExp(r'<([a-z]+)[^>]*q-header[^>]*>(?:(?:<([a-z]+)[^>]*>[^><]*<\/(\2)>)|\n|[^><])*?<\/(\1)>'), (match) {
  173. String result = match.group(0) ?? '';
  174. result = result.replaceFirst(match.group(4).toString(), 'q_header');
  175. result = result.replaceAll('${match.group(4)}>', 'q_header>');
  176. return result;
  177. });
  178. }
  179. String replaceQText() {
  180. return replaceAllMapped(
  181. RegExp(r'<([a-z]+)[^>]*q-text[^>]*>(?:(?:<([a-z]+)[^>]*>[^><]*<\/(\2)>)|\n|[^><])*?<\/(\1)>'), (match) {
  182. String result = match.group(0) ?? '';
  183. result = result.replaceFirst(match.group(4).toString(), 'q_text');
  184. result = result.replaceAll('${match.group(4)}>', 'q_text>');
  185. return result;
  186. });
  187. }
  188. String replaceQAnswer() {
  189. return replaceAllMapped(
  190. RegExp(r'<([a-z]+)[^>]*q-answer[^>]*>(?:(?:<([a-z]+)[^>]*>[^><]*<\/(\2)>)|\n|[^><])*?<\/(\1)>'), (match) {
  191. String result = match.group(0) ?? '';
  192. result = result.replaceFirst(match.group(4).toString(), 'q_answer');
  193. result = result.replaceAll('${match.group(4)}>', 'q_answer>');
  194. return result;
  195. });
  196. }
  197. String replaceTextStyle() {
  198. return replaceAll(RegExp(r'font-size: ?\d{1,2}px;'), '')
  199. .replaceAll(RegExp(r'font-weight: ?[^;]*;'), '')
  200. .replaceAll(RegExp(r'font-family: ?"[^/"]*"'), '');
  201. }
  202. }