Skip to content

Commit b72324b

Browse files
authored
🔀 Merge pull request #410 from richardfrost/build_target_audio_sites
Customize Web Audio Sites for Build Targets
2 parents bbeda89 + b626dd5 commit b72324b

File tree

11 files changed

+377
-261
lines changed

11 files changed

+377
-261
lines changed

bin/postbuild.mjs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ import {
1313

1414
let buildData;
1515

16+
function appleBuild(updateBuildNumber) {
17+
const files = [
18+
path.join('dist', 'img', 'donate.gif'),
19+
path.join('dist', 'img', 'patreon-small.png'),
20+
path.join('dist', 'img', 'patreon.png'),
21+
];
22+
23+
removeOptionPageBookmarklet();
24+
removeOptionPageDonations();
25+
removeFiles(files);
26+
27+
if (buildData.release) {
28+
updateSafariXcodeVersion(updateBuildNumber);
29+
}
30+
}
31+
1632
function common() {
1733
handleManifestVersion();
1834
handleVersion();
@@ -73,6 +89,11 @@ function handleVersion() {
7389
}
7490
}
7591

92+
function iOSBuild() {
93+
const updateBuildNumber = false;
94+
appleBuild(updateBuildNumber);
95+
}
96+
7697
function main() {
7798
buildData = loadJSONFile(buildFilePath);
7899

@@ -83,6 +104,10 @@ function main() {
83104
firefoxBuild();
84105
}
85106

107+
if (buildData.target == 'ios') {
108+
iOSBuild();
109+
}
110+
86111
if (buildData.target == 'safari') {
87112
safariBuild();
88113
}
@@ -115,32 +140,24 @@ function removeOptionPageDonations() {
115140
}
116141

117142
function safariBuild() {
118-
const files = [
119-
path.join('dist', 'img', 'donate.gif'),
120-
path.join('dist', 'img', 'patreon-small.png'),
121-
path.join('dist', 'img', 'patreon.png'),
122-
];
123-
124-
removeOptionPageBookmarklet();
125-
removeOptionPageDonations();
126-
removeFiles(files);
127-
if (buildData.release) {
128-
updateSafariXcodeVersion();
129-
}
143+
const updateBuildNumber = true;
144+
appleBuild(updateBuildNumber);
130145
}
131146

132-
function updateSafariXcodeVersion() {
147+
function updateSafariXcodeVersion(updateBuildNumber) {
133148
const projectFilePath = path.join('safari', 'Advanced Profanity Filter.xcodeproj', 'project.pbxproj');
134149
const projectFileText = fse.readFileSync(projectFilePath).toString();
135150
let updatedProjectFileText = projectFileText.replace(/MARKETING_VERSION = \d+\.\d+\.\d+;$/gm, `MARKETING_VERSION = ${buildData.version};`);
136151

137152
// Increment the build version when running a Safari release
138153
// macOS Apps require the build number to be larger than the previous build number
139154
// https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleversion
140-
const buildVersionMatch = projectFileText.match(/CURRENT_PROJECT_VERSION = (?<buildNumber>\d+);/);
141-
if (buildVersionMatch.groups) {
142-
const newBuildNumber = parseInt(buildVersionMatch.groups.buildNumber) + 1;
143-
updatedProjectFileText = updatedProjectFileText.replace(/CURRENT_PROJECT_VERSION = (?<buildNumber>\d+);/gm, `CURRENT_PROJECT_VERSION = ${newBuildNumber};`);
155+
if (updateBuildNumber) {
156+
const buildVersionMatch = projectFileText.match(/CURRENT_PROJECT_VERSION = (?<buildNumber>\d+);/);
157+
if (buildVersionMatch.groups) {
158+
const newBuildNumber = parseInt(buildVersionMatch.groups.buildNumber) + 1;
159+
updatedProjectFileText = updatedProjectFileText.replace(/CURRENT_PROJECT_VERSION = (?<buildNumber>\d+);/gm, `CURRENT_PROJECT_VERSION = ${newBuildNumber};`);
160+
}
144161
}
145162

146163
if (projectFileText !== updatedProjectFileText) {

bin/prebuild.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ function firefoxBuild() {
3434
data.target = 'firefox';
3535
}
3636

37+
function iOSBuild() {
38+
data.target = 'ios';
39+
data.config.muteMethod = 2; // Constants.MUTE_METHODS.VIDEO_MUTE;
40+
}
41+
3742
function main() {
3843
const argv = parseArgv(process.argv);
3944
if (argv.count >= 2 && argv.count <= 4) {
@@ -66,6 +71,9 @@ function main() {
6671
case '--firefox':
6772
firefoxBuild();
6873
break;
74+
case '--ios':
75+
iOSBuild();
76+
break;
6977
case '--manifestV2':
7078
manifestV2Build();
7179
break;
@@ -109,6 +117,7 @@ function targetFromData() {
109117
return `--manifestV${data.manifestVersion}`;
110118
case 'bookmarklet':
111119
case 'firefox:':
120+
case 'ios':
112121
case 'safari':
113122
return `--${data.target}`;
114123
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"homepage": "https://github.com/richardfrost/AdvancedProfanityFilter#readme",
2020
"scripts": {
2121
"build:firefox": "node bin/prebuild.mjs --firefox && npm run build",
22+
"build:ios": "node bin/prebuild.mjs --ios && npm run build",
2223
"build:libs": "tsc -p ./src/script/lib/tsconfig.json",
2324
"build:safari": "node bin/prebuild.mjs --safari && npm run build",
2425
"build:static": "node bin/copy-static.mjs",
@@ -43,6 +44,7 @@
4344
"release:all": "npm run release:mv2 && npm run release:mv3 && npm run release:firefox",
4445
"release:build": "npm run build:static && webpack --config bin/webpack.config.js",
4546
"release:firefox": "npm run package:firefox",
47+
"release:ios": "npm run clean && node bin/prebuild.mjs --release --ios && npm run release:build",
4648
"release:safari": "npm run clean && node bin/prebuild.mjs --release --safari && npm run release:build",
4749
"release:mv2": "npm run package:mv2",
4850
"release:mv3": "npm run package:mv3",

src/script/lib/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import { upperCaseFirst } from './helper';
44
export default class Constants {
55
// Named Constants
66
static readonly ALL_WORDS_WORDLIST_ID = 0;
7+
static readonly BUILD_TARGET_BOOKMARKLET = 'bookmarklet';
8+
static readonly BUILD_TARGET_CHROME = 'chrome';
9+
static readonly BUILD_TARGET_FIREFOX = 'firefox';
10+
static readonly BUILD_TARGET_IOS = 'ios';
11+
static readonly BUILD_TARGET_SAFARI = 'safari';
712
static readonly DOMAIN_MODES = { NORMAL: 0, ADVANCED: 1, DEEP: 2 };
813
static readonly FALSE = 0;
914
static readonly FILTER_METHODS = { CENSOR: 0, SUBSTITUTE: 1, REMOVE: 2, OFF: 3 };

src/script/lib/globals.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ interface AudioRule {
33
_dynamic?: boolean; // [Dynamic] Set to true on a dynamic rule
44
apfCaptions?: boolean; // [Cue] Display an HTML version of the caption/subtitle text: Requires videoCueHideCues = true
55
apfCaptionsSelector?: string; // [Cue] Selector for container that will hold the custom HTML captions
6+
buildTarget?: string; // [All] Only allow rule to run on a specific buildTarget
67
checkInterval?: number; // [Watcher] Set a custom watch interval (in ms, Default: 20)
78
className?: string; // [Element] node.className.includes()
89
containsSelector?: string; // [Element] node.querySelector() [Not commonly used]
@@ -50,6 +51,10 @@ interface AudioRule {
5051
videoSelector?: string; // [Cue,Watcher] Selector for video, also used for volume muteMethod (Default: 'video')
5152
}
5253

54+
interface AudioSites {
55+
[site: string]: AudioRule[];
56+
}
57+
5358
interface BackgroundData {
5459
disabledTab?: boolean;
5560
}
@@ -60,6 +65,11 @@ interface BackgroundStorage {
6065
};
6166
}
6267

68+
interface BuildTargetSites {
69+
disabledSites: string[];
70+
sites: AudioSites;
71+
}
72+
6373
interface ConfirmModalSettings {
6474
backup?: boolean;
6575
content?: string;

src/script/lib/helper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ export function booleanToNumber(value: boolean): number {
44
return value ? Constants.TRUE : Constants.FALSE;
55
}
66

7+
export function cloneWithJSON(object) {
8+
return JSON.parse(JSON.stringify(object));
9+
}
10+
711
/* istanbul ignore next */
812
export function dynamicList(list: string[], select: HTMLSelectElement, upperCaseFirstChar: boolean = false, title?: string) {
913
removeChildren(select);

src/script/optionPage.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Domain from './domain';
55
import OptionAuth from './optionAuth';
66
import DataMigration from './dataMigration';
77
import Bookmarklet from './bookmarklet';
8-
import WebAudioSites from './webAudioSites';
8+
import WebAudio from './webAudio';
99
import Logger from './lib/logger';
1010
import {
1111
booleanToNumber,
@@ -26,6 +26,7 @@ export default class OptionPage {
2626
darkModeButton: Element;
2727
lightModeButton: Element;
2828
prefersDarkScheme: boolean;
29+
supportedAudioSites: AudioSites;
2930
themeElements: Element[];
3031

3132
static readonly activeClass = 'w3-flat-belize-hole';
@@ -1711,7 +1712,7 @@ export default class OptionPage {
17111712
const select = document.querySelector('#supportedAudioSitesModal select#siteSelect') as HTMLSelectElement;
17121713
const textArea = document.querySelector('#supportedAudioSitesModal div#modalContentRight textarea') as HTMLTextAreaElement;
17131714
const config = {};
1714-
config[select.value] = WebAudioSites.sites[select.value];
1715+
config[select.value] = this.supportedAudioSites[select.value];
17151716
textArea.textContent = JSON.stringify(config, null, 2);
17161717
}
17171718

@@ -1722,7 +1723,8 @@ export default class OptionPage {
17221723
const select = contentLeft.querySelector('#siteSelect') as HTMLSelectElement;
17231724
removeChildren(select);
17241725

1725-
const sortedSites = Domain.sortedKeys(WebAudioSites.sites);
1726+
this.supportedAudioSites = WebAudio.supportedSites();
1727+
const sortedSites = Domain.sortedKeys(this.supportedAudioSites);
17261728
sortedSites.forEach((site) => {
17271729
const optionElement = document.createElement('option');
17281730
optionElement.value = site;

src/script/popup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Constants from './lib/constants';
22
import { dynamicList } from './lib/helper';
3-
import WebAudioSites from './webAudioSites';
3+
import WebAudio from './webAudio';
44
import WebConfig from './webConfig';
55
import Domain from './domain';
66
import Page from './page';
@@ -137,7 +137,7 @@ class Popup {
137137
dynamicList(wordlists, wordlistSelect);
138138
wordlistSelect.selectedIndex = wordlistIndex;
139139
if (this.cfg.muteAudio) {
140-
this.audioSiteKeys = Object.keys(WebAudioSites.combineSites(this.cfg.customAudioSites));
140+
this.audioSiteKeys = Object.keys(WebAudio.supportedAndCustomSites(this.cfg.customAudioSites));
141141
if (this.audioSiteKeys.includes(this.domain.cfgKey)) {
142142
audioPage = true;
143143
const audioWordlistIndex = this.domain.audioWordlistId >= 0 ? this.domain.audioWordlistId + 1 : 0;

src/script/webAudio.ts

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Constants from './lib/constants';
22
import WebFilter from './webFilter';
33
import BookmarkletFilter from './bookmarkletFilter';
4-
import WebAudioSites from './webAudioSites';
4+
import { defaultTargetConfig, iOSTargetConfig, safariTargetConfig, supportedSites } from './webAudioSites';
55
import {
66
getElement,
77
getElements,
@@ -30,7 +30,7 @@ export default class WebAudio {
3030
lastProcessedText: string;
3131
muted: boolean;
3232
rules: AudioRule[];
33-
sites: { [site: string]: AudioRule[] };
33+
sites: AudioSites;
3434
siteKey: string;
3535
supportedPage: boolean;
3636
unmuteTimeout: number;
@@ -67,6 +67,53 @@ export default class WebAudio {
6767
videoCueLanguage: 'language',
6868
};
6969

70+
static getBuildTargetConfig() {
71+
switch (WebConfig.BUILD.target) {
72+
case Constants.BUILD_TARGET_IOS:
73+
return iOSTargetConfig;
74+
case Constants.BUILD_TARGET_SAFARI:
75+
return safariTargetConfig;
76+
default:
77+
return defaultTargetConfig;
78+
}
79+
}
80+
81+
static removeUnsupportedSites(sites: AudioSites) {
82+
Object.keys(sites).forEach((siteKey) => {
83+
// Ensure site rules is an array
84+
const siteRules = sites[siteKey];
85+
if (!Array.isArray(siteRules)) {
86+
sites[siteKey] = [siteRules];
87+
}
88+
89+
// Remove any rules with a buildTarget that doesn't match
90+
sites[siteKey] = sites[siteKey].filter((rule) => {
91+
return rule.buildTarget == null || rule.buildTarget == WebConfig.BUILD.target;
92+
});
93+
});
94+
95+
// Remove sites without rules
96+
Object.keys(sites).forEach((siteKey) => {
97+
if (sites[siteKey].length == 0) {
98+
delete sites[siteKey];
99+
}
100+
});
101+
}
102+
103+
static supportedSites(removeUnsupported: boolean = true): AudioSites {
104+
const buildTargetConfig = WebAudio.getBuildTargetConfig();
105+
const siteConfig = Object.assign({}, supportedSites, buildTargetConfig.sites);
106+
buildTargetConfig.disabledSites.forEach((disabledSite) => { delete siteConfig[disabledSite]; });
107+
if (removeUnsupported) { WebAudio.removeUnsupportedSites(siteConfig); }
108+
return siteConfig;
109+
}
110+
111+
static supportedAndCustomSites(customConfig: AudioSites) {
112+
const combinedSites = Object.assign({}, WebAudio.supportedSites(false), customConfig);
113+
WebAudio.removeUnsupportedSites(combinedSites);
114+
return combinedSites;
115+
}
116+
70117
constructor(filter: WebFilter | BookmarkletFilter) {
71118
this.filter = filter;
72119
logger.setLevel(this.filter.cfg.loggingLevel);
@@ -84,7 +131,7 @@ export default class WebAudio {
84131
) {
85132
filter.cfg.customAudioSites = {};
86133
}
87-
this.sites = WebAudioSites.combineSites(filter.cfg.customAudioSites);
134+
this.sites = WebAudio.supportedAndCustomSites(filter.cfg.customAudioSites);
88135
this.volume = 1;
89136
this.wordlistId = filter.audioWordlistId;
90137
this.youTubeAutoSubsMax = filter.cfg.youTubeAutoSubsMax * 1000;
@@ -95,7 +142,6 @@ export default class WebAudio {
95142
this.siteKey = this.getSiteKey();
96143
this.rules = this.sites[this.siteKey];
97144
if (this.rules) {
98-
if (!Array.isArray(this.rules)) { this.rules = [this.rules]; }
99145
this.rules.forEach((rule) => { this.initRule(rule); });
100146
if (this.enabledRuleIds.length > 0) {
101147
this.supportedPage = true;
@@ -448,6 +494,10 @@ export default class WebAudio {
448494
this.initWatcherRule(rule);
449495
if (!rule.disabled) { this.watcherRuleIds.push(ruleId); }
450496
break;
497+
case 'ytauto':
498+
// This rule doesn't run like other rules, and is marked as disabled
499+
rule.disabled = true;
500+
break;
451501
}
452502
if (!rule.disabled) {
453503
this.enabledRuleIds.push(ruleId);
@@ -488,7 +538,8 @@ export default class WebAudio {
488538
this.filter.cfg.addWord(youTubeAutoCensor, youTubeAutoCensorOptions);
489539

490540
// Setup rule for YouTube Auto Subs
491-
this.youTubeAutoSubsRule = { filterSubtitles: true, mode: 'ytauto', muteMethod: this.filter.cfg.muteMethod } as AudioRule;
541+
this.youTubeAutoSubsRule = { mode: 'ytauto' } as AudioRule;
542+
this.initRule(this.youTubeAutoSubsRule);
492543
}
493544
}
494545

0 commit comments

Comments
 (0)