Skip to content

Commit

Permalink
refactor dict_content_view to separate files for dpd extra buttons sh…
Browse files Browse the repository at this point in the history
…ow_declension_dialog.dart ... etc
  • Loading branch information
bksubhuti committed Oct 10, 2024
1 parent b6e867a commit 92115e8
Show file tree
Hide file tree
Showing 10 changed files with 876 additions and 810 deletions.
2 changes: 1 addition & 1 deletion lib/data/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const String highlightTagName = 'highlight';

class DatabaseInfo {
DatabaseInfo._();
static const int version = 46;
static const int version = 47;
static const String fileName = 'tipitaka_pali.db';
}

Expand Down
156 changes: 156 additions & 0 deletions lib/ui/dialogs/show_compound_family_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tipitaka_pali/ui/screens/dictionary/controller/dictionary_controller.dart';
import 'package:tipitaka_pali/utils/platform_info.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:tipitaka_pali/utils/super_scripter_uni.dart';

import '../../../../business_logic/models/dpd_compound_family.dart';
import '../../../../services/prefs.dart';

showCompoundFamilyDialog(BuildContext context, int wordId) async {
var dictionaryController = context.read<DictionaryController>();
List<DpdCompoundFamily>? compoundFamilies =
await dictionaryController.getDpdCompoundFamilies(wordId);

// prevent using context across asynch gaps
if (!context.mounted) return;

if (compoundFamilies == null || compoundFamilies.isEmpty) {
// TODO not all words have root family, so need to show a 'install' dialog
// only if the root family tables do not exist

return;
}

debugPrint('Compound families count: ${compoundFamilies.length}');
if (!context.mounted) return;

List<dynamic> jsonData = [];
for (final compoundFamily in compoundFamilies) {
jsonData.addAll(json.decode(compoundFamily.data));
}

final DpdCompoundFamily first = compoundFamilies[0];
final count = compoundFamilies.fold(0, (sum, cf) => sum + cf.count);
final isMobile = Mobile.isPhone(context);
const insetPadding = 10.0;
final word = first.word.replaceAll(RegExp(r" \d.*\$"), '');

final content = isMobile
? SizedBox(
width: MediaQuery.of(context).size.width - 2 * insetPadding,
child: _getCompoundFamilyWidget(count, word, jsonData),
)
: Container(
constraints: const BoxConstraints(
maxHeight: 400,
maxWidth: 800,
),
child: _getCompoundFamilyWidget(count, word, jsonData));

showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(superscripterUni(first.word)),
contentPadding: isMobile ? EdgeInsets.zero : null,
insetPadding: isMobile ? const EdgeInsets.all(insetPadding) : null,
content: content,
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.ok))
],
));
}

Scrollbar _getCompoundFamilyWidget(count, word, jsonData) {
final horizontal = ScrollController();
final vertical = ScrollController();
return Scrollbar(
controller: vertical,
thumbVisibility: true,
trackVisibility: true,
child: Scrollbar(
controller: horizontal,
thumbVisibility: true,
trackVisibility: true,
notificationPredicate: (notification) => notification.depth == 1,
child: SingleChildScrollView(
controller: vertical,
child: SingleChildScrollView(
controller: horizontal,
scrollDirection: Axis.horizontal,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_getCompoundFamilyHeader(count, word),
_getCompoundFamilyTable(jsonData)
],
)),
),
),
);
}

SelectableText _getCompoundFamilyHeader(count, word) {
return SelectableText.rich(
TextSpan(children: [
TextSpan(
text: '$count', style: const TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(text: ' compounds which contain '),
TextSpan(
text: word,
style: TextStyle(
fontSize: Prefs.dictionaryFontSize.toDouble(),
fontWeight: FontWeight.bold)),
]),
textAlign: TextAlign.left,
);
}

Table _getCompoundFamilyTable(List<dynamic> jsonData) {
return Table(
border: TableBorder.all(),
defaultColumnWidth: const IntrinsicColumnWidth(),
children: jsonData.map((item) {
return TableRow(
children: [
TableCell(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SelectableText(
item[0],
style: TextStyle(
fontSize: Prefs.dictionaryFontSize.toDouble(),
color: Colors.orange,
fontWeight: FontWeight.bold),
),
),
),
TableCell(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SelectableText(
item[1],
style: TextStyle(
fontSize: Prefs.dictionaryFontSize.toDouble(),
fontWeight: FontWeight.bold),
),
),
),
TableCell(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SelectableText('${item[2]} ${item[3]}',
style:
TextStyle(fontSize: Prefs.dictionaryFontSize.toDouble())),
),
),
],
);
}).toList(),
);
}
187 changes: 187 additions & 0 deletions lib/ui/dialogs/show_declension_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import 'dart:convert';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tipitaka_pali/business_logic/models/dpd_inflection.dart';
import 'package:tipitaka_pali/routes.dart';
import 'package:tipitaka_pali/services/prefs.dart';
import 'package:tipitaka_pali/ui/screens/dictionary/controller/dictionary_controller.dart';
import 'package:tipitaka_pali/ui/screens/settings/download_view.dart';
import 'package:tipitaka_pali/utils/platform_info.dart';
import 'package:tipitaka_pali/utils/super_scripter_uni.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

