Skip to content

Commit

Permalink
Merge branch 'master' into grc-deinflection
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanVukovic99 committed Feb 25, 2025
2 parents 90054eb + 3ca2800 commit 12b53ff
Show file tree
Hide file tree
Showing 26 changed files with 410 additions and 38 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@ Yomitan uses several third-party libraries to function.

## Attribution

`button.mp3` is provided by [UNIVERSFIELD](https://pixabay.com/sound-effects/error-8-206492/) and licensed under the [Pixabay Content License](https://pixabay.com/service/license-summary/).
`fallback-bloop.mp3` is provided by [UNIVERSFIELD](https://pixabay.com/sound-effects/error-8-206492/) and licensed under the [Pixabay Content License](https://pixabay.com/service/license-summary/).
3 changes: 3 additions & 0 deletions dev/data/manifest-variants.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
"service_worker": "sw.js",
"type": "module"
},
"omnibox": {
"keyword": "yomi"
},
"content_scripts": [
{
"run_at": "document_idle",
Expand Down
9 changes: 9 additions & 0 deletions ext/css/display.css
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,15 @@ button.footer-notification-close-button {
:root[data-anki-enabled=false] .action-button[data-action=save-note] {
display: none;
}

:root[data-average-frequency=true] .frequency-group-item:not([data-details='Average']) {
display: none;
}

:root[data-average-frequency=false] .frequency-group-item[data-details='Average'] {
display: none;
}

:root[data-audio-enabled=false] .action-button[data-action=play-audio] {
display: none;
}
Expand Down
Binary file removed ext/data/audio/button.mp3
Binary file not shown.
Binary file added ext/data/audio/fallback-bloop.mp3
Binary file not shown.
Binary file added ext/data/audio/fallback-click.mp3
Binary file not shown.
14 changes: 10 additions & 4 deletions ext/data/schemas/options-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"showGuide",
"enableContextMenuScanSelected",
"compactTags",
"averageFrequency",
"glossaryLayoutMode",
"mainDictionary",
"popupTheme",
Expand Down Expand Up @@ -236,6 +237,10 @@
"type": "boolean",
"default": false
},
"averageFrequency": {
"type": "boolean",
"default": false
},
"glossaryLayoutMode": {
"type": "string",
"enum": ["default", "compact"],
Expand Down Expand Up @@ -391,7 +396,7 @@
"enabled",
"volume",
"autoPlay",
"playFallbackSound",
"fallbackSoundType",
"sources"
],
"properties": {
Expand All @@ -409,9 +414,10 @@
"type": "boolean",
"default": false
},
"playFallbackSound": {
"type": "boolean",
"default": true
"fallbackSoundType": {
"type": "string",
"enum": ["none", "click", "bloop"],
"default": "click"
},
"sources": {
"type": "array",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{#*inline "sentence-furigana-plain"}}
{{~#if definition.cloze~}}
{{~#if (hasMedia "textFuriganaPlain" definition.cloze.sentence)~}}
{{{getMedia "textFuriganaPlain" definition.cloze.sentence escape=false}}}
{{~else~}}
{{{definition.cloze.sentence}}}
{{~/if~}}
{{~/if~}}
{{/inline}}
10 changes: 10 additions & 0 deletions ext/data/templates/default-anki-field-templates.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -472,4 +472,14 @@
{{~/if~}}
{{/inline}}

{{#*inline "sentence-furigana-plain"}}
{{~#if definition.cloze~}}
{{~#if (hasMedia "textFuriganaPlain" definition.cloze.sentence)~}}
{{{getMedia "textFuriganaPlain" definition.cloze.sentence escape=false}}}
{{~else~}}
{{{definition.cloze.sentence}}}
{{~/if~}}
{{~/if~}}
{{/inline}}

{{~> (lookup . "marker") ~}}
14 changes: 14 additions & 0 deletions ext/js/background/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,8 @@ export class Backend {

this._setupContextMenu(options);

this._attachOmniboxListener();

void this._accessibilityController.update(this._getOptionsFull(false));

this._sendMessageAllTabsIgnoreResponse({action: 'applicationOptionsUpdated', params: {source}});
Expand Down Expand Up @@ -1404,6 +1406,18 @@ export class Backend {
}
}

/** */
_attachOmniboxListener() {
try {
chrome.omnibox.onInputEntered.addListener((text) => {
const newURL = 'search.html?query=' + encodeURIComponent(text);
void chrome.tabs.create({url: newURL});
});
} catch (e) {
log.error(e);
}
}

/**
* @param {boolean} useSchema
* @returns {import('settings').Options}
Expand Down
26 changes: 24 additions & 2 deletions ext/js/data/anki-note-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,9 @@ export class AnkiNoteBuilder {
break;
}
if (data !== null) {
const value = this._createFuriganaHtml(data, readingMode);
results.push({text, readingMode, details: {value}});
const valueHtml = this._createFuriganaHtml(data, readingMode);
const valuePlain = this._createFuriganaPlain(data, readingMode);
results.push({text, readingMode, detailsHtml: {value: valueHtml}, detailsPlain: {value: valuePlain}});
}
}
return results;
Expand Down Expand Up @@ -551,6 +552,27 @@ export class AnkiNoteBuilder {
return result;
}

/**
* @param {import('api').ParseTextLine[]} data
* @param {?import('anki-templates').TextFuriganaReadingMode} readingMode
* @returns {string}
*/
_createFuriganaPlain(data, readingMode) {
let result = '';
for (const term of data) {
for (const {text, reading} of term) {
if (reading.length > 0) {
const reading2 = this._convertReading(reading, readingMode);
result += ` ${text}[${reading2}]`;
} else {
result += text;
}
}
}
result = result.substring(1);
return result;
}

/**
* @param {string} reading
* @param {?import('anki-templates').TextFuriganaReadingMode} readingMode
Expand Down
2 changes: 2 additions & 0 deletions ext/js/data/anki-template-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function getStandardFieldMarkers(type) {
'popup-selection-text',
'sentence',
'sentence-furigana',
'sentence-furigana-plain',
'tags',
'url',
];
Expand Down Expand Up @@ -91,6 +92,7 @@ export function getStandardFieldMarkers(type) {
'popup-selection-text',
'sentence',
'sentence-furigana',
'sentence-furigana-plain',
'stroke-count',
'tags',
'url',
Expand Down
32 changes: 32 additions & 0 deletions ext/js/data/options-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,9 @@ export class OptionsUtil {
this._updateVersion57,
this._updateVersion58,
this._updateVersion59,
this._updateVersion60,
this._updateVersion61,
this._updateVersion62,
];
/* eslint-enable @typescript-eslint/unbound-method */
if (typeof targetVersion === 'number' && targetVersion < result.length) {
Expand Down Expand Up @@ -1594,6 +1597,35 @@ export class OptionsUtil {
}
}

/**
* - Replaced audio.playFallbackSound with audio.fallbackSoundType
* @type {import('options-util').UpdateFunction}
*/
async _updateVersion60(options) {
for (const profile of options.profiles) {
profile.options.audio.fallbackSoundType = profile.options.audio.playFallbackSound ? 'click' : 'none';
delete profile.options.audio.playFallbackSound;
}
}

/**
* - Added sentence-furigana-plain handlebar
* @type {import('options-util').UpdateFunction}
*/
async _updateVersion61(options) {
await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v61.handlebars');
}

/**
* - Added options.general.averageFrequency
* @type {import('options-util').UpdateFunction}
*/
async _updateVersion62(options) {
for (const profile of options.profiles) {
profile.options.general.averageFrequency = false;
}
}

/**
* @param {string} url
* @returns {Promise<chrome.tabs.Tab>}
Expand Down
89 changes: 87 additions & 2 deletions ext/js/dictionary/dictionary-data-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,23 +83,108 @@ export function groupTermFrequencies(dictionaryEntry, dictionaryInfo) {
}

const results = [];

/** @type {import('dictionary').AverageFrequencyListGroup} */
const averages = new Map();
for (const [dictionary, map2] of map1.entries()) {
/** @type {import('dictionary-data-util').TermFrequency[]} */
const frequencies = [];
const dictionaryAlias = aliasMap.get(dictionary) ?? dictionary;
for (const {term, reading, values} of map2.values()) {
frequencies.push({
const termFrequency = {
term,
reading,
values: [...values.values()],
});
};
frequencies.push(termFrequency);

const averageFrequencyData = makeAverageFrequencyData(termFrequency, averages.get(term));
if (averageFrequencyData) {
averages.set(term, averageFrequencyData);
}
}
const currentDictionaryInfo = dictionaryInfo.find(({title}) => title === dictionary);
const freqCount = currentDictionaryInfo?.counts?.termMeta.freq ?? 0;
results.push({dictionary, frequencies, dictionaryAlias, freqCount});
}

results.push({dictionary: 'Average', frequencies: makeAverageFrequencyArray(averages), dictionaryAlias: 'Average', freqCount: 1});

return results;
}

/**
* @param {import('dictionary-data-util').TermFrequency} termFrequency
* @param {import('dictionary').AverageFrequencyListTerm | undefined} averageTerm
* @returns {import('dictionary').AverageFrequencyListTerm | undefined}
*/
function makeAverageFrequencyData(termFrequency, averageTerm) {
const valuesArray = [...termFrequency.values.values()];
const newReading = termFrequency.reading ?? '';

/** @type {import('dictionary').AverageFrequencyListTerm} */
const termMap = typeof averageTerm === 'undefined' ? new Map() : averageTerm;

const frequencyData = termMap.get(newReading) ?? {currentAvg: 1, count: 0};

if (valuesArray[0].frequency === null) { return; }

frequencyData.currentAvg = frequencyData.count / frequencyData.currentAvg + 1 / valuesArray[0].frequency;
frequencyData.currentAvg = (frequencyData.count + 1) / frequencyData.currentAvg;
frequencyData.count += 1;

termMap.set(newReading, frequencyData);
return termMap;
}

/**
* @param {import('dictionary').AverageFrequencyListGroup} averages
* @returns {import('dictionary-data-util').TermFrequency[]}
*/
function makeAverageFrequencyArray(averages) {
// Merge readings if one is null and there's only two readings
// More than one non-null reading cannot be merged since it cannot be determined which reading to merge with
for (const currentTerm of averages.keys()) {
const readingsMap = averages.get(currentTerm);
if (!readingsMap) { continue; } // Skip if readingsMap is undefined

const readingArray = [...readingsMap.keys()];
const nullIndex = readingArray.indexOf('');

if (readingArray.length === 2 && nullIndex >= 0) {
const key1 = readingArray[0];
const key2 = readingArray[1];

const value1 = readingsMap.get(key1);
const value2 = readingsMap.get(key2);

if (!value1 || !value2) { continue; } // Skip if any value is undefined

const avg1 = value1.currentAvg;
const count1 = value1.count;
const avg2 = value2.currentAvg;
const count2 = value2.count;

const newcount = count1 + count2;
const newavg = newcount / (count1 / avg1 + count2 / avg2);

const validKey = nullIndex === 0 ? key2 : key1;
readingsMap.set(validKey, {currentAvg: newavg, count: newcount});
readingsMap.delete('');
}
}

// Convert averages Map back to array format
return [...averages.entries()].flatMap(([termName, termMap]) => [...termMap.entries()].map(([readingName, data]) => ({
term: termName,
reading: readingName,
values: [{
frequency: Math.round(data.currentAvg),
displayValue: Math.round(data.currentAvg).toString(),
}],
})));
}

/**
* @param {import('dictionary').KanjiFrequency[]} sourceFrequencies
* @param {import('dictionary-importer').Summary[]} dictionaryInfo
Expand Down
10 changes: 5 additions & 5 deletions ext/js/display/display-audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export class DisplayAudio {
this._playbackVolume = 1;
/** @type {boolean} */
this._autoPlay = false;
/** @type {boolean} */
this._playFallbackSound = true;
/** @type {import('settings').FallbackSoundType} */
this._fallbackSoundType = 'none';
/** @type {?import('core').Timeout} */
this._autoPlayAudioTimer = null;
/** @type {number} */
Expand Down Expand Up @@ -170,10 +170,10 @@ export class DisplayAudio {
_onOptionsUpdated({options}) {
const {
general: {language},
audio: {enabled, autoPlay, playFallbackSound, volume, sources},
audio: {enabled, autoPlay, fallbackSoundType, volume, sources},
} = options;
this._autoPlay = enabled && autoPlay;
this._playFallbackSound = playFallbackSound;
this._fallbackSoundType = fallbackSoundType;
this._playbackVolume = Number.isFinite(volume) ? Math.max(0, Math.min(1, volume / 100)) : 1;

/** @type {Set<import('settings').AudioSourceType>} */
Expand Down Expand Up @@ -454,7 +454,7 @@ export class DisplayAudio {
const sourceIndex = sources.indexOf(source);
title = `From source ${1 + sourceIndex}: ${source.name}`;
} else {
audio = this._audioSystem.getFallbackAudio(this._playFallbackSound);
audio = this._audioSystem.getFallbackAudio(this._fallbackSoundType);
title = 'Could not find audio';
}

Expand Down
1 change: 1 addition & 0 deletions ext/js/display/display.js
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,7 @@ export class Display extends EventDispatcher {
data.resultOutputMode = `${options.general.resultOutputMode}`;
data.glossaryLayoutMode = `${options.general.glossaryLayoutMode}`;
data.compactTags = `${options.general.compactTags}`;
data.averageFrequency = `${options.general.averageFrequency}`;
data.frequencyDisplayMode = `${options.general.frequencyDisplayMode}`;
data.termDisplayMode = `${options.general.termDisplayMode}`;
data.enableSearchTags = `${options.scanning.enableSearchTags}`;
Expand Down
Loading

0 comments on commit 12b53ff

Please sign in to comment.