mirror of
https://github.com/open-goal/launcher.git
synced 2024-10-19 14:47:36 -04:00
i18n/fonts: lazily download locale-specific fonts (#316)
This commit is contained in:
parent
bf4db0188e
commit
02f7b7b2d2
|
@ -47,3 +47,6 @@ default = ["custom-protocol"]
|
|||
# this feature is used used for production builds where `devPath` points to the filesystem
|
||||
# DO NOT remove this
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
||||
[profile.release]
|
||||
strip = true # Automatically strip symbols from the binary.
|
||||
|
|
|
@ -2,6 +2,7 @@ use serde::{Serialize, Serializer};
|
|||
|
||||
pub mod binaries;
|
||||
pub mod config;
|
||||
pub mod download;
|
||||
pub mod features;
|
||||
pub mod game;
|
||||
pub mod logging;
|
||||
|
|
35
src-tauri/src/commands/download.rs
Normal file
35
src-tauri/src/commands/download.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::util::{file::create_dir, network};
|
||||
|
||||
use super::CommandError;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn download_file(url: String, destination: String) -> Result<(), CommandError> {
|
||||
let download_path = PathBuf::from(&destination);
|
||||
match download_path.parent() {
|
||||
Some(parent) => {
|
||||
if parent == Path::new("") {
|
||||
return Err(CommandError::OSOperation(
|
||||
"Unable to successfully download file".to_owned(),
|
||||
));
|
||||
} else {
|
||||
create_dir(&parent.to_path_buf()).map_err(|_| {
|
||||
CommandError::VersionManagement(format!(
|
||||
"Unable to prepare destination folder '{}' for download",
|
||||
parent.display()
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return Err(CommandError::OSOperation(
|
||||
"Unable to successfully download file".to_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
network::download_file(&url, &download_path)
|
||||
.await
|
||||
.map_err(|_| CommandError::OSOperation("Unable to successfully download file".to_owned()))?;
|
||||
Ok(())
|
||||
}
|
|
@ -158,6 +158,7 @@ fn main() {
|
|||
commands::config::set_locale,
|
||||
commands::config::get_enabled_texture_packs,
|
||||
commands::config::cleanup_enabled_texture_packs,
|
||||
commands::download::download_file,
|
||||
commands::game::reset_game_settings,
|
||||
commands::game::uninstall_game,
|
||||
commands::game::get_furthest_game_milestone,
|
||||
|
|
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Black.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Black.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Bold.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Bold.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-ExtraBold.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-ExtraBold.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-ExtraLight.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-ExtraLight.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Light.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Light.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Medium.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Medium.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Regular.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Regular.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-SemiBold.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-SemiBold.woff2
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Thin.woff2
Normal file
BIN
src/assets/fonts/Noto Sans/general/NotoSans-Thin.woff2
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,70 +1,60 @@
|
|||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Thin.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Thin.woff2");
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-ExtraLight.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-ExtraLight.woff2");
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Light.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Light.woff2");
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Regular.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Regular.woff2");
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Medium.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Medium.woff2");
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-SemiBold.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-SemiBold.woff2");
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Bold.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Bold.woff2");
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-ExtraBold.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-ExtraBold.woff2");
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Black.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSans-Black.woff2");
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans Mono";
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSansMono-VariableFont.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans Arabic";
|
||||
src: url("/src/assets/fonts/Noto Sans/NotoSansArabic-VariableFont.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans JP";
|
||||
src: url("/src/assets/fonts/Noto Sans/NotoSansJP-VariableFont.ttf");
|
||||
src: url("/src/assets/fonts/Noto Sans/general/NotoSansMono-VariableFont.woff2");
|
||||
}
|
||||
|
||||
.font-mono {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import { addMessages, init, register } from "svelte-i18n";
|
||||
|
||||
interface Locale {
|
||||
export interface Locale {
|
||||
id: string;
|
||||
flag: string;
|
||||
localizedName: string;
|
||||
fontFamily?: string;
|
||||
fontFileName?: string;
|
||||
fontDownloadUrl?: string;
|
||||
}
|
||||
|
||||
// https://omniglot.com/language/names.htm
|
||||
|
@ -19,6 +21,9 @@ export const AVAILABLE_LOCALES: Locale[] = [
|
|||
flag: "🇸🇦",
|
||||
localizedName: "العربية الفصحى",
|
||||
fontFamily: "Noto Sans Arabic",
|
||||
fontFileName: "NotoSansArabic-VariableFont.woff2",
|
||||
fontDownloadUrl:
|
||||
"https://github.com/open-goal/launcher-assets/releases/download/fonts%2Fv1.0.0/NotoSansArabic-VariableFont.woff2",
|
||||
},
|
||||
{
|
||||
id: "ca-ES",
|
||||
|
@ -90,11 +95,18 @@ export const AVAILABLE_LOCALES: Locale[] = [
|
|||
flag: "🇯🇵",
|
||||
localizedName: "日本語",
|
||||
fontFamily: "Noto Sans JP",
|
||||
fontFileName: "NotoSansJP-VariableFont.woff2",
|
||||
fontDownloadUrl:
|
||||
"https://github.com/open-goal/launcher-assets/releases/download/fonts%2Fv1.0.0/NotoSansJP-VariableFont.woff2",
|
||||
},
|
||||
{
|
||||
id: "ko-KR",
|
||||
flag: "🇰🇷",
|
||||
localizedName: "한국어",
|
||||
fontFamily: "Noto Sans KR",
|
||||
fontFileName: "NotoSansKR-VariableFont_wght.woff2",
|
||||
fontDownloadUrl:
|
||||
"https://github.com/open-goal/launcher-assets/releases/download/fonts%2Fv1.0.0/NotoSansKR-VariableFont_wght.woff2",
|
||||
},
|
||||
{
|
||||
id: "nl-NL",
|
||||
|
@ -160,11 +172,19 @@ export const AVAILABLE_LOCALES: Locale[] = [
|
|||
id: "zh-CN",
|
||||
flag: "🇨🇳",
|
||||
localizedName: "简体中文",
|
||||
fontFamily: "Noto Sans SC",
|
||||
fontFileName: "NotoSansSC-VariableFont_wght.woff2",
|
||||
fontDownloadUrl:
|
||||
"https://github.com/open-goal/launcher-assets/releases/download/fonts%2Fv1.0.0/NotoSansSC-VariableFont_wght.woff2",
|
||||
},
|
||||
{
|
||||
id: "zh-TW",
|
||||
flag: "🇹🇼",
|
||||
localizedName: "繁體中文",
|
||||
fontFamily: "Noto Sans TC",
|
||||
fontFileName: "NotoSansTC-VariableFont_wght.woff2",
|
||||
fontDownloadUrl:
|
||||
"https://github.com/open-goal/launcher-assets/releases/download/fonts%2Fv1.0.0/NotoSansTC-VariableFont_wght.woff2",
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -3,7 +3,10 @@ import { locale as svelteLocale } from "svelte-i18n";
|
|||
import { errorLog } from "./logging";
|
||||
import { invoke_rpc } from "./rpc";
|
||||
import type { VersionFolders } from "./versions";
|
||||
import { AVAILABLE_LOCALES } from "$lib/i18n/i18n";
|
||||
import { AVAILABLE_LOCALES, type Locale } from "$lib/i18n/i18n";
|
||||
import { readBinaryFile, BaseDirectory, exists } from "@tauri-apps/api/fs";
|
||||
import { appDataDir, join } from "@tauri-apps/api/path";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
|
||||
export async function oldDataDirectoryExists(): Promise<boolean> {
|
||||
return await invoke_rpc("has_old_data_directory", {}, () => false);
|
||||
|
@ -106,23 +109,72 @@ export async function getLocale(): Promise<string | null> {
|
|||
return await invoke_rpc("get_locale", {}, () => "en-US");
|
||||
}
|
||||
|
||||
export async function localeSpecificFontAvailableForDownload(
|
||||
localeId: string,
|
||||
): Promise<Locale | undefined> {
|
||||
let localeInfo = AVAILABLE_LOCALES.find((locale) => locale.id === localeId);
|
||||
if (
|
||||
localeInfo !== undefined &&
|
||||
localeInfo.fontFileName !== undefined &&
|
||||
localeInfo.fontDownloadUrl !== undefined
|
||||
) {
|
||||
const fontPath = await join(
|
||||
await appDataDir(),
|
||||
"fonts",
|
||||
localeInfo.fontFileName,
|
||||
);
|
||||
const fontAlreadyDownloaded = await exists(fontPath);
|
||||
if (fontAlreadyDownloaded) {
|
||||
return undefined;
|
||||
}
|
||||
return localeInfo;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export async function setLocale(localeId: string): Promise<void> {
|
||||
return await invoke_rpc(
|
||||
"set_locale",
|
||||
{ locale: localeId },
|
||||
() => {},
|
||||
null, // no toast
|
||||
() => {
|
||||
undefined, // no toast
|
||||
async () => {
|
||||
svelteLocale.set(localeId);
|
||||
// Update CSS variable if needed
|
||||
let localeInfo = AVAILABLE_LOCALES.find(
|
||||
(locale) => locale.id === localeId,
|
||||
);
|
||||
if (localeInfo !== undefined && localeInfo.fontFamily !== undefined) {
|
||||
document.documentElement.style.setProperty(
|
||||
"--launcher-font-family",
|
||||
localeInfo.fontFamily,
|
||||
if (
|
||||
localeInfo !== undefined &&
|
||||
localeInfo.fontFamily !== undefined &&
|
||||
localeInfo.fontFileName !== undefined
|
||||
) {
|
||||
// Dynamically get the font
|
||||
const fontPath = await join(
|
||||
await appDataDir(),
|
||||
"fonts",
|
||||
localeInfo.fontFileName,
|
||||
);
|
||||
const fontExists = await exists(fontPath);
|
||||
if (fontExists) {
|
||||
const assetUrl = convertFileSrc(fontPath);
|
||||
var newFontStyle = document.createElement("style");
|
||||
newFontStyle.appendChild(
|
||||
document.createTextNode(
|
||||
`@font-face {\nfont-family: "${localeInfo.fontFamily}";\nsrc: url('${assetUrl}');\n}\n`,
|
||||
),
|
||||
);
|
||||
document.head.appendChild(newFontStyle);
|
||||
document.documentElement.style.setProperty(
|
||||
"--launcher-font-family",
|
||||
localeInfo.fontFamily,
|
||||
);
|
||||
} else {
|
||||
document.documentElement.style.setProperty(
|
||||
"--launcher-font-family",
|
||||
"Noto Sans",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
document.documentElement.style.setProperty(
|
||||
"--launcher-font-family",
|
||||
|
|
13
src/lib/rpc/download.ts
Normal file
13
src/lib/rpc/download.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { invoke_rpc } from "./rpc";
|
||||
|
||||
export async function downloadFile(
|
||||
url: String,
|
||||
destination: String,
|
||||
): Promise<void> {
|
||||
await invoke_rpc(
|
||||
"download_file",
|
||||
{ url, destination },
|
||||
() => {},
|
||||
"Unable to download file",
|
||||
);
|
||||
}
|
|
@ -1,24 +1,36 @@
|
|||
<script lang="ts">
|
||||
import { AVAILABLE_LOCALES } from "$lib/i18n/i18n";
|
||||
import { AVAILABLE_LOCALES, type Locale } from "$lib/i18n/i18n";
|
||||
import {
|
||||
getBypassRequirements,
|
||||
getInstallationDirectory,
|
||||
getLocale,
|
||||
localeSpecificFontAvailableForDownload,
|
||||
resetLauncherSettingsToDefaults,
|
||||
setBypassRequirements,
|
||||
setLocale,
|
||||
} from "$lib/rpc/config";
|
||||
import { getActiveVersion, getActiveVersionFolder } from "$lib/rpc/versions";
|
||||
import { VersionStore } from "$lib/stores/VersionStore";
|
||||
import { Button, Helper, Label, Select, Toggle } from "flowbite-svelte";
|
||||
import {
|
||||
Button,
|
||||
Helper,
|
||||
Label,
|
||||
Select,
|
||||
Spinner,
|
||||
Toggle,
|
||||
} from "flowbite-svelte";
|
||||
import { onMount } from "svelte";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { confirm } from "@tauri-apps/api/dialog";
|
||||
import { downloadFile } from "$lib/rpc/download";
|
||||
import { appDataDir, join } from "@tauri-apps/api/path";
|
||||
|
||||
let currentInstallationDirectory = "";
|
||||
let currentLocale;
|
||||
let availableLocales = [];
|
||||
let currentBypassRequirementsVal = false;
|
||||
let localeFontForDownload: Locale | undefined = undefined;
|
||||
let localeFontDownloading = false;
|
||||
|
||||
onMount(async () => {
|
||||
currentInstallationDirectory = await getInstallationDirectory();
|
||||
|
@ -33,6 +45,10 @@
|
|||
}
|
||||
currentLocale = await getLocale();
|
||||
currentBypassRequirementsVal = await getBypassRequirements();
|
||||
if (currentLocale !== null) {
|
||||
localeFontForDownload =
|
||||
await localeSpecificFontAvailableForDownload(currentLocale);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -45,7 +61,10 @@
|
|||
items={availableLocales}
|
||||
bind:value={currentLocale}
|
||||
on:change={async (evt) => {
|
||||
setLocale(evt.target.value);
|
||||
await setLocale(evt.target.value);
|
||||
localeFontForDownload = await localeSpecificFontAvailableForDownload(
|
||||
evt.target.value,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Label>
|
||||
|
@ -59,6 +78,36 @@
|
|||
>
|
||||
{$_("settings_general_localeChange_helper_2")}</Helper
|
||||
>
|
||||
{#if localeFontForDownload !== undefined}
|
||||
<Button
|
||||
class="flex-shrink border-solid rounded bg-white hover:bg-orange-400 text-sm text-slate-900 font-semibold px-5 py-2 mt-2"
|
||||
disabled={localeFontDownloading}
|
||||
on:click={async () => {
|
||||
if (
|
||||
localeFontForDownload !== undefined &&
|
||||
localeFontForDownload.fontDownloadUrl !== undefined &&
|
||||
localeFontForDownload.fontFileName !== undefined
|
||||
) {
|
||||
localeFontDownloading = true;
|
||||
const fontPath = await join(
|
||||
await appDataDir(),
|
||||
"fonts",
|
||||
localeFontForDownload.fontFileName,
|
||||
);
|
||||
await downloadFile(localeFontForDownload.fontDownloadUrl, fontPath);
|
||||
await setLocale(currentLocale);
|
||||
localeFontForDownload =
|
||||
await localeSpecificFontAvailableForDownload(currentLocale);
|
||||
localeFontDownloading = false;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if localeFontDownloading}
|
||||
<Spinner class="mr-3" size="4" color="white" />
|
||||
{/if}
|
||||
Download Locale Specific Font
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
<Toggle
|
||||
|
|
Loading…
Reference in a new issue