Last active
August 24, 2022 23:07
-
-
Save temberature/7a02987f4f9a7c43dd0d0882542ef5bf to your computer and use it in GitHub Desktop.
rga client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> | |
<meta http-equiv="Content-Security-Policy" | |
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"> | |
<link href="./styles.css" rel="stylesheet"> | |
<title>Hello World!</title> | |
</head> | |
<body> | |
<!-- <video controls autoplay> | |
<source src="file:///Volumes/video/Subtitles/The Big Bang Theory Season 1-11 Complete 720p/The Big Bang Theory Season 1/The.Big.Bang.Theory.S01E17.The.Tangerine.Factor.1080p.BluRay.x264-CiNEFiLE.English.mkv" type="video/mp4"> | |
</video> --> | |
<div class="query"> | |
<input type="text" value="/usr/local/bin/rga 'intervene' --json -n -C 4 /Volumes/video/Subtitles/" /> | |
<button class="searchBtn">搜索</button> | |
</div> | |
<div class="multiChoice"> | |
<video data-start="10" data-end="20" controls autoplay> | |
<source src="file:///Volumes/video/Subtitles/The Big Bang Theory Season 1-11 Complete 720p/The Big Bang Theory Season 1/The.Big.Bang.Theory.S01E17.The.Tangerine.Factor.1080p.BluRay.x264-CiNEFiLE.English.mkv"> | |
</video> | |
<div class="subtitle">dawdaffawf</div> | |
</div> | |
<div class="matches"> | |
<div> | |
<div class="filename"> | |
The.Big.Bang.Theory.S09E16.The.Positive.Negative.Reaction.720p.BluRay.x264.Pahe.in.vtt | |
</div> | |
<ul> | |
<li> | |
<span class="line_number">403</span>:What, are you not h<span | |
class="query" | |
>app</span>y about this? | |
</li> | |
<li> | |
<span class="line_number">596</span>:so this doesn't h | |
<span class="query">app</span>en to us? | |
</li> | |
<li> | |
<span class="line_number">765</span>:all | |
<span class="query">App</span>le does | |
</li> | |
<li> | |
<span class="line_number">1320</span>:I | |
<span class="query">app</span>reciate this, but you really don-- | |
</li> | |
<li> | |
<span class="line_number">1383</span>:Well, I am so h | |
<span class="query">app</span>y | |
</li> | |
</ul> | |
</div> | |
</div> | |
<hr> | |
We are using Node.js <span id="node-version"></span>, | |
Chromium <span id="chrome-version"></span>, | |
and Electron <span id="electron-version"></span>. | |
<!-- You can also require other files to run in this process --> | |
<script src="./renderer.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Modules to control application life and create native browser window | |
const { app, BrowserWindow, ipcMain } = require('electron') | |
const path = require('path') | |
const { exec, spawn } = require("child_process"); | |
let win; | |
function createWindow() { | |
// Create the browser window. | |
const mainWindow = new BrowserWindow({ | |
width: 800, | |
height: 600, | |
webPreferences: { | |
preload: path.join(__dirname, 'preload.js'), | |
nodeIntegration: true, | |
contextIsolation: false, | |
webSecurity: true, | |
} | |
}) | |
// and load the index.html of the app. | |
mainWindow.loadFile('index.html') | |
// Open the DevTools. | |
mainWindow.webContents.openDevTools() | |
win = mainWindow; | |
} | |
// This method will be called when Electron has finished | |
// initialization and is ready to create browser windows. | |
// Some APIs can only be used after this event occurs. | |
app.whenReady().then(() => { | |
createWindow() | |
app.on('activate', function () { | |
// On macOS it's common to re-create a window in the app when the | |
// dock icon is clicked and there are no other windows open. | |
if (BrowserWindow.getAllWindows().length === 0) createWindow() | |
}) | |
}) | |
// Quit when all windows are closed, except on macOS. There, it's common | |
// for applications and their menu bar to stay active until the user quits | |
// explicitly with Cmd + Q. | |
app.on('window-all-closed', function () { | |
if (process.platform !== 'darwin') app.quit() | |
}) | |
// In this file you can include the rest of your app's specific main process | |
// code. You can also put them in separate files and require them here. | |
ipcMain.handle('my-invokable-ipc', async (event, ...args) => { | |
console.log(args) | |
var c = args[0].split(' '); | |
var command = c.shift(); | |
const process = await spawn(command, c, {shell: true}) | |
console.log(process); | |
let result = ''; | |
process.stdout.on('data', data => { | |
console.log(data); | |
result += data.toString(); | |
// do something with the data here | |
// win.webContents.send('asynchronous-message', data.toString()); | |
}) | |
// process.stdout.on('drain', () => { | |
// console.log(args) | |
// win.webContents.send('asynchronous-message', result); | |
// // final checks (e.g. - expect) go here | |
// }) | |
process.on('exit', () => { | |
console.log(args) | |
win.webContents.send('asynchronous-message', result); | |
// final checks (e.g. - expect) go here | |
}) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "american-role-adopt-oqmmz", | |
"productName": "american-role-adopt-oqmmz", | |
"description": "My Electron application description", | |
"keywords": [], | |
"main": "./main.js", | |
"version": "1.0.0", | |
"author": "tong", | |
"scripts": { | |
"start": "electron ." | |
}, | |
"dependencies": {}, | |
"devDependencies": { | |
"electron": "19.0.6" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// All of the Node.js APIs are available in the preload process. | |
// It has the same sandbox as a Chrome extension. | |
const { shell } = require('electron') | |
window.addEventListener('DOMContentLoaded', () => { | |
const replaceText = (selector, text) => { | |
const element = document.getElementById(selector) | |
if (element) element.innerText = text | |
} | |
for (const type of ['chrome', 'node', 'electron']) { | |
replaceText(`${type}-version`, process.versions[type]) | |
} | |
}) | |
// assuming $ is jQuery | |
document.addEventListener('click', function (event) { | |
const target = event.target; | |
if (target.nodeName === 'A') { | |
event.preventDefault(); | |
shell.openExternal(target.getAttribute('href')); | |
} | |
}); | |
document.addEventListener('loadedmetadata', function (event) { | |
console.log(event); | |
const target = event.target; | |
if (target.nodeName === 'VIDEO') { | |
event.preventDefault(); | |
target.currentTime = target.getAttribute('data-start'); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This file is required by the index.html file and will | |
// be executed in the renderer process for that window. | |
// No Node.js APIs are available in this process because | |
// `nodeIntegration` is turned off. Use `preload.js` to | |
// selectively enable features needed in the rendering | |
// process. | |
const { app, BrowserWindow, ipcRenderer } = require('electron') | |
var $ = document.querySelectorAll; | |
document.querySelectorAll('.searchBtn')[0].addEventListener('click', function (t, e) { | |
console.log(t, e); | |
(async () => { | |
document.querySelectorAll('.matches')[0].innerHTML = ''; | |
const result = await ipcRenderer.invoke('my-invokable-ipc', document.querySelectorAll('input')[0].value) | |
// ... | |
})() | |
const transaction = db.transaction(["customers"]); | |
const objectStore = transaction.objectStore("customers"); | |
const request = objectStore.get(1); | |
request.onerror = (event) => { | |
// Handle errors! | |
}; | |
request.onsuccess = (event) => { | |
// Do something with the request.result! | |
console.log(request.result); | |
var record = request.result; | |
var multiChoice = createElementFromHTML(`<div class="multiChoice"> | |
<video data-start="${record.start}" data-end="${record.end}" autoplay> | |
<source src="file://${record.path}"> | |
<source src="file://${record.path.replace('mp4', 'mkv')}"> | |
</video> | |
<div class="subtitle">${record.subtitle}<div class="span">${record.span}</div></div> | |
</div>`)[0]; | |
multiChoice.querySelectorAll('video').forEach(video => { | |
var start = +video.getAttribute('data-start') + 5, end = +video.getAttribute('data-end') + 5; | |
video.addEventListener('loadedmetadata', function (event) { | |
console.log(event); | |
video.currentTime = start; | |
}); | |
video.addEventListener('timeupdate', (event) => { | |
console.log(event); | |
if(video.currentTime > end) { | |
video.currentTime = start; | |
// video.play(); | |
} | |
console.log('The currentTime attribute has been updated. Again.'); | |
}); | |
}) | |
document.querySelectorAll('.multiChoice')[0].replaceWith(multiChoice) | |
}; | |
}) | |
const dbName = "the_name"; | |
let db; | |
const request = indexedDB.open(dbName, 2); | |
request.onerror = (event) => { | |
// Handle errors. | |
}; | |
request.onsuccess = (event) => { | |
db = event.target.result; | |
}; | |
request.onupgradeneeded = (event) => { | |
db = event.target.result; | |
// Create an objectStore to hold information about our customers. We're | |
// going to use "ssn" as our key path because it's guaranteed to be | |
// unique - or at least that's what I was told during the kickoff meeting. | |
const objectStore = db.createObjectStore("customers", { keyPath: "id", autoIncrement: true }); | |
// Create an index to search customers by name. We may have duplicates | |
// so we can't use a unique index. | |
objectStore.createIndex("subtitle", "subtitle", { unique: false }); | |
// Create an index to search customers by email. We want to ensure that | |
// no two customers have the same email, so use a unique index. | |
objectStore.createIndex("path", "path", { unique: false }); | |
}; | |
ipcRenderer.on('asynchronous-message', function (evt, message) { | |
console.log(message); // Returns: {'SAVED': 'File Saved'} | |
main(message) | |
}); | |
function main(message) { | |
var result = readJsonLines(message) | |
console.log(result); | |
if (result[0].type === 'summary') { | |
return; | |
} | |
var html = `${(function () { | |
return result.reduce((p, c) => { | |
// console.log(c); | |
let html; | |
if (c.type == 'begin') { | |
html = `<div><div class="filename"> | |
${c.data.path.text} | |
</div><ul>` | |
} else if (c.type == 'end') { | |
html = `</ul></div>`; | |
} else if (c.type == 'summary') { | |
html = ''; | |
} else { | |
var text = c.data.lines.text.replace(/(\d\d):(\d\d):(\d\d).(\d\d\d)/g, function (match, p1, p2, p3) { | |
console.log(match, p1, p2, p3); | |
let location = (+p1 * 60 * 60) + (+p2 * 60) + (+p3); | |
location = location - 5 > 0 ? location - 5 : 0; | |
return `<a href="sioyek://${c.data.path.text.replace('srt', 'mp4')}#${location}">${match}</a><button class="saveBtn">Save</button>` | |
}) | |
text = text.replace(/Page (\d*)/g, function (match, p1) { | |
return `<a href="sioyek://${c.data.path.text}#${p1}">${match}</a>` | |
}) | |
html = `<li> | |
<span class="line_number">${c.data.line_number}</span> | |
:<span class="text">${c.data.submatches.length > 0 ? text.replace(c.data.submatches[0].match.text, `<span class="query">${c.data.submatches[0].match.text}</span>`) : text}</span> | |
</li>` | |
} | |
return p + html; | |
}, ''); | |
})()}` | |
console.log(html); | |
if (html == '') { | |
return; | |
} | |
var nodes = createElementFromHTML(html); | |
// nodes = nodes.length > 0 ? nodes : [nodes]; | |
nodes.forEach(node => { | |
node.querySelectorAll('.saveBtn').forEach(function (saveBtn) { | |
saveBtn.addEventListener('click', function (e) { | |
console.log(e); | |
var container = this.parentNode.parentNode; | |
var span = container.querySelector('.text').innerHTML.replaceAll('<button class="saveBtn">Save</button>', ''); | |
var path, start, end; | |
container.querySelectorAll('a').forEach(function (link, index) { | |
var parts = link.getAttribute('href').split('#'); | |
path = parts[0].replace('sioyek://', ''); | |
if (index === 0) { | |
start = +parts[1]; | |
} else { | |
end = +parts[1]; | |
} | |
}) | |
var subtitle = ''; | |
container = container.nextElementSibling; | |
while (container && container.querySelector('.text').innerText.replace(' ', '') != '') { | |
subtitle += ' ' + container.querySelector('.text').innerText; | |
container = container.nextElementSibling; | |
} | |
console.log(span, path, start, end, subtitle); | |
const customerObjectStore = db.transaction("customers", "readwrite").objectStore("customers"); | |
customerObjectStore.add({ | |
subtitle, | |
path, | |
span, start, end, | |
}); | |
this.innerText = 'success'; | |
}) | |
}) | |
setTimeout(function () { | |
document.querySelectorAll('.matches')[0].appendChild(node); | |
}, 10); | |
}) | |
} | |
function readJsonLines(jsonl) { | |
return jsonl.split(/(?<=})\n(?={)/).map((jsonStr, index) => { | |
// console.log(jsonStr); | |
if (jsonStr[jsonStr.length - 1] !== '}') { | |
jsonStr = jsonStr.slice(0, -1) | |
} | |
const match = JSON.parse(jsonStr.replaceAll('\n', '\\n').replaceAll('\r', '\\r')); | |
// console.log(index, match); | |
return match; | |
}); | |
} | |
function createElementFromHTML(htmlString) { | |
var div = document.createElement('div'); | |
div.innerHTML = htmlString.trim(); | |
// Change this to div.childNodes to support multiple top-level nodes. | |
return div.childNodes; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* styles.css */ | |
/* Add styles here to customize the appearance of your app */ | |
.query { | |
margin: 50px auto; | |
text-align: center; | |
} | |
input { | |
width: 50%; | |
} | |
.multiChoice { | |
position: relative; | |
} | |
video { | |
width: 100%; | |
} | |
.subtitle { | |
position: absolute; | |
bottom: 0; | |
/* transform: translateY(10px); */ | |
/* padding-top: 5vw; */ | |
color: white; | |
font-size: 8vw; | |
text-align: center; | |
vertical-align: middle; | |
width: 100%; | |
height: 100%; | |
pointer-events: none; | |
background: rgba(125, 125, 125, 0.7); | |
} | |
.span { | |
font-size: 2vw; | |
pointer-events: all; | |
} | |
.filename { | |
color: rgb(223, 82, 210) | |
} | |
.line_number { | |
color: rgb(4, 188, 68) | |
} | |
.query { | |
color: rgb(199, 53, 39) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment