importDictionary method

Future<void> importDictionary(
  1. {required File file,
  2. required ValueNotifier<String> progressNotifier,
  3. required dynamic onImportSuccess(
      )}
    )

    Start the process of importing a dictionary. This is called from the dictionary menu, and starts the process of importing for the lastSelectedDictionaryFormat.

    Implementation

    Future<void> importDictionary({
      required File file,
      required ValueNotifier<String> progressNotifier,
      required Function() onImportSuccess,
    }) async {
      /// New results may be wrong after dictionary is added so this has to be
      /// done.
      clearDictionaryResultsCache();
    
      Directory workingDirectory = _dictionaryImportWorkingDirectory;
      DictionaryFormat dictionaryFormat = lastSelectedDictionaryFormat;
    
      /// Importing makes heavy use of isolates as it is very performance
      /// intensive to work with files. In order to ensure the UI isolate isn't
      /// blocked, a [ReceivePort] is necessary to receive UI updates.
      ReceivePort receivePort = ReceivePort();
      receivePort.listen((message) {
        progressNotifier.value = '$message';
      });
    
      /// Used to show an [AlertDialog] if critical information needs to be
      /// given to a user regarding the dictionary they are importing.
      ReceivePort alertReceivePort = ReceivePort();
      alertReceivePort.listen((message) {
        Fluttertoast.showToast(
          msg: message.toString(),
          toastLength: Toast.LENGTH_LONG,
        );
      });
    
      /// If any [Exception] occurs, the process is aborted with a message as
      /// shown below. A dialog is shown to show the progress of the dictionary
      /// file import, with messages pertaining to the above [ValueNotifier].
      try {
        /// The working directory should always be emptied before and after
        /// dictionary import to ensure that no files bloat the system and that
        /// files from previous imports do not carry over.
        if (workingDirectory.existsSync()) {
          progressNotifier.value = t.import_clean;
          workingDirectory.deleteSync(recursive: true);
          workingDirectory.createSync();
        }
    
        String charset = '';
    
        /// Find a way to check if this is a text file or a binary file instead
        /// of doing this, it's not good to do format-specific tweaks in a
        /// general function like this.
        if (dictionaryFormat.isTextFormat) {
          var randomAccessFile = file.openSync();
          var bytes = randomAccessFile.readSync(100);
          DecodingResult result = await CharsetDetector.autoDecode(bytes);
          charset = result.charset;
        }
    
        PrepareDirectoryParams prepareDirectoryParams = PrepareDirectoryParams(
          file: file,
          charset: charset,
          directoryPath: _databaseDirectory.path,
          workingDirectory: workingDirectory,
          dictionaryFormat: dictionaryFormat,
          sendPort: receivePort.sendPort,
        );
        progressNotifier.value = t.import_extract;
        await dictionaryFormat.prepareDirectory(prepareDirectoryParams);
    
        String name = await dictionaryFormat.prepareName(prepareDirectoryParams);
        progressNotifier.value = t.import_name(name: name);
        Dictionary? bottomMostDictionary = _database.dictionarys
            .where(sort: Sort.desc)
            .anyOrder()
            .findFirstSync();
    
        Dictionary? sameNameDictionary =
            _database.dictionarys.where().nameEqualTo(name).findFirstSync();
        if (sameNameDictionary != null) {
          throw Exception(t.import_duplicate(name: name));
        }
    
        int order = (bottomMostDictionary?.order ?? 0) + 1;
    
        Dictionary dictionary = Dictionary(
          order: order,
          name: name,
          formatKey: dictionaryFormat.uniqueKey,
        );
    
        PrepareDictionaryParams prepareDictionaryParams = PrepareDictionaryParams(
          dictionary: dictionary,
          workingDirectory: workingDirectory,
          directoryPath: _databaseDirectory.path,
          dictionaryFormat: dictionaryFormat,
          useSlowImport: useSlowImport,
          sendPort: receivePort.sendPort,
          alertSendPort: alertReceivePort.sendPort,
        );
    
        await compute(depositDictionaryDataHelper, prepareDictionaryParams);
    
        /// The working directory should always be emptied before and after
        /// dictionary import to ensure that no files bloat the system and that
        /// files from previous imports do not carry over.
        if (workingDirectory.existsSync()) {
          progressNotifier.value = t.import_clean;
          workingDirectory.deleteSync(recursive: true);
          workingDirectory.createSync();
        }
    
        progressNotifier.value = t.import_complete;
        onImportSuccess();
        await Future.delayed(const Duration(seconds: 1), () {});
      } catch (e) {
        progressNotifier.value = '$e';
        await Future.delayed(const Duration(seconds: 3), () {});
        progressNotifier.value = t.import_failed;
        await Future.delayed(const Duration(seconds: 1), () {});
      } finally {
        receivePort.close();
      }
    }