Skip to content

Commit

Permalink
Merrge
Browse files Browse the repository at this point in the history
  • Loading branch information
PikachuEXE committed Jul 10, 2024
2 parents 4b01da4 + d30666a commit c98dbeb
Show file tree
Hide file tree
Showing 107 changed files with 5,458 additions and 7,484 deletions.
2 changes: 1 addition & 1 deletion .stylelintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"selector-pseudo-class-no-unknown": [
true,
{
"ignorePseudoClasses": ["deep"]
"ignorePseudoClasses": ["deep", "global"]
}
],
"a11y/no-outline-none": true,
Expand Down
5 changes: 0 additions & 5 deletions _scripts/_domParser.js

This file was deleted.

34 changes: 24 additions & 10 deletions _scripts/dev-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ const web = process.argv.indexOf('--web') !== -1
let mainConfig
let rendererConfig
let webConfig
let SHAKA_LOCALES_TO_BE_BUNDLED

if (!web) {
mainConfig = require('./webpack.main.config')
rendererConfig = require('./webpack.renderer.config')

SHAKA_LOCALES_TO_BE_BUNDLED = rendererConfig.SHAKA_LOCALES_TO_BE_BUNDLED
delete rendererConfig.SHAKA_LOCALES_TO_BE_BUNDLED
} else {
webConfig = require('./webpack.web.config')
}
Expand Down Expand Up @@ -128,17 +132,27 @@ function startRenderer(callback) {
})

