1use serde::Serialize;
4
5#[derive(Clone, Copy, Debug, Serialize)]
8pub struct Skin {
9 pub id: &'static str,
10 pub name: &'static str,
11 pub logo: &'static str,
13 pub description: &'static str,
14 pub scheme: Scheme,
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
20#[serde(rename_all = "snake_case")]
21pub enum Scheme {
22 Light,
23 Dark,
24 System,
26}
27
28impl Scheme {
29 pub fn as_str(self) -> &'static str {
30 match self {
31 Scheme::Light => "light",
32 Scheme::Dark => "dark",
33 Scheme::System => "system",
34 }
35 }
36}
37
38pub const DEFAULT_SKIN: &str = "teamcraft";
39
40pub const TEAMCRAFT_ICON: &str = "logos/TeamCraft_Icon.svg";
42
43pub const SKINS: [Skin; 10] = [
44 Skin {
45 id: "teamcraft",
46 name: "TeamCraft",
47 logo: TEAMCRAFT_ICON,
48 description: "Follows your system: light or dark",
49 scheme: Scheme::System,
50 },
51 Skin {
52 id: "teamcraft-day",
53 name: "TeamCraft Light",
54 logo: TEAMCRAFT_ICON,
55 description: "House style, light",
56 scheme: Scheme::Light,
57 },
58 Skin {
59 id: "teamcraft-night",
60 name: "TeamCraft Dark",
61 logo: TEAMCRAFT_ICON,
62 description: "House style, dark",
63 scheme: Scheme::Dark,
64 },
65 Skin {
66 id: "arch",
67 name: "Arch",
68 logo: TEAMCRAFT_ICON,
69 description: "Blueprint grid",
70 scheme: Scheme::Dark,
71 },
72 Skin {
73 id: "cachyos",
74 name: "CachyOS",
75 logo: TEAMCRAFT_ICON,
76 description: "Teal dot matrix",
77 scheme: Scheme::Dark,
78 },
79 Skin {
80 id: "endeavouros",
81 name: "EndeavourOS",
82 logo: TEAMCRAFT_ICON,
83 description: "Purple sunset",
84 scheme: Scheme::Dark,
85 },
86 Skin {
87 id: "kde",
88 name: "KDE",
89 logo: TEAMCRAFT_ICON,
90 description: "Breeze dark",
91 scheme: Scheme::Dark,
92 },
93 Skin {
94 id: "kubuntu",
95 name: "Kubuntu",
96 logo: TEAMCRAFT_ICON,
97 description: "Blue rings",
98 scheme: Scheme::Dark,
99 },
100 Skin {
101 id: "opensuse",
102 name: "openSUSE",
103 logo: TEAMCRAFT_ICON,
104 description: "Chameleon scales",
105 scheme: Scheme::Dark,
106 },
107 Skin {
108 id: "ubuntu",
109 name: "Ubuntu",
110 logo: TEAMCRAFT_ICON,
111 description: "Circle of friends",
112 scheme: Scheme::Dark,
113 },
114];
115
116pub fn skin_or_default(id: &str) -> &'static str {
118 let id = id.trim();
119 SKINS
120 .iter()
121 .find(|s| s.id == id)
122 .map(|s| s.id)
123 .unwrap_or(DEFAULT_SKIN)
124}
125
126pub fn is_skin(id: &str) -> bool {
127 SKINS.iter().any(|s| s.id == id)
128}
129
130pub fn skin_scheme(id: &str) -> Scheme {
132 let id = skin_or_default(id);
133 SKINS
134 .iter()
135 .find(|s| s.id == id)
136 .map(|s| s.scheme)
137 .unwrap_or(Scheme::System)
138}
139
140pub fn initials(display_name: &str, username: &str) -> String {
143 let source = if display_name.trim().is_empty() {
144 username
145 } else {
146 display_name
147 };
148 let words: Vec<&str> = source.split_whitespace().collect();
149 let first = |w: &str| {
150 w.chars()
151 .next()
152 .map(|c| c.to_uppercase().collect::<String>())
153 };
154 match words.as_slice() {
155 [] => "?".to_string(),
156 [one] => first(one).unwrap_or_default(),
157 [a, .., b] => format!(
158 "{}{}",
159 first(a).unwrap_or_default(),
160 first(b).unwrap_or_default()
161 ),
162 }
163}
164
165pub fn avatar_tint(username: &str) -> u32 {
167 let hash = username.bytes().fold(0x811c_9dc5_u32, |h, b| {
169 (h ^ u32::from(b)).wrapping_mul(0x0100_0193)
170 });
171 hash % 6 + 1
172}
173
174pub fn skin_is_light(id: &str) -> bool {
176 skin_scheme(id) == Scheme::Light
177}