Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/app/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:sagase/services/firebase_service.dart';
import 'package:sagase/services/dictionary_service.dart';
import 'package:sagase/services/mecab_service.dart';
import 'package:sagase/services/shared_preferences_service.dart';
import 'package:sagase/ui/bottom_sheets/add_to_my_list_bottom_sheet.dart';
import 'package:sagase/ui/bottom_sheets/assign_lists_bottom_sheet.dart';
import 'package:sagase/ui/bottom_sheets/assign_my_lists_bottom_sheet.dart';
import 'package:sagase/ui/bottom_sheets/select_dictionary_item_bottom_sheet.dart';
Expand Down Expand Up @@ -107,6 +108,7 @@ import 'package:stacked_themes/stacked_themes.dart';
LazySingleton(classType: SearchViewModel),
],
bottomsheets: [
StackedBottomsheet(classType: AddToMyListBottomSheet),
StackedBottomsheet(classType: AssignMyListsBottomSheet),
StackedBottomsheet(classType: AssignListsBottomSheet),
StackedBottomsheet(classType: StrokeOrderBottomSheet),
Expand Down
8 changes: 8 additions & 0 deletions lib/services/dictionary_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,14 @@ class DictionaryService {
.addDictionaryItem(dictionaryList, dictionaryItem);
}

Future<void> addManyToMyDictionaryList(
MyDictionaryList dictionaryList,
List<DictionaryItem> dictionaryItems,
) async {
await _database.myDictionaryListsDao
.addDictionaryItems(dictionaryList, dictionaryItems);
}

Future<void> removeFromMyDictionaryList(
MyDictionaryList dictionaryList,
DictionaryItem dictionaryItem,
Expand Down
54 changes: 54 additions & 0 deletions lib/ui/bottom_sheets/add_to_my_list_bottom_sheet.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:sagase/ui/bottom_sheets/base_bottom_sheet.dart';
import 'package:stacked_services/stacked_services.dart';

class AddToMyListBottomSheet extends StatelessWidget {
final SheetRequest request;
final Function(SheetResponse) completer;

const AddToMyListBottomSheet({
required this.request,
required this.completer,
super.key,
});

@override
Widget build(BuildContext context) {
return BaseBottomSheet(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 16, right: 16, top: 8),
child: Text(
'Add vocab to list',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 8),
child: const Text(
'Identified vocab will be added to the selected list.\nWords with multiple options will be skipped.',
textAlign: TextAlign.center,
),
),
const Divider(height: 1),
Expanded(
child: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: request.data.length,
itemBuilder: (context, index) => ListTile(
title: Text(request.data[index].name),
onTap: () =>
completer(SheetResponse(data: request.data[index])),
),
),
),
],
),
);
}
}
6 changes: 4 additions & 2 deletions lib/ui/views/text_analysis/text_analysis_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ class _Body extends StackedHookView<TextAnalysisViewModel> {
icon: const Icon(Icons.edit),
),
IconButton(
onPressed: viewModel.copyText,
icon: const Icon(Icons.copy),
onPressed: viewModel.analysisFailed
? null
: viewModel.addToDictionaryList,
icon: const Icon(Icons.playlist_add),
),
],
},
Expand Down
69 changes: 52 additions & 17 deletions lib/ui/views/text_analysis/text_analysis_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class TextAnalysisViewModel extends FutureViewModel {

bool _addToHistory;

List<JapaneseTextToken>? tokens;
List<List<JapaneseTextToken>>? tokens;

bool _analysisFailed = true;
bool get analysisFailed => _analysisFailed;
Expand Down Expand Up @@ -54,22 +54,31 @@ class TextAnalysisViewModel extends FutureViewModel {

_analysisFailed = true;

tokens = _mecabService.parseText(_text);
final lines = _text.split('\n');
tokens = [];

for (var token in tokens!) {
if (token.pos == PartOfSpeech.nounProper &&
_sharedPreferencesService.getProperNounsEnabled()) {
token.associatedDictionaryItems =
await _dictionaryService.getProperNounByJapaneseTextToken(token);
}
for (var line in lines) {
String internalTrimmed = line.trim();
if (internalTrimmed.isEmpty) continue;

if (token.associatedDictionaryItems == null ||
token.associatedDictionaryItems!.isEmpty) {
token.associatedDictionaryItems =
await _dictionaryService.getVocabByJapaneseTextToken(token);
}
if (token.associatedDictionaryItems!.isNotEmpty) {
_analysisFailed = false;
final lineTokens = _mecabService.parseText(internalTrimmed);
tokens!.add(lineTokens);

for (var token in lineTokens) {
if (token.pos == PartOfSpeech.nounProper &&
_sharedPreferencesService.getProperNounsEnabled()) {
token.associatedDictionaryItems =
await _dictionaryService.getProperNounByJapaneseTextToken(token);
}

if (token.associatedDictionaryItems == null ||
token.associatedDictionaryItems!.isEmpty) {
token.associatedDictionaryItems =
await _dictionaryService.getVocabByJapaneseTextToken(token);
}
if (token.associatedDictionaryItems!.isNotEmpty) {
_analysisFailed = false;
}
}
}

Expand All @@ -87,8 +96,34 @@ class TextAnalysisViewModel extends FutureViewModel {
rebuildUi();
}

void copyText() {
Clipboard.setData(ClipboardData(text: _text));
Future<void> addToDictionaryList() async {
final myDictionaryLists =
await _dictionaryService.getAllMyDictionaryLists();

final response = await _bottomSheetService.showCustomSheet(
variant: BottomSheetType.addToMyListBottom,
data: myDictionaryLists,
);

if (response?.data == null) return;

final List<DictionaryItem> itemsToAdd = [];
for (var lineTokens in tokens!) {
for (var token in lineTokens) {
if (token.associatedDictionaryItems != null &&
token.associatedDictionaryItems!.length == 1 &&
token.associatedDictionaryItems!.first is Vocab) {
itemsToAdd.add(token.associatedDictionaryItems!.first);
}
}
}

await _dictionaryService.addManyToMyDictionaryList(
response!.data! as MyDictionaryList,
itemsToAdd,
);

_snackbarService.showSnackbar(message: 'Vocab added to list');
}

void openAssociatedDictionaryItem(JapaneseTextToken token) {
Expand Down
Loading