const server = new WebpackDevServer({
static: {
directory: path.resolve(__dirname, '..', 'static'),
watch: {
ignored: [
/(dashFiles|storyboards)\/*/,
'/**/.DS_Store',
'**/static/locales/*'
]
static: [
{
directory: path.resolve(__dirname, '..', 'static'),
watch: {
ignored: [
/(dashFiles|storyboards)\/*/,
'/**/.DS_Store',
'**/static/locales/*'
]
},
publicPath: '/static'
},
publicPath: '/static'
},
{
directory: path.resolve(__dirname, '..', 'node_modules', 'shaka-player', 'ui', 'locales'),
publicPath: '/static/shaka-player-locales',
watch: {
// Ignore everything that isn't one of the locales that we would bundle in production mode
ignored: `**/!(${SHAKA_LOCALES_TO_BE_BUNDLED.join('|')}).json`
}
}
],
port
}, compiler)

Expand Down
114 changes: 114 additions & 0 deletions _scripts/getShakaLocales.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
const { readFileSync, readdirSync } = require('fs')

function getPreloadedLocales() {
const localesFile = readFileSync(`${__dirname}/../node_modules/shaka-player/dist/locales.js`, 'utf-8')

const localesLine = localesFile.match(/^\/\/ LOCALES: ([\w, -]+)$/m)

if (!localesLine) {
throw new Error("Failed to parse shaka-player's preloaded locales")
}

return localesLine[1].split(',').map(locale => locale.trim())
}

function getAllLocales() {
const filenames = readdirSync(`${__dirname}/../node_modules/shaka-player/ui/locales`)

return new Set(filenames
.filter(filename => filename !== 'source.json' && filename.endsWith('.json'))
.map(filename => filename.replace('.json', '')))
}

/**
* Maps the shaka locales to FreeTube's active ones
* This allows us to know which locale files are actually needed
* and which shaka locale needs to be activated for a given FreeTube one.
* @param {Set<string>} shakaLocales
* @param {string[]} freeTubeLocales
*/
function getMappings(shakaLocales, freeTubeLocales) {
/**
* @type {[string, string][]}
* Using this structure as it gets passed to `new Map()` in the player component
* The first element is the FreeTube locale, the second one is the shaka-player one
**/
const mappings = []

for (const locale of freeTubeLocales) {
if (shakaLocales.has(locale)) {
mappings.push([
locale,
locale
])
} else if (shakaLocales.has(locale.replace('_', '-'))) {
mappings.push([
locale,
locale.replace('_', '-')
])
} else if (shakaLocales.has(locale.split(/[-_]/)[0])) {
mappings.push([
locale,
locale.split(/[-_]/)[0]
])
}
}

// special cases

mappings.push(
// according to https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
// "no" is the macro language for "nb" and "nn"
[
'nb_NO',
'no'
],
[
'nn',
'no'
],

// according to https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
// "iw" is the old/original code for Hebrew, these days it's "he"
[
'he',
'iw'
],

// not sure why we have pt, pt-PT and pt-BR in the FreeTube locales
// as pt and pt-PT are the same thing, but we should handle it here anyway
[
'pt',
'pt-PT'
]
)

return mappings
}

function getShakaLocales() {
const shakaLocales = getAllLocales()

/** @type {string[]} */
const freeTubeLocales = JSON.parse(readFileSync(`${__dirname}/../static/locales/activeLocales.json`, 'utf-8'))

const mappings = getMappings(shakaLocales, freeTubeLocales)

const preloaded = getPreloadedLocales()

const shakaMappings = mappings.map(mapping => mapping[1])

// use a set to deduplicate the list
// we don't need to bundle any locale files that are already embedded in shaka-player/preloaded

/** @type {string[]} */
const toBeBundled = [...new Set(shakaMappings.filter(locale => !preloaded.includes(locale)))]

return {
SHAKA_LOCALE_MAPPINGS: mappings,
SHAKA_LOCALES_PREBUNDLED: preloaded,
SHAKA_LOCALES_TO_BE_BUNDLED: toBeBundled
}
}

module.exports = getShakaLocales()
135 changes: 135 additions & 0 deletions _scripts/patchShaka.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// This script fixes shaka not exporting its type definitions and referencing remote google fonts in its CSS
// by adding an export line to the type definitions and downloading the fonts and updating the CSS to point to the local files
// this script only makes changes if they are needed, so running it multiple times doesn't cause any problems

import { appendFileSync, closeSync, ftruncateSync, openSync, readFileSync, writeFileSync, writeSync } from 'fs'
import { resolve } from 'path'

const SHAKA_DIST_DIR = resolve(import.meta.dirname, '../node_modules/shaka-player/dist')

function fixTypes() {
let fixedTypes = false

let fileHandleNormal
try {
fileHandleNormal = openSync(`${SHAKA_DIST_DIR}/shaka-player.ui.d.ts`, 'a+')

const contents = readFileSync(fileHandleNormal, 'utf-8')

// This script is run after every `yarn install`, even if shaka-player wasn't updated
// So we want to check first, if we actually need to make any changes
// or if the ones from the previous run are still intact
if (!contents.includes('export default shaka')) {
appendFileSync(fileHandleNormal, 'export default shaka;\n')

fixedTypes = true
}
} finally {
if (typeof fileHandleNormal !== 'undefined') {
closeSync(fileHandleNormal)
}
}

let fileHandleDebug
try {
fileHandleDebug = openSync(`${SHAKA_DIST_DIR}/shaka-player.ui.debug.d.ts`, 'a+')

const contents = readFileSync(fileHandleDebug, 'utf-8')

// This script is run after every `yarn install`, even if shaka-player wasn't updated
// So we want to check first, if we actually need to make any changes
// or if the ones from the previous run are still intact
if (!contents.includes('export default shaka')) {
appendFileSync(fileHandleDebug, 'export default shaka;\n')

fixedTypes = true
}
} finally {
if (typeof fileHandleDebug !== 'undefined') {
closeSync(fileHandleDebug)
}
}

if (fixedTypes) {
console.log('Fixed shaka-player types')
}
}

async function removeRobotoFont() {
let cssFileHandle
try {
cssFileHandle = openSync(`${SHAKA_DIST_DIR}/controls.css`, 'r+')

let cssContents = readFileSync(cssFileHandle, 'utf-8')

const beforeReplacement = cssContents.length
cssContents = cssContents.replace(/@font-face\{font-family:Roboto;[^}]+\}/, '')

if (cssContents.length !== beforeReplacement) {
ftruncateSync(cssFileHandle)
writeSync(cssFileHandle, cssContents, 0, 'utf-8')

console.log('Removed shaka-player Roboto font, so it uses ours')
}
} finally {
if (typeof cssFileHandle !== 'undefined') {
closeSync(cssFileHandle)
}
}
}

