imtired method
Implementation
Future<void> imtired(Map<String, String> map) async {
if (_sheet == null) await _connect();
await _initHeaders();
// masterLanguage = config.locales.first;
// var remoteMasterLangId = remoteHeader.indexOf(masterLanguage) + 1;
/// get remote keys
trace('🔑 getting remote Keys ...');
var remoteKeys = await _table.values.column(1, fromRow: 1);
trace('found ${remoteKeys.length} remote Keys 🔑');
var hasKeys = (remoteKeys.length > 1 && remoteKeys[1].isNotEmpty);
// var startRow = hasKeys ? remoteKeys.length + 1 : 2;
// trace(remoteKeys);
if (!hasKeys) {
trace('⛔ no remote Keys found, generating...');
/// no checking needed.
final keys = map.keys.toList();
final values = map.values.toList();
/// direct insert!
await _table.values.insertColumn(
1,
keys,
fromRow: 2,
);
await _table.values.insertColumn(
masterLanguageCol,
values,
fromRow: 2,
);
}
/// how much to fill now ?
var lastRow = await _getLastRemoteRow();
// trace('Last remote keys row: ', lastRow);
/// check each lang separately now.
trace('Validating header columns...');
var rowsData = await _table.values.allRows(
fromColumn: 1,
count: 2,
fill: true,
);
/// inspect 2nd row with access to header :)
for (var i = 0; i < rowsData[1].length; ++i) {
var colData = rowsData[1][i];
var headerValue = rowsData[0][i];
if (colData.isEmpty &&
headerValue.isNotEmpty &&
localHeader.contains(headerValue)) {
if (headerValue == masterLanguage) {
trace('Master language ($headerValue) is corrupt, regenerating.');
await _table.clearColumn(masterLanguageCol, fromRow: 2);
await _table.values.insertColumn(
masterLanguageCol,
map.values.toList(),
fromRow: 2,
);
} else {
trace(
'Auto translate column ${i + 1} ($headerValue) x $lastRow rows');
var data = _generateGoogleTranslateColumn(
fromRow: 2,
fromLocaleCol: masterLanguageCol,
fromLocale: masterLanguage,
toLocale: headerValue,
len: lastRow - 1,
);
await _table.values.insertColumn(i + 1, data, fromRow: 2);
}
}
}
/// --- now let's see what changed.
/// load remote key + master
print('${yellow('❯')} checking changes with the remote keys...');
var remoteMap = await _getRemoteMap(masterLanguageCol);
print('${yellow('❯')} remote keys received ${green('✓')}');
/// check master language text changes
trace('Checking remote master String changes...');
final rowsToUpdate = <int, List<String>>{};
List<String> buildGTRow({
required int row,
required String keyText,
required String masterText,
}) {
var master = config.locales.first;
var out = <String>[];
for (var i = 0; i < remoteHeader.length; ++i) {
var header = remoteHeader[i];
if (header == 'keys') {
out.add(keyText);
} else if (localHeader.contains(header)) {
if (header == master) {
out.add(masterText);
} else {
var data = _getTranslateCell(row, header);
out.add(data);
// out.add(_getCellGTranslate(row, master, header));
}
} else {
out.add('');
}
}
return out;
}
for (var k in map.keys) {
if (!remoteMap.containsKey(k)) continue;
var localText = map[k]!;
var remoteText = remoteMap[k]!;
if (remoteText != localText) {
var row = remoteKeys.indexOf(k) + 1;
rowsToUpdate[row] = buildGTRow(
row: row,
masterText: localText,
keyText: k,
);
trace('- row $row: \n\t', remoteText, '\n\t != \n\t', localText);
}
}
if (rowsToUpdate.isNotEmpty) {
trace('Updating ${rowsToUpdate.length} rows...');
trace(rowsToUpdate);
await _table.batchUpdateRows(rowsToUpdate);
trace('Done updating rows with mismatch text.');
}
/// REMOVE KEYS
var deletedKeys = [];
for (var k in remoteMap.keys) {
if (!map.containsKey(k) && k.isNotEmpty) {
deletedKeys.add(k);
}
}
if (deletedKeys.isNotEmpty) {
trace(
'keys nonexistent in the local map: \n-',
deletedKeys.join(' \n- '),
);
/// we will delete the rows remotely?
// var autoDelete = deletedKeys.length < 2;
var autoDelete = true;
if (autoDelete) {
//// clear the fields!
// _table.batchClearRows(rows)
var clearRows = <int>[];
for (var k in deletedKeys) {
var row = remoteKeys.indexOf(k) + 1;
clearRows.add(row);
// await _table.deleteRow(row);
// remoteMap.remove(k);
// remoteKeys.remove(k);
// trace('Row $row deleted.');
}
if (clearRows.isNotEmpty) {
trace(
'${clearRows.length} rows will be cleared ( ${clearRows.join((', '))} )');
var result = await _table.batchClearRows(clearRows);
trace('Clear rows result:', result);
if (result) {
for (var row in clearRows) {
var k = remoteKeys[row - 1];
remoteMap.remove(k);
remoteKeys[row - 1] = '';
// remoteKeys.remove(k);
}
clearRows.clear();
trace('Rows clearing successful');
}
}
} else {
/// check if its a batch!
trace('You will have to manually delete:');
for (var k in deletedKeys) {
// _table.clearRow(row, fromColumn: 1, length: 12, count: 20);
var row = remoteKeys.indexOf(k) + 1;
trace('- row $row');
}
}
}
/// ADD NEW KEYS
var addedKeys = [];
for (var k in map.keys) {
if (!remoteMap.containsKey(k)) {
addedKeys.add(k);
}
}
if (addedKeys.isNotEmpty) {
trace(
'new keys inserted:\n - ',
addedKeys.join('\n - '),
);
/// we will add the rows to their positions?
// var addToEnd = addedKeys.length > 4;
var addToEnd = true;
final keys0 = map.keys.toList(growable: false);
if (addToEnd) {
var lastRow = await _getLastRemoteRow() + 1;
trace('We will add new records at the end.');
/// ( row > $lastRow )
var insertRows = <List<String>>[];
var row = lastRow;
for (var k in addedKeys) {
// ++lastRow;
// await _table.insertRow(row);
var rowData = _getNewRowKey(
row: row,
key: k,
text: map[k]!,
remoteHeader: remoteHeader,
localHeader: localHeader,
);
insertRows.add(rowData);
++row;
// trace('row $row built');
}
trace('Inserting ${insertRows.length} record(s)');
// await _table.values.insertRows(lastRow, insertRows);
try {
await _table.values.appendRows(insertRows);
} catch (e) {
error('ERROR: $e');
if (e is GSheetsException) {
if (e.cause.toLowerCase().contains('not have permission')) {
error(badCredentialsHelp);
}
}
exit(3);
}
trace('🙂 Append rows complete');
} else {
for (var k in addedKeys) {
var row = keys0.indexOf(k) + 2;
await _table.insertRow(row);
var rowData = _getNewRowKey(
row: row,
key: k,
text: map[k]!,
remoteHeader: remoteHeader,
localHeader: localHeader,
);
await _table.values.insertRow(row, rowData);
trace('row $row built');
}
}
}
if (remoteKeys.contains('')) {
var numBlankSpaces = remoteKeys.where((text) => text.isEmpty).length;
trace('total blank key rows: ', red('$numBlankSpaces'));
/// TODO: Clean up EMPTY keys.
if (numBlankSpaces > 1) {
trace('Empty keys detected: $numBlankSpaces');
var result = await _removeTableWhitespaces();
var count = result['replies']?.first['deleteDuplicates']
?['duplicatesRemovedCount'] ??
0;
trace('Duplicated rows deleted: $count');
}
/// detect the first row!🎯
var firstCleanIndex = remoteKeys.indexOf('');
if (firstCleanIndex > 1) {
var row = firstCleanIndex + 1;
await _table.deleteRow(row);
print('Empty row ${red('$row')} deleted.');
}
}
// trace('Current row count: ', _table.rowCount);
// trace(remoteKeys.length, ':', remoteValues.length);
// trace(remoteMap);
}