showDeclensionDialog(BuildContext context, int wordId) async {
var dictionaryController = context.read<DictionaryController>();
DpdInflection? inflection =
await dictionaryController.getDpdInflection(wordId);

// Prevent using context across async gaps
if (!context.mounted) return;

// Handle case where no inflection data is found
if (inflection == null) {
bool? shouldNavigate = await showDialog<bool>(
context: context,
builder: (dialogContext) => AlertDialog(
title: Text(AppLocalizations.of(context)!.inflectionNoDataTitle),
content: Text(AppLocalizations.of(context)!.inflectionNoDataMessage),
actions: [
TextButton(
onPressed: () => Navigator.of(dialogContext).pop(false),
child: Text(AppLocalizations.of(context)!.close),
),
],
),
);

if (shouldNavigate == true) {
if (!context.mounted) return;
final route =
MaterialPageRoute(builder: (context) => const DownloadView());
NestedNavigationHelper.goto(
context: context, route: route, navkey: dictionaryNavigationKey);
}

return;
}

debugPrint('Inflection: $inflection');

String data = await DefaultAssetBundle.of(context)
.loadString("assets/inflectionTemplates.json");
List inflectionTemplates = jsonDecode(data);
final template = inflectionTemplates
.firstWhereOrNull((map) => map['pattern'] == inflection.pattern);

if (template == null) {
debugPrint('Could not find template...');
return;
}

debugPrint('Template: $template');

// Prepare the table rows from the template data
List<TableRow> rows =
template['data'].asMap().entries.map<TableRow>((rowEntry) {
int rowIndex = rowEntry.key;
List<List<String>> row = (rowEntry.value as List)
.map((e) => (e as List).map((item) => item as String).toList())
.toList();

return TableRow(
children: row
.asMap()
.entries
.map<Padding?>((entry) {
int colIndex = entry.key;
List<String> cell = entry.value;
if (colIndex == 0) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SelectableText(cell[0],
style: const TextStyle(
fontWeight: FontWeight.w600, color: Colors.orange)),
);
}
if (colIndex % 2 != 1) {
return null;
}
List<InlineSpan> spans = [];

cell.asMap().forEach((index, value) {
if (index > 0) {
spans.add(const TextSpan(text: '\n'));
}
if (rowIndex == 0) {
spans.add(TextSpan(
text: value,
style: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.orange)));
} else if (value.isNotEmpty) {
spans.add(TextSpan(
text: inflection.stem,
style: TextStyle(
fontSize: Prefs.dictionaryFontSize.toDouble())));
spans.add(TextSpan(
text: value,
style: TextStyle(
fontSize: Prefs.dictionaryFontSize.toDouble(),
fontWeight: FontWeight.bold)));
}
});

return Padding(
padding: const EdgeInsets.all(8.0),
child: SelectableText.rich(TextSpan(children: spans)),
);
})
.where((cell) => cell != null)
.cast<Padding>()
.toList(),
);
}).toList();

if (!context.mounted) return;

final isMobile = Mobile.isPhone(context);
const insetPadding = 10.0;

final content = isMobile
? SizedBox(
width: MediaQuery.of(context).size.width - 2 * insetPadding,
child: _getInflectionWidget(rows),
)
: Container(
constraints: const BoxConstraints(
maxHeight: 400,
maxWidth: 800,
),
child: _getInflectionWidget(rows),
);

showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(superscripterUni(inflection.word)),
contentPadding: isMobile ? EdgeInsets.zero : null,
insetPadding: isMobile ? const EdgeInsets.all(insetPadding) : null,
content: content,
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.ok)),
],
),
);
}

Scrollbar _getInflectionWidget(List<TableRow> rows) {
final horizontal = ScrollController();
final vertical = ScrollController();

return Scrollbar(
controller: vertical,
thumbVisibility: true,
trackVisibility: true,
child: Scrollbar(
controller: horizontal,
thumbVisibility: true,
trackVisibility: true,
notificationPredicate: (notification) => notification.depth == 1,
child: SingleChildScrollView(
controller: vertical,
child: SingleChildScrollView(
controller: horizontal,
scrollDirection: Axis.horizontal,
child: Table(
border: TableBorder.all(),
defaultColumnWidth: const IntrinsicColumnWidth(),
children: rows,
),
),
),
),
);
}
Loading

0 comments on commit 92115e8

Please sign in to comment.