async function replaceAndDownloadMaterialIconsFont() {
let cssFileHandle
try {
cssFileHandle = openSync(`${SHAKA_DIST_DIR}/controls.css`, 'r+')

let cssContents = readFileSync(cssFileHandle, 'utf-8')

const fontFaceRegex = /@font-face{font-family:'Material Icons Round'[^}]+format\('opentype'\)}/

if (fontFaceRegex.test(cssContents)) {
const cssResponse = await fetch('https://fonts.googleapis.com/icon?family=Material+Icons+Round', {
headers: {
// Without the user-agent it returns the otf file instead of the woff2 one
'user-agent': 'Firefox/125.0'
}
})

const text = await cssResponse.text()

let newFontCSS = text.match(/(@font-face\s*{[^}]+})/)[1].replaceAll('\n', '')


const urlMatch = newFontCSS.match(/https:\/\/fonts\.gstatic\.com\/s\/materialiconsround\/(?<version>[^\/]+)\/[^.]+\.(?<extension>[\w]+)/)

const url = urlMatch[0]
const { version, extension } = urlMatch.groups

const fontResponse = await fetch(url)
const fontContent = new Uint8Array(await fontResponse.arrayBuffer())

const filename = `shaka-materialiconsround-${version}.${extension}`
writeFileSync(`${SHAKA_DIST_DIR}/${filename}`, fontContent)

newFontCSS = newFontCSS.replace(url, `./${filename}`)

cssContents = cssContents.replace(fontFaceRegex, newFontCSS)

ftruncateSync(cssFileHandle)
writeSync(cssFileHandle, cssContents, 0, 'utf-8')

console.log('Changed shaka-player Material Icons Rounded font to use the smaller woff2 format instead of otf')
console.log('Downloaded shaka-player Material Icons Rounded font')
}
} catch (e) {
console.error(e)
} finally {
if (typeof cssFileHandle !== 'undefined') {
closeSync(cssFileHandle)
}
}
}

fixTypes()
await removeRobotoFont()
await replaceAndDownloadMaterialIconsFont()
40 changes: 33 additions & 7 deletions _scripts/webpack.renderer.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const ProcessLocalesPlugin = require('./ProcessLocalesPlugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const {
SHAKA_LOCALE_MAPPINGS,
SHAKA_LOCALES_PREBUNDLED,
SHAKA_LOCALES_TO_BE_BUNDLED
} = require('./getShakaLocales')

const isDevMode = process.env.NODE_ENV === 'development'

Expand Down Expand Up @@ -122,7 +127,9 @@ const config = {
'process.env.SUPPORTS_LOCAL_API': true,
'process.env.LOCALE_NAMES': JSON.stringify(processLocalesPlugin.localeNames),
'process.env.GEOLOCATION_NAMES': JSON.stringify(readdirSync(path.join(__dirname, '..', 'static', 'geolocations')).map(filename => filename.replace('.json', ''))),
'process.env.SWIPER_VERSION': `'${swiperVersion}'`
'process.env.SWIPER_VERSION': `'${swiperVersion}'`,
'process.env.SHAKA_LOCALE_MAPPINGS': JSON.stringify(SHAKA_LOCALE_MAPPINGS),
'process.env.SHAKA_LOCALES_PREBUNDLED': JSON.stringify(SHAKA_LOCALES_PREBUNDLED)
}),
new HtmlWebpackPlugin({
excludeChunks: ['processTaskWorker'],
Expand All @@ -143,26 +150,45 @@ const config = {
transformAll: (assets) => {
return Buffer.concat(assets.map(asset => asset.data))
}
}
},
// Don't need to copy them in dev mode,
// as we configure WebpackDevServer to serve them
...(isDevMode ? [] : [
{
from: path.join(__dirname, '../node_modules/shaka-player/ui/locales', `{${SHAKA_LOCALES_TO_BE_BUNDLED.join(',')}}.json`).replaceAll('\\', '/'),
to: path.join(__dirname, '../dist/static/shaka-player-locales'),
context: path.join(__dirname, '../node_modules/shaka-player/ui/locales'),
transform: {
transformer: (input) => {
return JSON.stringify(JSON.parse(input.toString('utf-8')))
}
}
}
])
]
})
],
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js',
'portal-vue$': 'portal-vue/dist/portal-vue.esm.js',

'DB_HANDLERS_ELECTRON_RENDERER_OR_WEB$': path.resolve(__dirname, '../src/datastores/handlers/electron.js'),
DB_HANDLERS_ELECTRON_RENDERER_OR_WEB$: path.resolve(__dirname, '../src/datastores/handlers/electron.js'),

'youtubei.js$': 'youtubei.js/web',

// video.js's mpd-parser uses @xmldom/xmldom so that it can support both node and web browsers
// as FreeTube only runs in electron and web browsers we can use the native DOMParser class, instead of the "polyfill"
// https://caniuse.com/mdn-api_domparser
'@xmldom/xmldom$': path.resolve(__dirname, '_domParser.js')
// change to "shaka-player.ui.debug.js" to get debug logs (update jsconfig to get updated types)
'shaka-player$': 'shaka-player/dist/shaka-player.ui.js',
},
extensions: ['.js', '.vue']
},
target: 'electron-renderer',
}

if (isDevMode) {
// hack to pass it through to the dev-runner.js script
// gets removed there before the config object is passed to webpack
config.SHAKA_LOCALES_TO_BE_BUNDLED = SHAKA_LOCALES_TO_BE_BUNDLED
}

module.exports = config
Loading

0 comments on commit c98dbeb

Please sign in to comment.