Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Burrito translation multimedia and notes #373

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
33 changes: 33 additions & 0 deletions main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@ function isDev() {
return process.argv[2] == '--dev';
}

const CACHE_DIR = path.join(app.getPath('userData'), 'video-cache');

if (!fs.existsSync(CACHE_DIR)) {
fs.mkdirSync(CACHE_DIR);
}

// Handle requests to check if a video is cached
ipcMain.handle('is-video-cached', (event, videoUrl) => {
const videoFileName = path.basename(videoUrl);
const localVideoPath = path.join(CACHE_DIR, videoFileName);
return fs.existsSync(localVideoPath) ? localVideoPath : null;
});

// Handle requests to download and cache the video
ipcMain.handle('download-and-cache-video', async (event, videoUrl) => {
const videoFileName = path.basename(videoUrl);
const localVideoPath = path.join(CACHE_DIR, videoFileName);

const net = require('electron').net;
const request = net.request(videoUrl);

return new Promise((resolve, reject) => {
const fileStream = fs.createWriteStream(localVideoPath);
request.on('response', (response) => {
response.pipe(fileStream);
fileStream.on('finish', () => resolve(localVideoPath));
});

request.on('error', reject);
request.end();
});
});

async function setPermissions(chromePath) {
try {
fs.chmodSync(chromePath, '755');
Expand Down
2 changes: 2 additions & 0 deletions renderer/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const environment = {
GITEA_SERVER: 'https://git.door43.org',
GITEA_TOKEN: 'Gitea AG Testing',
GITEA_API_ENDPOINT: 'https://git.door43.org/api/v1',
GITHUB_SERVER: 'https://github.com',
GITHUB_API_ENDPOINT: 'https://api.github.com',
uuidToken: '6223f833-3e59-429c-bec9-16910442b599',
SYNC_BACKUP_COUNT: 5,
AG_MINIMUM_BURRITO_VERSION: '0.3.0',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function SelectBook({
function bookSelect(e, bookId) {
e.preventDefault();
onChangeBook(bookId, selectedBooks[0]);
setBook(bookId);
setBook && setBook(bookId);
if (multiSelectBook === false) { selectBook(); }
}

Expand Down
67 changes: 66 additions & 1 deletion renderer/src/components/EditorPage/Reference/TranslationHelps.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React, { useContext } from 'react';
import React, { useContext, useState, useEffect } from 'react';
import * as localforage from 'localforage';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { ReferenceContext } from '@/components/context/ReferenceContext';
import { debug } from '../../../logger';
import TranslationHelpsCard from './TranslationHelpsCard';
import TranslationHelpsMultimediaCard from './TranslationHelpsMultimediaCard';
import ObsTnCard from './OBS/ObsTn';
import ObsTwlCard from './OBS/ObsTwlCard';
import packageInfo from '../../../../../package.json';

const TranslationHelps = ({
selectedResource, languageId, refName, bookId, chapter, verse, owner, story, offlineResource, font, fontSize,
Expand All @@ -17,16 +21,58 @@ const TranslationHelps = ({
} = useContext(ReferenceContext);
const { t } = useTranslation();

/**
* Function to search a directory for a file containing a specific name part.
* @param {string} directoryPath - The path of the directory to search in.
* @param {string} partialName - The partial name to search for in the file names.
* @returns {string|null} - The full name of the matched file, or null if not found.
*/
const findFileByPartialName = (fsInstance, directoryPath, partialName) => fsInstance.readdirSync(directoryPath).find((file) => file.includes(partialName)) || null;

const translationQuestionsPath = `${(chapter < 10) ? (`0${ chapter}`)
: chapter}/${(verse < 10) ? (`0${ verse}`) : verse}.md`;

const filePathTa = `${taNavigationPath?.path}/01.md`;

const [resourceLinkPath, setResourceLinkPath] = useState('');
const [imagesPath, setImagesPath] = useState('');

useEffect(() => {
async function getLinkedFolderPath() {
const fs = window.require('fs');
const path = window.require('path');
try {
const newpath = localStorage.getItem('userPath');
const userProfile = await localforage.getItem('userProfile');
const resourceDirPath = path.join(newpath, packageInfo.name, 'users', userProfile?.username, 'resources');
const pathToIngredients = path.resolve(resourceDirPath, offlineResource.data.projectDir, 'ingredients');
if (pathToIngredients) {
const pathRelationFile = path.resolve(pathToIngredients, 'relation.txt');
if (fs.existsSync(pathRelationFile)) {
setImagesPath(pathToIngredients);
const relationFileContent = fs.readFileSync(pathRelationFile, 'utf8');
const fileName = findFileByPartialName(fs, path.resolve(resourceDirPath), relationFileContent.trim());
setResourceLinkPath(path.resolve(resourceDirPath, fileName, 'ingredients'));
} else {
setImagesPath('');
setResourceLinkPath(pathToIngredients);
debug('TranslationHelps.js', `pathRelationFile : ${pathRelationFile} - Not found!`);
}
}
} catch (e) {
debug('TranslationHelps.js', `Error : ${e}`);
}
}

getLinkedFolderPath();
}, [selectedResource, offlineResource]);

return (
<>
{(() => {
switch (selectedResource) {
case 'tn':
case 'x-bcvnotes':
return (
<TranslationHelpsCard
title={t('label-resource-tn')}
Expand All @@ -43,6 +89,25 @@ const TranslationHelps = ({
fontSize={fontSize}
/>
);
case 'tir':
return (
<TranslationHelpsMultimediaCard
title={t('label-resource-tir')}
verse={verse}
chapter={chapter}
projectId={bookId.toUpperCase() || 'mat'.toUpperCase()}
branch={branch}
languageId={languageId}
resourceId="tir"
owner={owner}
server="https://git.door43.org"
offlineResource={offlineResource}
font={font}
fontSize={fontSize}
folderPath={resourceLinkPath}
linkedFolderPath={imagesPath}
/>
);
// case 'twl':
// return (
// <TranslationHelpsCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,29 @@ export default function TranslationHelpsCard({
const [currentChapterVerse, setCurrentChapterVerse] = useState({ verse, chapter });

// eslint-disable-next-line prefer-const
let { items, markdown, isLoading } = useContent({
verse: currentChapterVerse.verse,
chapter: currentChapterVerse.chapter,
projectId,
branch,
languageId,
resourceId,
filePath,
owner,
server,
readyToFetch: true,
});
let items = [];
let markdown = '';
let isLoading;
try {
const tmpRes = useContent({
verse: currentChapterVerse.verse,
chapter: currentChapterVerse.chapter,
projectId,
branch,
languageId,
resourceId,
filePath,
owner,
// server:"https://api.github.com",
server,
readyToFetch: true,
});
items = tmpRes.items;
markdown = tmpRes.markdown;
isLoading = tmpRes.isLoading;
} catch (e) {
logger.debug('TranslationHelpsCard.js', 'Error setting up in useContent');
}

useEffect(() => {
if (currentTnTab === 1) {
Expand All @@ -73,26 +84,56 @@ export default function TranslationHelpsCard({
try {
setOfflineMarkdown('');
setOfflineItems('');
let isBurrito = false;
localForage.getItem('userProfile').then(async (user) => {
logger.debug('TranslationHelpsCard.js', `reading offline helps ${offlineResource.data?.projectDir}`);
const fs = window.require('fs');
const path = require('path');
const newpath = localStorage.getItem('userPath');
const currentUser = user?.username;
const folder = path.join(newpath, packageInfo.name, 'users', `${currentUser}`, 'resources');
const projectName = `${offlineResource?.data?.value?.meta?.name}_${offlineResource?.data?.value?.meta?.owner}_${offlineResource?.data?.value?.meta?.release?.tag_name}`;
let projectName = `${offlineResource?.data?.value?.meta?.name}_${offlineResource?.data?.value?.meta?.owner}_${offlineResource?.data?.value?.meta?.release?.tag_name}`;
if (!offlineResource?.data?.value?.meta?.name) {
isBurrito = true;
projectName = offlineResource?.data?.projectDir;
}
// projectName = `${offlineResource?.data?.value?.meta?.name}_${offlineResource?.data?.value?.meta?.owner}_${offlineResource?.data?.value?.meta?.release?.tag_name}`;
// switch resources
switch (resourceId) {
case 'tn':
case 'x-bcvnotes':
// console.log("yep", folder, 'and projectName ==', projectName);
if (fs.existsSync(path.join(folder, projectName))) {
// eslint-disable-next-line array-callback-return
const currentFile = offlineResource?.data?.value?.projects.filter((item) => {
if (item?.identifier.toLowerCase() === projectId.toLowerCase()) {
return item;
let currentFile;
if (isBurrito) {
const asArray = Object.entries(offlineResource?.data?.value?.ingredients);
// currentFile = asArray.filter(([key, value]) => {
// if (key.toLocaleLowerCase().indexOf(projectId.toLowerCase()) !== -1) {
// console.log("key ==", key);
// console.log("value ==", value);
// return value;
// }
// return [];
// })[0];
// eslint-disable-next-line
for (const [key, value] of asArray) {
if (key.toLocaleLowerCase().indexOf(projectId.toLowerCase()) !== -1) {
currentFile = key;
break;
}
}
});
} else {
currentFile = offlineResource?.data?.value?.projects.filter((item) => {
if (item?.identifier.toLowerCase() === projectId.toLowerCase()) {
return item;
}
return null;
});
}
if (currentFile?.length > 0) {
const filecontent = await fs.readFileSync(path.join(folder, projectName, currentFile[0].path), 'utf8');
// const filecontent = await fs.readFileSync(path.join(folder, projectName, currentFile[0].path), 'utf8');
const filecontent = await fs.readFileSync(path.join(folder, projectName, isBurrito ? currentFile : currentFile[0].path), 'utf8');
// convert tsv to json
const headerArr = filecontent.split('\n')[0].split('\t');
let noteName;
Expand All @@ -111,21 +152,21 @@ export default function TranslationHelpsCard({
}

const json = filecontent.split('\n')
.map((file) => {
.map((line) => {
if (bvcType) {
const [Book, Chapter, Verse, ID, SupportReference, OrigQuote, Occurrence, GLQuote, OccurrenceNote] = file.split('\t');
const [Book, Chapter, Verse, ID, SupportReference, OrigQuote, Occurrence, GLQuote, OccurrenceNote] = line.split('\t');
return {
Book, Chapter, Verse, ID, SupportReference, OrigQuote, Occurrence, GLQuote, OccurrenceNote,
};
}
const Book = projectId;
const [ref, ID] = file.split('\t');
const [ref, ID] = line.split('\t');
const Chapter = ref.split(':')[0];
const Verse = ref.split(':')[1];
return {
Book, Chapter, Verse, ID, [noteName]: file.split('\t')[indexOfNote],
Book, Chapter, Verse, ID, [noteName]: line.split('\t')[indexOfNote],
};
}).filter((data) => data.Chapter === currentChapterVerse.chapter && data.Verse === currentChapterVerse.verse);
}).filter((data) => data.Chapter === `${currentChapterVerse.chapter }` && data.Verse === `${currentChapterVerse.verse }`);
setOfflineItemsDisable(false);
setOfflineItems(json);
}
Expand Down Expand Up @@ -200,7 +241,7 @@ export default function TranslationHelpsCard({
setOfflineItemsDisable(true);
setOfflineMarkdown(filecontent);
} else {
setOfflineMarkdown({ error: true, data: 'No Content Avaialble' });
setOfflineMarkdown({ error: true, data: 'No Content Available' });
}
}
});
Expand Down Expand Up @@ -247,7 +288,7 @@ export default function TranslationHelpsCard({
items = !offlineItemsDisable && offlineResource?.offline ? offlineItems : items;
markdown = offlineResource?.offline ? offlineMarkdown : markdown;

if (resourceId === 'tn' && items) {
if ((resourceId === 'tn' || resourceId === 'x-bcvnotes') && items) {
if (items[0]?.Note) {
items[0].Note = (items[0].Note).replace(/(<br>|\\n)/gm, '\n');
}
Expand All @@ -258,7 +299,7 @@ export default function TranslationHelpsCard({

return (
<>
{resourceId === 'tn' && (<TabSelector currentTab={currentTnTab} setCurrentTab={setCurrentTnTab} tabData={tnTabHeads} />)}
{(resourceId === 'tn' || resourceId === 'x-bcvnotes') && (<TabSelector currentTab={currentTnTab} setCurrentTab={setCurrentTnTab} tabData={tnTabHeads} />)}
{(markdown || items) ? (
<ReferenceCard
resourceId={resourceId}
Expand Down
Loading
Loading