mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Add a SwiftUI iOS app that plays the same maturita content.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
3f88e55f33
commit
6c7336c7bb
33 changed files with 4498 additions and 10 deletions
60
ios/Maturita/Data/Answers.swift
Normal file
60
ios/Maturita/Data/Answers.swift
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import Foundation
|
||||
|
||||
func normalizeAnswer(_ input: String?) -> String {
|
||||
var pre = ""
|
||||
for ch in (input ?? "").lowercased() {
|
||||
switch ch {
|
||||
case "ä": pre += "ae"
|
||||
case "ö": pre += "oe"
|
||||
case "ü": pre += "ue"
|
||||
case "ß": pre += "ss"
|
||||
default: pre.append(ch)
|
||||
}
|
||||
}
|
||||
let decomp = pre.decomposedStringWithCanonicalMapping
|
||||
var out = ""
|
||||
var prevSpace = false
|
||||
for scalar in decomp.unicodeScalars {
|
||||
let v = scalar.value
|
||||
if (0x0300...0x036F).contains(v) || (0x1AB0...0x1AFF).contains(v) ||
|
||||
(0x1DC0...0x1DFF).contains(v) || (0x20D0...0x20FF).contains(v) ||
|
||||
(0xFE20...0xFE2F).contains(v) {
|
||||
continue
|
||||
}
|
||||
if CharacterSet.whitespacesAndNewlines.contains(scalar) {
|
||||
if !out.isEmpty && !prevSpace { out.append(" ") }
|
||||
prevSpace = true
|
||||
continue
|
||||
}
|
||||
if !CharacterSet.alphanumerics.contains(scalar) { continue }
|
||||
prevSpace = false
|
||||
out.unicodeScalars.append(scalar)
|
||||
}
|
||||
return out.trimmingCharacters(in: .whitespaces)
|
||||
}
|
||||
|
||||
func answerAccepts(_ selNorm: String, _ ans: String?) -> Bool {
|
||||
guard let ans, !ans.isEmpty else { return false }
|
||||
return ans.split(separator: "|").contains { normalizeAnswer(String($0)) == selNorm }
|
||||
}
|
||||
|
||||
func answerIncomplete(_ selNorm: String, _ ans: String?) -> Bool {
|
||||
guard !selNorm.isEmpty, let ans, !ans.isEmpty else { return false }
|
||||
for part in ans.split(separator: "|") {
|
||||
let a = normalizeAnswer(String(part))
|
||||
if a.hasPrefix(selNorm + " ") && a.count > selNorm.count + 1 { return true }
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func netTxtEq(_ a: String?, _ b: String?) -> Bool {
|
||||
guard let a, let b else { return a == b }
|
||||
let x = a.filter { !$0.isWhitespace }.lowercased()
|
||||
let y = b.filter { !$0.isWhitespace }.lowercased()
|
||||
return x == y
|
||||
}
|
||||
|
||||
func hasUmlaut(_ s: String?) -> Bool {
|
||||
guard let s else { return false }
|
||||
return s.contains(where: { "äöüÄÖÜß".contains($0) })
|
||||
}
|
||||
95
ios/Maturita/Data/Content.swift
Normal file
95
ios/Maturita/Data/Content.swift
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import Foundation
|
||||
|
||||
enum AppConfig {
|
||||
static var commit: String {
|
||||
let raw = (Bundle.main.object(forInfoDictionaryKey: "GITCommit") as? String)?
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
return raw.isEmpty || raw.hasPrefix("$(") ? "dev" : raw
|
||||
}
|
||||
|
||||
static var versionName: String {
|
||||
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "ios-1"
|
||||
}
|
||||
|
||||
static var updateRepo: String {
|
||||
(Bundle.main.object(forInfoDictionaryKey: "UPDATE_REPO") as? String)
|
||||
?? "pepaskopec-blip/maturita.c"
|
||||
}
|
||||
|
||||
static var updateBranch: String {
|
||||
(Bundle.main.object(forInfoDictionaryKey: "UPDATE_BRANCH") as? String) ?? "builds"
|
||||
}
|
||||
}
|
||||
|
||||
final class Content {
|
||||
let raw: J
|
||||
let i18n: [String: (String?, String?)]
|
||||
let subjects: [J]
|
||||
let german: [J]
|
||||
let net: J
|
||||
let netLessons: [J]
|
||||
let netTasks: [J]
|
||||
let netAnswers: [[J]]
|
||||
let hw: [J]
|
||||
let mluvnice: [J]
|
||||
let books: [J]
|
||||
|
||||
init(_ root: [String: Any]) {
|
||||
raw = J(root)
|
||||
let obj = root["i18n"] as? [String: Any] ?? [:]
|
||||
var map: [String: (String?, String?)] = [:]
|
||||
for (key, value) in obj {
|
||||
let e = J(value)
|
||||
let cs = e.strOrNull("cs")
|
||||
let en = e.strOrNull("en")
|
||||
map[key] = (cs, en)
|
||||
}
|
||||
i18n = map
|
||||
subjects = raw.arr("subjects")
|
||||
german = raw.arr("german")
|
||||
net = raw.obj("net") ?? J([:])
|
||||
netLessons = net.arr("lessons")
|
||||
netTasks = net.arr("tasks")
|
||||
if let a = net.o["answers"] as? [Any] {
|
||||
netAnswers = a.map { block in
|
||||
guard let rows = block as? [Any] else { return [] }
|
||||
return rows.compactMap { item in
|
||||
item is [String: Any] ? J(item) : nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
netAnswers = []
|
||||
}
|
||||
hw = raw.arr("hw")
|
||||
mluvnice = raw.arr("mluvnice")
|
||||
books = raw.arr("books")
|
||||
}
|
||||
|
||||
func germanUnit(_ id: Int) -> J? { german.first { $0.int("id") == id } }
|
||||
func netLesson(_ id: Int) -> J? { netLessons.first { $0.int("id") == id } }
|
||||
func hwLesson(_ id: Int) -> J? { hw.first { $0.int("id") == id } }
|
||||
func mluv(_ n: Int) -> J? { mluvnice.first { $0.int("id") == n } }
|
||||
func book(_ id: String) -> J? { books.first { $0.str("id") == id } }
|
||||
|
||||
func tr(_ key: String?, lang: UiLang) -> String {
|
||||
guard let key, !key.isEmpty else { return "" }
|
||||
let hit = i18n[key]
|
||||
if lang == .en { return hit?.1 ?? key }
|
||||
return hit?.0 ?? key
|
||||
}
|
||||
|
||||
func fmt(_ key: String, lang: UiLang, _ args: [CVarArg]) -> String {
|
||||
let template = tr(key, lang: lang).replacingOccurrences(of: "%s", with: "%@")
|
||||
return String(format: template, arguments: args)
|
||||
}
|
||||
|
||||
static func load() -> Content {
|
||||
guard let url = Bundle.main.url(forResource: "content", withExtension: "json"),
|
||||
let data = try? Data(contentsOf: url),
|
||||
let obj = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
|
||||
else {
|
||||
return Content([:])
|
||||
}
|
||||
return Content(obj)
|
||||
}
|
||||
}
|
||||
102
ios/Maturita/Data/JSON.swift
Normal file
102
ios/Maturita/Data/JSON.swift
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import Foundation
|
||||
|
||||
struct J {
|
||||
let o: [String: Any]
|
||||
|
||||
init(_ obj: Any?) {
|
||||
o = obj as? [String: Any] ?? [:]
|
||||
}
|
||||
|
||||
func has(_ key: String) -> Bool {
|
||||
guard let value = o[key], !(value is NSNull) else { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
func str(_ key: String, _ fallback: String = "") -> String {
|
||||
guard has(key) else { return fallback }
|
||||
if let s = o[key] as? String { return s }
|
||||
if let n = o[key] as? NSNumber { return n.stringValue }
|
||||
return fallback
|
||||
}
|
||||
|
||||
func strOrNull(_ key: String) -> String? {
|
||||
guard has(key) else { return nil }
|
||||
if let s = o[key] as? String, !s.isEmpty, s != "null" { return s }
|
||||
return nil
|
||||
}
|
||||
|
||||
func bool(_ key: String, _ fallback: Bool = false) -> Bool {
|
||||
if let b = o[key] as? Bool { return b }
|
||||
if let n = o[key] as? NSNumber { return n.boolValue }
|
||||
return fallback
|
||||
}
|
||||
|
||||
func int(_ key: String, _ fallback: Int = 0) -> Int {
|
||||
if let n = o[key] as? Int { return n }
|
||||
if let n = o[key] as? NSNumber { return n.intValue }
|
||||
if let s = o[key] as? String, let n = Int(s) { return n }
|
||||
return fallback
|
||||
}
|
||||
|
||||
func obj(_ key: String) -> J? {
|
||||
guard let value = o[key], !(value is NSNull) else { return nil }
|
||||
if value is [String: Any] { return J(value) }
|
||||
return nil
|
||||
}
|
||||
|
||||
func exercise(_ n: Int) -> J? {
|
||||
guard let ex = o["exercises"] as? [String: Any] else { return nil }
|
||||
return J(ex["\(n)"])
|
||||
}
|
||||
|
||||
func arr(_ key: String) -> [J] {
|
||||
guard let a = o[key] as? [Any] else { return [] }
|
||||
return a.compactMap { item in
|
||||
item is [String: Any] ? J(item) : nil
|
||||
}
|
||||
}
|
||||
|
||||
func strs(_ key: String) -> [String] {
|
||||
guard let a = o[key] as? [Any] else { return [] }
|
||||
return a.compactMap { item in
|
||||
if item is NSNull { return nil }
|
||||
if let s = item as? String, !s.isEmpty { return s }
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func strsOrEmpty(_ key: String) -> [String?] {
|
||||
guard let a = o[key] as? [Any] else { return [] }
|
||||
return a.map { item in
|
||||
if item is NSNull { return nil }
|
||||
return item as? String
|
||||
}
|
||||
}
|
||||
|
||||
func intRows(_ key: String) -> [[String]] {
|
||||
guard let a = o[key] as? [Any] else { return [] }
|
||||
return a.map { row in
|
||||
guard let cells = row as? [Any] else { return [] }
|
||||
return cells.map { cell in
|
||||
if let s = cell as? String { return s }
|
||||
if let n = cell as? NSNumber { return n.stringValue }
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rawArray(_ key: String) -> [Any] {
|
||||
o[key] as? [Any] ?? []
|
||||
}
|
||||
|
||||
func answerList() -> [String] {
|
||||
if let a = o["answers"] as? [Any] {
|
||||
return a.compactMap { item in
|
||||
if item is NSNull { return nil }
|
||||
if let s = item as? String, !s.isEmpty { return s }
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return [strOrNull("answers")].compactMap { $0 }
|
||||
}
|
||||
}
|
||||
81
ios/Maturita/Data/ProgressStore.swift
Normal file
81
ios/Maturita/Data/ProgressStore.swift
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import Foundation
|
||||
|
||||
final class ProgressStore {
|
||||
private let defaults = UserDefaults.standard
|
||||
|
||||
var themeId: ThemeId {
|
||||
get { ThemeId(rawValue: defaults.integer(forKey: "theme")) ?? .catppuccin }
|
||||
set { defaults.set(newValue.rawValue, forKey: "theme") }
|
||||
}
|
||||
|
||||
var mode: ColorMode {
|
||||
get { defaults.string(forKey: "mode") == "dark" ? .dark : .light }
|
||||
set { defaults.set(newValue == .light ? "light" : "dark", forKey: "mode") }
|
||||
}
|
||||
|
||||
var lang: UiLang {
|
||||
get { defaults.string(forKey: "lang") == "en" ? .en : .cs }
|
||||
set { defaults.set(newValue == .en ? "en" : "cs", forKey: "lang") }
|
||||
}
|
||||
|
||||
func germanDone(_ unit: Int, _ ex: Int) -> Bool { defaults.bool(forKey: "g.\(unit).\(ex)") }
|
||||
func markGerman(_ unit: Int, _ ex: Int) { defaults.set(true, forKey: "g.\(unit).\(ex)") }
|
||||
func vocabDone(_ unit: Int) -> Bool { defaults.bool(forKey: "g.\(unit).vocab") }
|
||||
func markVocab(_ unit: Int) { defaults.set(true, forKey: "g.\(unit).vocab") }
|
||||
|
||||
func netDone(_ id: Int) -> Bool { defaults.bool(forKey: "net.\(id)") }
|
||||
func markNet(_ id: Int) { defaults.set(true, forKey: "net.\(id)") }
|
||||
|
||||
func hwDone(_ id: Int) -> Bool { defaults.bool(forKey: "hw.\(id)") }
|
||||
func markHw(_ id: Int) { defaults.set(true, forKey: "hw.\(id)") }
|
||||
|
||||
func mluvDone(_ n: Int) -> Bool { defaults.bool(forKey: "mluv.\(n)") }
|
||||
func markMluv(_ n: Int) { defaults.set(true, forKey: "mluv.\(n)") }
|
||||
|
||||
func bookQuiz(_ id: String) -> Bool { defaults.bool(forKey: "book.\(id).quiz") }
|
||||
func markBookQuiz(_ id: String) { defaults.set(true, forKey: "book.\(id).quiz") }
|
||||
func bookPlot(_ id: String) -> Bool { defaults.bool(forKey: "book.\(id).plot") }
|
||||
func markBookPlot(_ id: String) { defaults.set(true, forKey: "book.\(id).plot") }
|
||||
}
|
||||
|
||||
struct ProgressSum {
|
||||
var doneEx = 0
|
||||
var totalEx = 0
|
||||
var doneUnits = 0
|
||||
var openUnits = 0
|
||||
}
|
||||
|
||||
func summarize(_ content: Content, _ p: ProgressStore) -> ProgressSum {
|
||||
var sum = ProgressSum()
|
||||
for u in content.german where u.bool("unlocked") {
|
||||
let id = u.int("id")
|
||||
let names = u.strs("names")
|
||||
sum.totalEx += names.count
|
||||
sum.openUnits += 1
|
||||
let done = names.indices.filter { p.germanDone(id, $0 + 1) }.count
|
||||
sum.doneEx += done
|
||||
if !names.isEmpty && done == names.count { sum.doneUnits += 1 }
|
||||
}
|
||||
for l in content.netLessons {
|
||||
sum.totalEx += 1
|
||||
sum.openUnits += 1
|
||||
if p.netDone(l.int("id")) {
|
||||
sum.doneEx += 1
|
||||
sum.doneUnits += 1
|
||||
}
|
||||
}
|
||||
for l in content.hw {
|
||||
sum.totalEx += 1
|
||||
sum.openUnits += 1
|
||||
if p.hwDone(l.int("id")) {
|
||||
sum.doneEx += 1
|
||||
sum.doneUnits += 1
|
||||
}
|
||||
}
|
||||
sum.totalEx += content.mluvnice.count
|
||||
sum.openUnits += 1
|
||||
let md = content.mluvnice.filter { p.mluvDone($0.int("id")) }.count
|
||||
sum.doneEx += md
|
||||
if md == content.mluvnice.count && !content.mluvnice.isEmpty { sum.doneUnits += 1 }
|
||||
return sum
|
||||
}
|
||||
173
ios/Maturita/Data/Theme.swift
Normal file
173
ios/Maturita/Data/Theme.swift
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
import SwiftUI
|
||||
|
||||
enum ThemeId: Int, CaseIterable {
|
||||
case catppuccin, nord, dracula, rosePine, ocean, gruvbox, solarized, everforest, monokai, oneDark
|
||||
}
|
||||
|
||||
enum ColorMode {
|
||||
case dark, light
|
||||
}
|
||||
|
||||
enum UiLang {
|
||||
case cs, en
|
||||
}
|
||||
|
||||
let themeNames = [
|
||||
"Catppuccin", "Nord", "Dracula", "Rose Pine", "Ocean",
|
||||
"Gruvbox", "Solarized", "Everforest", "Monokai", "One Dark",
|
||||
]
|
||||
|
||||
struct Palette {
|
||||
let crust, base, mantle, surface0, surface1, surface2: Color
|
||||
let overlay, text, subtext: Color
|
||||
let accent, accent2, accent3: Color
|
||||
let success, success2, warning, error: Color
|
||||
let onAccent, node, lockedBg, lockedBorder, rail: Color
|
||||
let finishDark, finishLight, finishStroke: Color
|
||||
}
|
||||
|
||||
private func hx(_ v: UInt32) -> Color {
|
||||
Color(
|
||||
red: Double((v >> 16) & 0xFF) / 255,
|
||||
green: Double((v >> 8) & 0xFF) / 255,
|
||||
blue: Double(v & 0xFF) / 255
|
||||
)
|
||||
}
|
||||
|
||||
private func pal(_ c: [UInt32]) -> Palette {
|
||||
Palette(
|
||||
crust: hx(c[0]), base: hx(c[1]), mantle: hx(c[2]), surface0: hx(c[3]),
|
||||
surface1: hx(c[4]), surface2: hx(c[5]), overlay: hx(c[6]), text: hx(c[7]),
|
||||
subtext: hx(c[8]), accent: hx(c[9]), accent2: hx(c[10]), accent3: hx(c[11]),
|
||||
success: hx(c[12]), success2: hx(c[13]), warning: hx(c[14]), error: hx(c[15]),
|
||||
onAccent: hx(c[16]), node: hx(c[17]), lockedBg: hx(c[18]),
|
||||
lockedBorder: hx(c[19]), rail: hx(c[20]), finishDark: hx(c[21]),
|
||||
finishLight: hx(c[22]), finishStroke: hx(c[23])
|
||||
)
|
||||
}
|
||||
|
||||
func themePalette(_ id: ThemeId, _ mode: ColorMode) -> Palette {
|
||||
let light = mode == .light
|
||||
switch id {
|
||||
case .catppuccin:
|
||||
return light ? pal([
|
||||
0xf3eee6, 0xfaf7f2, 0xffffff, 0xffffff, 0xf0ebe3, 0xe5dfd4,
|
||||
0x8a8378, 0x1a1a1a, 0x5c574f, 0xffcc00, 0x0071e3, 0x2997ff,
|
||||
0x1f8a4c, 0x1a7f4a, 0xe6a800, 0xd32f2f, 0x1a1a1a,
|
||||
0xffffff, 0xf0ebe3, 0xd5cfc4, 0xe5dfd4, 0xf3eee6, 0xd5cfc4, 0x8a8378,
|
||||
]) : pal([
|
||||
0x000000, 0x000000, 0x111111, 0x1d1d1f, 0x2c2c2e, 0x3a3a3c,
|
||||
0x86868b, 0xf5f5f7, 0xa1a1a6, 0xffd60a, 0x2997ff, 0x64d2ff,
|
||||
0x30d158, 0x64d2ff, 0xffd60a, 0xff453a, 0x1d1d1f,
|
||||
0x1d1d1f, 0x111111, 0x3a3a3c, 0x2c2c2e, 0x000000, 0x3a3a3c, 0x86868b,
|
||||
])
|
||||
case .nord:
|
||||
return light ? pal([
|
||||
0xd8dee9, 0xeceff4, 0xe5e9f0, 0xd8dee9, 0xc7ceda, 0xb0b8c8,
|
||||
0x7b88a1, 0x2e3440, 0x4c566a, 0x5e81ac, 0x81a1c1, 0x5e81ac,
|
||||
0xa3be8c, 0x8fbcbb, 0xebcb8b, 0xbf616a, 0xeceff4,
|
||||
0xe5e9f0, 0xd8dee9, 0xc7ceda, 0xd8dee9, 0xd8dee9, 0xc7ceda, 0x7b88a1,
|
||||
]) : pal([
|
||||
0x2e3440, 0x3b4252, 0x2e3440, 0x434c5e, 0x4c566a, 0x616e88,
|
||||
0x7b88a1, 0xeceff4, 0xd8dee9, 0x88c0d0, 0x81a1c1, 0x5e81ac,
|
||||
0xa3be8c, 0x8fbcbb, 0xebcb8b, 0xbf616a, 0x2e3440,
|
||||
0x434c5e, 0x3b4252, 0x4c566a, 0x2e3440, 0x2e3440, 0x434c5e, 0x4c566a,
|
||||
])
|
||||
case .dracula:
|
||||
return light ? pal([
|
||||
0xd5d7e0, 0xf8f8f2, 0xefefea, 0xe2e2d8, 0xd0d0c4, 0xbfbfb2,
|
||||
0x9a9a8c, 0x282a36, 0x44475a, 0x7c3aed, 0xd946a6, 0x0891b2,
|
||||
0x16a34a, 0x0e7490, 0xca8a04, 0xdc2626, 0xf8f8f2,
|
||||
0xefefea, 0xe2e2d8, 0xd0d0c4, 0xe2e2d8, 0xd5d7e0, 0xd0d0c4, 0x9a9a8c,
|
||||
]) : pal([
|
||||
0x191a21, 0x282a36, 0x21222c, 0x44475a, 0x6272a4, 0x707eb0,
|
||||
0x6272a4, 0xf8f8f2, 0xbfbfb2, 0xbd93f9, 0xff79c6, 0x8be9fd,
|
||||
0x50fa7b, 0x8be9fd, 0xf1fa8c, 0xff5555, 0x282a36,
|
||||
0x383a4a, 0x2f3240, 0x44475a, 0x21222c, 0x191a21, 0x383a4a, 0x6272a4,
|
||||
])
|
||||
case .rosePine:
|
||||
return light ? pal([
|
||||
0xf2e9e1, 0xfaf4ed, 0xfffaf3, 0xf2e9e1, 0xdfdad9, 0xcecacd,
|
||||
0x9893a5, 0x575279, 0x797593, 0x907aa9, 0xd7827e, 0x56949f,
|
||||
0x286983, 0x56949f, 0xea9d34, 0xb4637a, 0xfaf4ed,
|
||||
0xfffaf3, 0xf2e9e1, 0xdfdad9, 0xf2e9e1, 0xf2e9e1, 0xdfdad9, 0x9893a5,
|
||||
]) : pal([
|
||||
0x191724, 0x1f1d2e, 0x1f1d2e, 0x26233a, 0x403d52, 0x524f67,
|
||||
0x6e6a86, 0xe0def4, 0x908caa, 0xc4a7e7, 0xebbcba, 0x9ccfd8,
|
||||
0x31748f, 0x9ccfd8, 0xf6c177, 0xeb6f92, 0x191724,
|
||||
0x26233a, 0x21202e, 0x403d52, 0x191724, 0x191724, 0x26233a, 0x524f67,
|
||||
])
|
||||
case .ocean:
|
||||
return light ? pal([
|
||||
0xd6dae8, 0xe1e2ec, 0xd5d6e2, 0xc8c9d6, 0xb4b6c5, 0x9aa0b5,
|
||||
0x7a8199, 0x2e3446, 0x4a5168, 0x2e7de9, 0x7847bd, 0x007197,
|
||||
0x387068, 0x007197, 0x8c6c3e, 0xc64343, 0xe1e2ec,
|
||||
0xd5d6e2, 0xc8c9d6, 0xb4b6c5, 0xc8c9d6, 0xd6dae8, 0xb4b6c5, 0x7a8199,
|
||||
]) : pal([
|
||||
0x16161e, 0x1a1b26, 0x16161e, 0x24283b, 0x414868, 0x565f89,
|
||||
0x565f89, 0xc0caf5, 0xa9b1d6, 0x7aa2f7, 0xbb9af7, 0x7dcfff,
|
||||
0x9ece6a, 0x73daca, 0xe0af68, 0xf7768e, 0x1a1b26,
|
||||
0x24283b, 0x1f2335, 0x3b4261, 0x16161e, 0x16161e, 0x24283b, 0x414868,
|
||||
])
|
||||
case .gruvbox:
|
||||
return light ? pal([
|
||||
0xebdbb2, 0xfbf1c7, 0xf2e5bc, 0xebdbb2, 0xd5c4a1, 0xbdae93,
|
||||
0x928374, 0x3c3836, 0x504945, 0xd65d0e, 0xb16286, 0x076678,
|
||||
0x79740e, 0x427b58, 0xb57614, 0x9d0006, 0xfbf1c7,
|
||||
0xf2e5bc, 0xebdbb2, 0xd5c4a1, 0xebdbb2, 0xebdbb2, 0xd5c4a1, 0x928374,
|
||||
]) : pal([
|
||||
0x1d2021, 0x282828, 0x1d2021, 0x3c3836, 0x504945, 0x665c54,
|
||||
0x928374, 0xebdbb2, 0xa89984, 0xfe8019, 0xd3869b, 0x83a598,
|
||||
0xb8bb26, 0x8ec07c, 0xfabd2f, 0xfb4934, 0x1d2021,
|
||||
0x3c3836, 0x32302f, 0x504945, 0x1d2021, 0x1d2021, 0x3c3836, 0x504945,
|
||||
])
|
||||
case .solarized:
|
||||
return light ? pal([
|
||||
0xeee8d5, 0xfdf6e3, 0xeee8d5, 0xeee8d5, 0xe2dbc6, 0xc9c0a6,
|
||||
0x657b83, 0x586e75, 0x657b83, 0x268bd2, 0x6c71c4, 0x2aa198,
|
||||
0x859900, 0x2aa198, 0xb58900, 0xdc322f, 0xfdf6e3,
|
||||
0xeee8d5, 0xe6dfc8, 0x93a1a1, 0xeee8d5, 0xeee8d5, 0x93a1a1, 0x586e75,
|
||||
]) : pal([
|
||||
0x002b36, 0x073642, 0x002b36, 0x586e75, 0x657b83, 0x839496,
|
||||
0x93a1a1, 0xfdf6e3, 0x93a1a1, 0x268bd2, 0x6c71c4, 0x2aa198,
|
||||
0x859900, 0x2aa198, 0xb58900, 0xdc322f, 0x002b36,
|
||||
0x073642, 0x002b36, 0x586e75, 0x002b36, 0x002b36, 0x073642, 0x586e75,
|
||||
])
|
||||
case .everforest:
|
||||
return light ? pal([
|
||||
0xe6e2cc, 0xfdf6e3, 0xf4f0d9, 0xefebd4, 0xe0dcc7, 0xa6b0a0,
|
||||
0x939f91, 0x5c6a72, 0x829181, 0x8da101, 0xdf69ba, 0x35a77c,
|
||||
0x8da101, 0x35a77c, 0xdfa000, 0xf85552, 0xfdf6e3,
|
||||
0xf4f0d9, 0xefebd4, 0xe0dcc7, 0xe6e2cc, 0xe6e2cc, 0xe0dcc7, 0x939f91,
|
||||
]) : pal([
|
||||
0x1e2326, 0x272e33, 0x2d353b, 0x374145, 0x4f5b58, 0x7a8478,
|
||||
0x859289, 0xd3c6aa, 0xa7c080, 0xa7c080, 0xd699b6, 0x7fbbb3,
|
||||
0xa7c080, 0x83c092, 0xdbbc7f, 0xe67e80, 0x272e33,
|
||||
0x374145, 0x2d353b, 0x4f5b58, 0x1e2326, 0x1e2326, 0x374145, 0x4f5b58,
|
||||
])
|
||||
case .monokai:
|
||||
return light ? pal([
|
||||
0xe6e3d4, 0xfaf8f0, 0xf3f0e4, 0xe8e4d4, 0xd6d2c0, 0xb8b49e,
|
||||
0x8a8674, 0x2d2a2e, 0x5b5854, 0xe14775, 0x7c5cbf, 0x1c7d9b,
|
||||
0x5b8c2a, 0x1c7d9b, 0xb08900, 0xe14775, 0xfaf8f0,
|
||||
0xf3f0e4, 0xe8e4d4, 0xd6d2c0, 0xe6e3d4, 0xe6e3d4, 0xd6d2c0, 0x8a8674,
|
||||
]) : pal([
|
||||
0x1d1e19, 0x272822, 0x1e1f1a, 0x3e3d32, 0x49483e, 0x75715e,
|
||||
0x75715e, 0xf8f8f2, 0xa59f85, 0xf92672, 0xae81ff, 0x66d9ef,
|
||||
0xa6e22e, 0xa1efe4, 0xe6db74, 0xf92672, 0x272822,
|
||||
0x3e3d32, 0x2e2f29, 0x49483e, 0x1d1e19, 0x1d1e19, 0x3e3d32, 0x49483e,
|
||||
])
|
||||
case .oneDark:
|
||||
return light ? pal([
|
||||
0xe5e5e6, 0xfafafa, 0xf0f0f0, 0xe5e5e6, 0xd0d0d2, 0xa0a1a7,
|
||||
0xa0a1a7, 0x383a42, 0x696c77, 0xa626a4, 0x4078f2, 0x0184bc,
|
||||
0x50a14f, 0x0184bc, 0xc18401, 0xe45649, 0xfafafa,
|
||||
0xf0f0f0, 0xe5e5e6, 0xd0d0d2, 0xe5e5e6, 0xe5e5e6, 0xd0d0d2, 0xa0a1a7,
|
||||
]) : pal([
|
||||
0x21252b, 0x282c34, 0x21252b, 0x3b4048, 0x4b5263, 0x5c6370,
|
||||
0x5c6370, 0xabb2bf, 0x7f848e, 0xc678dd, 0x61afef, 0x56b6c2,
|
||||
0x98c379, 0x56b6c2, 0xe5c07b, 0xe06c75, 0x282c34,
|
||||
0x3b4048, 0x2c313a, 0x4b5263, 0x21252b, 0x21252b, 0x3b4048, 0x4b5263,
|
||||
])
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue