mirror of
https://github.com/ankitects/anki.git
synced 2025-11-06 20:57:13 -05:00
Merge branch 'main' into tag-nc
This commit is contained in:
commit
4e4a5f8f52
11 changed files with 104 additions and 13 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -46,9 +46,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
|||
|
||||
[[package]]
|
||||
name = "ammonia"
|
||||
version = "4.1.1"
|
||||
version = "4.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f"
|
||||
checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6"
|
||||
dependencies = [
|
||||
"cssparser",
|
||||
"html5ever 0.35.0",
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ ninja_gen = { "path" = "build/ninja_gen" }
|
|||
unicase = "=2.6.0" # any changes could invalidate sqlite indexes
|
||||
|
||||
# normal
|
||||
ammonia = "4.1.0"
|
||||
ammonia = "4.1.2"
|
||||
anyhow = "1.0.98"
|
||||
async-compression = { version = "0.4.24", features = ["zstd", "tokio"] }
|
||||
async-stream = "0.3.6"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ service CollectionService {
|
|||
rpc LatestProgress(generic.Empty) returns (Progress);
|
||||
rpc SetWantsAbort(generic.Empty) returns (generic.Empty);
|
||||
rpc SetLoadBalancerEnabled(generic.Bool) returns (OpChanges);
|
||||
rpc GetCustomColours(generic.Empty) returns (GetCustomColoursResponse);
|
||||
}
|
||||
|
||||
// Implicitly includes any of the above methods that are not listed in the
|
||||
|
|
@ -163,3 +164,7 @@ message CreateBackupRequest {
|
|||
bool force = 2;
|
||||
bool wait_for_completion = 3;
|
||||
}
|
||||
|
||||
message GetCustomColoursResponse {
|
||||
repeated string colours = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from anki._legacy import DeprecatedNamesMixinForModule
|
|||
TR = anki._fluent.LegacyTranslationEnum
|
||||
FormatTimeSpan = _pb.FormatTimespanRequest
|
||||
|
||||
|
||||
# When adding new languages here, check lang_to_disk_lang() below
|
||||
langs = sorted(
|
||||
[
|
||||
("Afrikaans", "af_ZA"),
|
||||
|
|
@ -38,6 +38,7 @@ langs = sorted(
|
|||
("Italiano", "it_IT"),
|
||||
("lo jbobau", "jbo_EN"),
|
||||
("Lenga d'òc", "oc_FR"),
|
||||
("Қазақша", "kk_KZ"),
|
||||
("Magyar", "hu_HU"),
|
||||
("Nederlands", "nl_NL"),
|
||||
("Norsk", "nb_NO"),
|
||||
|
|
@ -64,6 +65,7 @@ langs = sorted(
|
|||
("Українська мова", "uk_UA"),
|
||||
("Հայերեն", "hy_AM"),
|
||||
("עִבְרִית", "he_IL"),
|
||||
("ייִדיש", "yi"),
|
||||
("العربية", "ar_SA"),
|
||||
("فارسی", "fa_IR"),
|
||||
("ภาษาไทย", "th_TH"),
|
||||
|
|
@ -104,6 +106,7 @@ compatMap = {
|
|||
"it": "it_IT",
|
||||
"ja": "ja_JP",
|
||||
"jbo": "jbo_EN",
|
||||
"kk": "kk_KZ",
|
||||
"ko": "ko_KR",
|
||||
"la": "la_LA",
|
||||
"mn": "mn_MN",
|
||||
|
|
@ -126,6 +129,7 @@ compatMap = {
|
|||
"uk": "uk_UA",
|
||||
"uz": "uz_UZ",
|
||||
"vi": "vi_VN",
|
||||
"yi": "yi",
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -233,7 +237,7 @@ def get_def_lang(user_lang: str | None = None) -> tuple[int, str]:
|
|||
|
||||
|
||||
def is_rtl(lang: str) -> bool:
|
||||
return lang in ("he", "ar", "fa", "ug")
|
||||
return lang in ("he", "ar", "fa", "ug", "yi")
|
||||
|
||||
|
||||
# strip off unicode isolation markers from a translated string
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ def show(mw: aqt.AnkiQt) -> QDialog:
|
|||
"Anon_0000",
|
||||
"Bilolbek Normuminov",
|
||||
"Sagiv Marzini",
|
||||
"Zhanibek Rassululy",
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -170,13 +170,42 @@ def favicon() -> Response:
|
|||
|
||||
def _mime_for_path(path: str) -> str:
|
||||
"Mime type for provided path/filename."
|
||||
if path.endswith(".css"):
|
||||
# some users may have invalid mime type in the Windows registry
|
||||
return "text/css"
|
||||
elif path.endswith(".js") or path.endswith(".mjs"):
|
||||
return "application/javascript"
|
||||
|
||||
_, ext = os.path.splitext(path)
|
||||
ext = ext.lower()
|
||||
|
||||
# Badly-behaved apps on Windows can alter the standard mime types in the registry, which can completely
|
||||
# break Anki's UI. So we hard-code the most common extensions.
|
||||
mime_types = {
|
||||
".css": "text/css",
|
||||
".js": "application/javascript",
|
||||
".mjs": "application/javascript",
|
||||
".html": "text/html",
|
||||
".htm": "text/html",
|
||||
".svg": "image/svg+xml",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".gif": "image/gif",
|
||||
".webp": "image/webp",
|
||||
".ico": "image/x-icon",
|
||||
".json": "application/json",
|
||||
".woff": "font/woff",
|
||||
".woff2": "font/woff2",
|
||||
".ttf": "font/ttf",
|
||||
".otf": "font/otf",
|
||||
".mp3": "audio/mpeg",
|
||||
".mp4": "video/mp4",
|
||||
".webm": "video/webm",
|
||||
".ogg": "audio/ogg",
|
||||
".pdf": "application/pdf",
|
||||
".txt": "text/plain",
|
||||
}
|
||||
|
||||
if mime := mime_types.get(ext):
|
||||
return mime
|
||||
else:
|
||||
# autodetect
|
||||
# fallback to mimetypes, which may consult the registry
|
||||
mime, _encoding = mimetypes.guess_type(path)
|
||||
return mime or "application/octet-stream"
|
||||
|
||||
|
|
@ -601,7 +630,7 @@ def deck_options_ready() -> bytes:
|
|||
|
||||
def save_custom_colours() -> bytes:
|
||||
colors = [
|
||||
QColorDialog.customColor(i).name(QColor.NameFormat.HexArgb)
|
||||
QColorDialog.customColor(i).name(QColor.NameFormat.HexRgb)
|
||||
for i in range(QColorDialog.customCount())
|
||||
]
|
||||
aqt.mw.col.set_config("customColorPickerPalette", colors)
|
||||
|
|
@ -630,6 +659,7 @@ post_handler_list = [
|
|||
exposed_backend_list = [
|
||||
# CollectionService
|
||||
"latest_progress",
|
||||
"get_custom_colours",
|
||||
# DeckService
|
||||
"get_deck_names",
|
||||
# I18nService
|
||||
|
|
|
|||
|
|
@ -134,5 +134,8 @@ pub fn ensure_os_supported() -> Result<()> {
|
|||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
unix::ensure_glibc_supported()?;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
windows::ensure_windows_version_supported()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,26 @@ fn is_windows_10() -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Ensures Windows 10 version 1809 or later
|
||||
pub fn ensure_windows_version_supported() -> Result<()> {
|
||||
unsafe {
|
||||
let mut info = OSVERSIONINFOW {
|
||||
dwOSVersionInfoSize: std::mem::size_of::<OSVERSIONINFOW>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if RtlGetVersion(&mut info).is_err() {
|
||||
anyhow::bail!("Failed to get Windows version information");
|
||||
}
|
||||
|
||||
if info.dwBuildNumber >= 17763 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
anyhow::bail!("Windows 10 version 1809 or later is required.")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensure_terminal_shown() -> Result<()> {
|
||||
unsafe {
|
||||
if !GetConsoleWindow().is_invalid() {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
use anki_proto::collection::GetCustomColoursResponse;
|
||||
use anki_proto::generic;
|
||||
|
||||
use crate::collection::Collection;
|
||||
use crate::config::ConfigKey;
|
||||
use crate::error;
|
||||
use crate::prelude::BoolKey;
|
||||
use crate::prelude::Op;
|
||||
|
|
@ -62,4 +64,13 @@ impl crate::services::CollectionService for Collection {
|
|||
})
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
fn get_custom_colours(
|
||||
&mut self,
|
||||
) -> error::Result<anki_proto::collection::GetCustomColoursResponse> {
|
||||
let colours = self
|
||||
.get_config_optional(ConfigKey::CustomColorPickerPalette)
|
||||
.unwrap_or_default();
|
||||
Ok(GetCustomColoursResponse { colours })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ pub(crate) enum ConfigKey {
|
|||
NextNewCardPosition,
|
||||
#[strum(to_string = "schedVer")]
|
||||
SchedulerVersion,
|
||||
CustomColorPickerPalette,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Serialize_repr, Deserialize_repr, Clone, Copy, Debug)]
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
onWheelDragX,
|
||||
} from "./tools/tool-zoom";
|
||||
import { fillMask } from "./tools/tool-fill";
|
||||
import { getCustomColours, saveCustomColours } from "@generated/backend";
|
||||
|
||||
export let canvas;
|
||||
export let iconSize;
|
||||
|
|
@ -76,6 +77,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
let colourRef: HTMLInputElement | undefined;
|
||||
const colour = writable(SHAPE_MASK_COLOR);
|
||||
|
||||
const customColorPickerPalette = writable<string[]>([]);
|
||||
|
||||
async function loadCustomColours() {
|
||||
customColorPickerPalette.set(
|
||||
(await getCustomColours({})).colours.filter(
|
||||
(hex) => !hex.startsWith("#ffffff"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function onClick(event: MouseEvent) {
|
||||
const upperCanvas = document.querySelector(".upper-canvas");
|
||||
if (event.target == upperCanvas) {
|
||||
|
|
@ -233,6 +244,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
on(document, "touchstart", onTouchstart),
|
||||
on(document, "mousemove", onMousemoveDocument),
|
||||
);
|
||||
loadCustomColours();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
|
|
@ -241,7 +253,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
</script>
|
||||
|
||||
<datalist id="colour-palette">
|
||||
<option value={SHAPE_MASK_COLOR}></option>
|
||||
<option>{SHAPE_MASK_COLOR}</option>
|
||||
{#each $customColorPickerPalette as colour}
|
||||
<option>{colour}</option>
|
||||
{/each}
|
||||
</datalist>
|
||||
|
||||
<input
|
||||
|
|
@ -251,6 +266,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
list="colour-palette"
|
||||
value={SHAPE_MASK_COLOR}
|
||||
on:input={(e) => ($colour = e.currentTarget!.value)}
|
||||
on:change={() => saveCustomColours({})}
|
||||
/>
|
||||
|
||||
<div class="tool-bar-container" style:--fill-tool-colour={$colour}>
|
||||
|
|
|
|||
Loading…
Reference in a new issue