diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..f2104ce
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..cb89205
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1780774218610
+
+
+ 1780774218610
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/yali-rs.iml b/.idea/yali-rs.iml
new file mode 100644
index 0000000..cf84ae4
--- /dev/null
+++ b/.idea/yali-rs.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..2b73450
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "rust-analyzer.checkOnSave": false
+}
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index abc32cb..09de98f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,8 +4,8 @@ version = "4.0.0"
edition = "2024"
[dependencies]
-eframe = "0.27"
-egui_extras = { version = "0.27", features = ["image", "file"] }
+eframe = { version = "0.27", features = ["default", "wgpu"] }
+egui_extras = { version = "0.27", features = ["image", "file", "svg"] }
image = { version = "0.24", features = ["png"] }
serde = { version = "1.0", features = ["derive"] }
toml = "0.8" # answer file ayrıştırma
diff --git a/assets/disk.png b/assets/disk.png
new file mode 100644
index 0000000..b260e73
Binary files /dev/null and b/assets/disk.png differ
diff --git a/assets/flags/ad.svg b/assets/flags/ad.svg
new file mode 100644
index 0000000..199ff19
--- /dev/null
+++ b/assets/flags/ad.svg
@@ -0,0 +1,150 @@
+
diff --git a/assets/flags/ae.svg b/assets/flags/ae.svg
new file mode 100644
index 0000000..651ac85
--- /dev/null
+++ b/assets/flags/ae.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/af.svg b/assets/flags/af.svg
new file mode 100644
index 0000000..4dbe455
--- /dev/null
+++ b/assets/flags/af.svg
@@ -0,0 +1,81 @@
+
diff --git a/assets/flags/ag.svg b/assets/flags/ag.svg
new file mode 100644
index 0000000..243c3d8
--- /dev/null
+++ b/assets/flags/ag.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/ai.svg b/assets/flags/ai.svg
new file mode 100644
index 0000000..9c2ea33
--- /dev/null
+++ b/assets/flags/ai.svg
@@ -0,0 +1,29 @@
+
diff --git a/assets/flags/al.svg b/assets/flags/al.svg
new file mode 100644
index 0000000..e85d95f
--- /dev/null
+++ b/assets/flags/al.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/am.svg b/assets/flags/am.svg
new file mode 100644
index 0000000..99fa4dc
--- /dev/null
+++ b/assets/flags/am.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/ao.svg b/assets/flags/ao.svg
new file mode 100644
index 0000000..b73b1ec
--- /dev/null
+++ b/assets/flags/ao.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/aq.svg b/assets/flags/aq.svg
new file mode 100644
index 0000000..c7e3536
--- /dev/null
+++ b/assets/flags/aq.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/ar.svg b/assets/flags/ar.svg
new file mode 100644
index 0000000..c753da1
--- /dev/null
+++ b/assets/flags/ar.svg
@@ -0,0 +1,32 @@
+
diff --git a/assets/flags/arab.svg b/assets/flags/arab.svg
new file mode 100644
index 0000000..9ef079f
--- /dev/null
+++ b/assets/flags/arab.svg
@@ -0,0 +1,109 @@
+
diff --git a/assets/flags/as.svg b/assets/flags/as.svg
new file mode 100644
index 0000000..82459de
--- /dev/null
+++ b/assets/flags/as.svg
@@ -0,0 +1,72 @@
+
diff --git a/assets/flags/asean.svg b/assets/flags/asean.svg
new file mode 100644
index 0000000..189ae02
--- /dev/null
+++ b/assets/flags/asean.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/at.svg b/assets/flags/at.svg
new file mode 100644
index 0000000..9d2775c
--- /dev/null
+++ b/assets/flags/at.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/au.svg b/assets/flags/au.svg
new file mode 100644
index 0000000..96e8076
--- /dev/null
+++ b/assets/flags/au.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/aw.svg b/assets/flags/aw.svg
new file mode 100644
index 0000000..413b7c4
--- /dev/null
+++ b/assets/flags/aw.svg
@@ -0,0 +1,186 @@
+
diff --git a/assets/flags/ax.svg b/assets/flags/ax.svg
new file mode 100644
index 0000000..0584d71
--- /dev/null
+++ b/assets/flags/ax.svg
@@ -0,0 +1,18 @@
+
diff --git a/assets/flags/az.svg b/assets/flags/az.svg
new file mode 100644
index 0000000..3557522
--- /dev/null
+++ b/assets/flags/az.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/ba.svg b/assets/flags/ba.svg
new file mode 100644
index 0000000..93bd9cf
--- /dev/null
+++ b/assets/flags/ba.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/flags/bb.svg b/assets/flags/bb.svg
new file mode 100644
index 0000000..cecd5cc
--- /dev/null
+++ b/assets/flags/bb.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/bd.svg b/assets/flags/bd.svg
new file mode 100644
index 0000000..16b794d
--- /dev/null
+++ b/assets/flags/bd.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/be.svg b/assets/flags/be.svg
new file mode 100644
index 0000000..ac706a0
--- /dev/null
+++ b/assets/flags/be.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/bf.svg b/assets/flags/bf.svg
new file mode 100644
index 0000000..4713822
--- /dev/null
+++ b/assets/flags/bf.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/bg.svg b/assets/flags/bg.svg
new file mode 100644
index 0000000..af2d0d0
--- /dev/null
+++ b/assets/flags/bg.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/bh.svg b/assets/flags/bh.svg
new file mode 100644
index 0000000..7a2ea54
--- /dev/null
+++ b/assets/flags/bh.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/bi.svg b/assets/flags/bi.svg
new file mode 100644
index 0000000..a4434a9
--- /dev/null
+++ b/assets/flags/bi.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/bj.svg b/assets/flags/bj.svg
new file mode 100644
index 0000000..0846724
--- /dev/null
+++ b/assets/flags/bj.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/bl.svg b/assets/flags/bl.svg
new file mode 100644
index 0000000..f84cbba
--- /dev/null
+++ b/assets/flags/bl.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/bm.svg b/assets/flags/bm.svg
new file mode 100644
index 0000000..f43a5eb
--- /dev/null
+++ b/assets/flags/bm.svg
@@ -0,0 +1,97 @@
+
diff --git a/assets/flags/bn.svg b/assets/flags/bn.svg
new file mode 100644
index 0000000..f544c25
--- /dev/null
+++ b/assets/flags/bn.svg
@@ -0,0 +1,36 @@
+
diff --git a/assets/flags/bo.svg b/assets/flags/bo.svg
new file mode 100644
index 0000000..7658e3f
--- /dev/null
+++ b/assets/flags/bo.svg
@@ -0,0 +1,673 @@
+
diff --git a/assets/flags/bq.svg b/assets/flags/bq.svg
new file mode 100644
index 0000000..0e6bc76
--- /dev/null
+++ b/assets/flags/bq.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/br.svg b/assets/flags/br.svg
new file mode 100644
index 0000000..719a763
--- /dev/null
+++ b/assets/flags/br.svg
@@ -0,0 +1,45 @@
+
diff --git a/assets/flags/bs.svg b/assets/flags/bs.svg
new file mode 100644
index 0000000..5cc918e
--- /dev/null
+++ b/assets/flags/bs.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/bt.svg b/assets/flags/bt.svg
new file mode 100644
index 0000000..20aef3a
--- /dev/null
+++ b/assets/flags/bt.svg
@@ -0,0 +1,89 @@
+
diff --git a/assets/flags/bv.svg b/assets/flags/bv.svg
new file mode 100644
index 0000000..40e16d9
--- /dev/null
+++ b/assets/flags/bv.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/bw.svg b/assets/flags/bw.svg
new file mode 100644
index 0000000..3435608
--- /dev/null
+++ b/assets/flags/bw.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/by.svg b/assets/flags/by.svg
new file mode 100644
index 0000000..948784f
--- /dev/null
+++ b/assets/flags/by.svg
@@ -0,0 +1,18 @@
+
diff --git a/assets/flags/bz.svg b/assets/flags/bz.svg
new file mode 100644
index 0000000..d81b16c
--- /dev/null
+++ b/assets/flags/bz.svg
@@ -0,0 +1,145 @@
+
diff --git a/assets/flags/ca.svg b/assets/flags/ca.svg
new file mode 100644
index 0000000..c9b23b4
--- /dev/null
+++ b/assets/flags/ca.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/cc.svg b/assets/flags/cc.svg
new file mode 100644
index 0000000..a42dec6
--- /dev/null
+++ b/assets/flags/cc.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/flags/cd.svg b/assets/flags/cd.svg
new file mode 100644
index 0000000..b9cf528
--- /dev/null
+++ b/assets/flags/cd.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/cefta.svg b/assets/flags/cefta.svg
new file mode 100644
index 0000000..f748d08
--- /dev/null
+++ b/assets/flags/cefta.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/cf.svg b/assets/flags/cf.svg
new file mode 100644
index 0000000..a6cd367
--- /dev/null
+++ b/assets/flags/cf.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/cg.svg b/assets/flags/cg.svg
new file mode 100644
index 0000000..f5a0e42
--- /dev/null
+++ b/assets/flags/cg.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/flags/ch.svg b/assets/flags/ch.svg
new file mode 100644
index 0000000..b42d670
--- /dev/null
+++ b/assets/flags/ch.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/ci.svg b/assets/flags/ci.svg
new file mode 100644
index 0000000..e400f0c
--- /dev/null
+++ b/assets/flags/ci.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/ck.svg b/assets/flags/ck.svg
new file mode 100644
index 0000000..18e547b
--- /dev/null
+++ b/assets/flags/ck.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/cl.svg b/assets/flags/cl.svg
new file mode 100644
index 0000000..5b3c72f
--- /dev/null
+++ b/assets/flags/cl.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/cm.svg b/assets/flags/cm.svg
new file mode 100644
index 0000000..70adc8b
--- /dev/null
+++ b/assets/flags/cm.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/cn.svg b/assets/flags/cn.svg
new file mode 100644
index 0000000..10d3489
--- /dev/null
+++ b/assets/flags/cn.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/flags/co.svg b/assets/flags/co.svg
new file mode 100644
index 0000000..ebd0a0f
--- /dev/null
+++ b/assets/flags/co.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/cp.svg b/assets/flags/cp.svg
new file mode 100644
index 0000000..b8aa9cf
--- /dev/null
+++ b/assets/flags/cp.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/cr.svg b/assets/flags/cr.svg
new file mode 100644
index 0000000..5a409ee
--- /dev/null
+++ b/assets/flags/cr.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/cu.svg b/assets/flags/cu.svg
new file mode 100644
index 0000000..053c9ee
--- /dev/null
+++ b/assets/flags/cu.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/cv.svg b/assets/flags/cv.svg
new file mode 100644
index 0000000..aec8994
--- /dev/null
+++ b/assets/flags/cv.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/cw.svg b/assets/flags/cw.svg
new file mode 100644
index 0000000..bb0ece2
--- /dev/null
+++ b/assets/flags/cw.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/cx.svg b/assets/flags/cx.svg
new file mode 100644
index 0000000..3a83c23
--- /dev/null
+++ b/assets/flags/cx.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/cy.svg b/assets/flags/cy.svg
new file mode 100644
index 0000000..ee4b0c7
--- /dev/null
+++ b/assets/flags/cy.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/cz.svg b/assets/flags/cz.svg
new file mode 100644
index 0000000..7913de3
--- /dev/null
+++ b/assets/flags/cz.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/de.svg b/assets/flags/de.svg
new file mode 100644
index 0000000..71aa2d2
--- /dev/null
+++ b/assets/flags/de.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/dg.svg b/assets/flags/dg.svg
new file mode 100644
index 0000000..dfee2bb
--- /dev/null
+++ b/assets/flags/dg.svg
@@ -0,0 +1,130 @@
+
diff --git a/assets/flags/dj.svg b/assets/flags/dj.svg
new file mode 100644
index 0000000..9b00a82
--- /dev/null
+++ b/assets/flags/dj.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/dk.svg b/assets/flags/dk.svg
new file mode 100644
index 0000000..563277f
--- /dev/null
+++ b/assets/flags/dk.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/dm.svg b/assets/flags/dm.svg
new file mode 100644
index 0000000..5aa9cea
--- /dev/null
+++ b/assets/flags/dm.svg
@@ -0,0 +1,152 @@
+
diff --git a/assets/flags/do.svg b/assets/flags/do.svg
new file mode 100644
index 0000000..6de2b26
--- /dev/null
+++ b/assets/flags/do.svg
@@ -0,0 +1,121 @@
+
diff --git a/assets/flags/dz.svg b/assets/flags/dz.svg
new file mode 100644
index 0000000..5ff29a7
--- /dev/null
+++ b/assets/flags/dz.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/eac.svg b/assets/flags/eac.svg
new file mode 100644
index 0000000..59d02d2
--- /dev/null
+++ b/assets/flags/eac.svg
@@ -0,0 +1,48 @@
+
diff --git a/assets/flags/ec.svg b/assets/flags/ec.svg
new file mode 100644
index 0000000..88c50bf
--- /dev/null
+++ b/assets/flags/ec.svg
@@ -0,0 +1,138 @@
+
diff --git a/assets/flags/ee.svg b/assets/flags/ee.svg
new file mode 100644
index 0000000..8b98c2c
--- /dev/null
+++ b/assets/flags/ee.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/eg.svg b/assets/flags/eg.svg
new file mode 100644
index 0000000..88e32b3
--- /dev/null
+++ b/assets/flags/eg.svg
@@ -0,0 +1,38 @@
+
diff --git a/assets/flags/eh.svg b/assets/flags/eh.svg
new file mode 100644
index 0000000..6aec728
--- /dev/null
+++ b/assets/flags/eh.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/flags/er.svg b/assets/flags/er.svg
new file mode 100644
index 0000000..48a13b4
--- /dev/null
+++ b/assets/flags/er.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/es-ct.svg b/assets/flags/es-ct.svg
new file mode 100644
index 0000000..4d85911
--- /dev/null
+++ b/assets/flags/es-ct.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/es-ga.svg b/assets/flags/es-ga.svg
new file mode 100644
index 0000000..573ca45
--- /dev/null
+++ b/assets/flags/es-ga.svg
@@ -0,0 +1,187 @@
+
diff --git a/assets/flags/es-pv.svg b/assets/flags/es-pv.svg
new file mode 100644
index 0000000..63c19f4
--- /dev/null
+++ b/assets/flags/es-pv.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/es.svg b/assets/flags/es.svg
new file mode 100644
index 0000000..a296ebf
--- /dev/null
+++ b/assets/flags/es.svg
@@ -0,0 +1,544 @@
+
diff --git a/assets/flags/et.svg b/assets/flags/et.svg
new file mode 100644
index 0000000..3f99be4
--- /dev/null
+++ b/assets/flags/et.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/eu.svg b/assets/flags/eu.svg
new file mode 100644
index 0000000..b0874c1
--- /dev/null
+++ b/assets/flags/eu.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/flags/fi.svg b/assets/flags/fi.svg
new file mode 100644
index 0000000..470be2d
--- /dev/null
+++ b/assets/flags/fi.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/fj.svg b/assets/flags/fj.svg
new file mode 100644
index 0000000..332ae61
--- /dev/null
+++ b/assets/flags/fj.svg
@@ -0,0 +1,120 @@
+
diff --git a/assets/flags/fk.svg b/assets/flags/fk.svg
new file mode 100644
index 0000000..a0dace8
--- /dev/null
+++ b/assets/flags/fk.svg
@@ -0,0 +1,90 @@
+
diff --git a/assets/flags/fm.svg b/assets/flags/fm.svg
new file mode 100644
index 0000000..c1b7c97
--- /dev/null
+++ b/assets/flags/fm.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/flags/fo.svg b/assets/flags/fo.svg
new file mode 100644
index 0000000..f802d28
--- /dev/null
+++ b/assets/flags/fo.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/flags/fr.svg b/assets/flags/fr.svg
new file mode 100644
index 0000000..e682b90
--- /dev/null
+++ b/assets/flags/fr.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/ga.svg b/assets/flags/ga.svg
new file mode 100644
index 0000000..76edab4
--- /dev/null
+++ b/assets/flags/ga.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/gb-eng.svg b/assets/flags/gb-eng.svg
new file mode 100644
index 0000000..12e3b67
--- /dev/null
+++ b/assets/flags/gb-eng.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/gb-nir.svg b/assets/flags/gb-nir.svg
new file mode 100644
index 0000000..e22190a
--- /dev/null
+++ b/assets/flags/gb-nir.svg
@@ -0,0 +1,132 @@
+
diff --git a/assets/flags/gb-sct.svg b/assets/flags/gb-sct.svg
new file mode 100644
index 0000000..f50cd32
--- /dev/null
+++ b/assets/flags/gb-sct.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/gb-wls.svg b/assets/flags/gb-wls.svg
new file mode 100644
index 0000000..d7f5791
--- /dev/null
+++ b/assets/flags/gb-wls.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/gb.svg b/assets/flags/gb.svg
new file mode 100644
index 0000000..7991383
--- /dev/null
+++ b/assets/flags/gb.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/gd.svg b/assets/flags/gd.svg
new file mode 100644
index 0000000..b3d250d
--- /dev/null
+++ b/assets/flags/gd.svg
@@ -0,0 +1,27 @@
+
diff --git a/assets/flags/ge.svg b/assets/flags/ge.svg
new file mode 100644
index 0000000..ab08a9a
--- /dev/null
+++ b/assets/flags/ge.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/gf.svg b/assets/flags/gf.svg
new file mode 100644
index 0000000..f8fe94c
--- /dev/null
+++ b/assets/flags/gf.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/gg.svg b/assets/flags/gg.svg
new file mode 100644
index 0000000..f8216c8
--- /dev/null
+++ b/assets/flags/gg.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/gh.svg b/assets/flags/gh.svg
new file mode 100644
index 0000000..5c3e3e6
--- /dev/null
+++ b/assets/flags/gh.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/gi.svg b/assets/flags/gi.svg
new file mode 100644
index 0000000..a5d7570
--- /dev/null
+++ b/assets/flags/gi.svg
@@ -0,0 +1,32 @@
+
diff --git a/assets/flags/gl.svg b/assets/flags/gl.svg
new file mode 100644
index 0000000..eb5a52e
--- /dev/null
+++ b/assets/flags/gl.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/gm.svg b/assets/flags/gm.svg
new file mode 100644
index 0000000..8fe9d66
--- /dev/null
+++ b/assets/flags/gm.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/gn.svg b/assets/flags/gn.svg
new file mode 100644
index 0000000..40d6ad4
--- /dev/null
+++ b/assets/flags/gn.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/gp.svg b/assets/flags/gp.svg
new file mode 100644
index 0000000..ee55c4b
--- /dev/null
+++ b/assets/flags/gp.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/gq.svg b/assets/flags/gq.svg
new file mode 100644
index 0000000..64c8eb2
--- /dev/null
+++ b/assets/flags/gq.svg
@@ -0,0 +1,23 @@
+
diff --git a/assets/flags/gr.svg b/assets/flags/gr.svg
new file mode 100644
index 0000000..599741e
--- /dev/null
+++ b/assets/flags/gr.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/flags/gs.svg b/assets/flags/gs.svg
new file mode 100644
index 0000000..29db9b9
--- /dev/null
+++ b/assets/flags/gs.svg
@@ -0,0 +1,133 @@
+
diff --git a/assets/flags/gt.svg b/assets/flags/gt.svg
new file mode 100644
index 0000000..7df9df5
--- /dev/null
+++ b/assets/flags/gt.svg
@@ -0,0 +1,204 @@
+
diff --git a/assets/flags/gu.svg b/assets/flags/gu.svg
new file mode 100644
index 0000000..3b95219
--- /dev/null
+++ b/assets/flags/gu.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/flags/gw.svg b/assets/flags/gw.svg
new file mode 100644
index 0000000..d470bac
--- /dev/null
+++ b/assets/flags/gw.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/gy.svg b/assets/flags/gy.svg
new file mode 100644
index 0000000..569fb56
--- /dev/null
+++ b/assets/flags/gy.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/hk.svg b/assets/flags/hk.svg
new file mode 100644
index 0000000..4fd55bc
--- /dev/null
+++ b/assets/flags/hk.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/hm.svg b/assets/flags/hm.svg
new file mode 100644
index 0000000..815c482
--- /dev/null
+++ b/assets/flags/hm.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/hn.svg b/assets/flags/hn.svg
new file mode 100644
index 0000000..11fde67
--- /dev/null
+++ b/assets/flags/hn.svg
@@ -0,0 +1,18 @@
+
diff --git a/assets/flags/hr.svg b/assets/flags/hr.svg
new file mode 100644
index 0000000..dde825c
--- /dev/null
+++ b/assets/flags/hr.svg
@@ -0,0 +1,58 @@
+
diff --git a/assets/flags/ht.svg b/assets/flags/ht.svg
new file mode 100644
index 0000000..8e8efc4
--- /dev/null
+++ b/assets/flags/ht.svg
@@ -0,0 +1,116 @@
+
diff --git a/assets/flags/hu.svg b/assets/flags/hu.svg
new file mode 100644
index 0000000..24fbfb9
--- /dev/null
+++ b/assets/flags/hu.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/ic.svg b/assets/flags/ic.svg
new file mode 100644
index 0000000..81e6ee2
--- /dev/null
+++ b/assets/flags/ic.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/id.svg b/assets/flags/id.svg
new file mode 100644
index 0000000..3b7c8fc
--- /dev/null
+++ b/assets/flags/id.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/ie.svg b/assets/flags/ie.svg
new file mode 100644
index 0000000..049be14
--- /dev/null
+++ b/assets/flags/ie.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/il.svg b/assets/flags/il.svg
new file mode 100644
index 0000000..f43be7e
--- /dev/null
+++ b/assets/flags/il.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/im.svg b/assets/flags/im.svg
new file mode 100644
index 0000000..fe6a59a
--- /dev/null
+++ b/assets/flags/im.svg
@@ -0,0 +1,36 @@
+
diff --git a/assets/flags/in.svg b/assets/flags/in.svg
new file mode 100644
index 0000000..bc47d74
--- /dev/null
+++ b/assets/flags/in.svg
@@ -0,0 +1,25 @@
+
diff --git a/assets/flags/io.svg b/assets/flags/io.svg
new file mode 100644
index 0000000..3058f7d
--- /dev/null
+++ b/assets/flags/io.svg
@@ -0,0 +1,130 @@
+
diff --git a/assets/flags/iq.svg b/assets/flags/iq.svg
new file mode 100644
index 0000000..8044514
--- /dev/null
+++ b/assets/flags/iq.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/flags/ir.svg b/assets/flags/ir.svg
new file mode 100644
index 0000000..8c6d516
--- /dev/null
+++ b/assets/flags/ir.svg
@@ -0,0 +1,219 @@
+
diff --git a/assets/flags/is.svg b/assets/flags/is.svg
new file mode 100644
index 0000000..a6588af
--- /dev/null
+++ b/assets/flags/is.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/flags/it.svg b/assets/flags/it.svg
new file mode 100644
index 0000000..20a8bfd
--- /dev/null
+++ b/assets/flags/it.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/je.svg b/assets/flags/je.svg
new file mode 100644
index 0000000..70a8754
--- /dev/null
+++ b/assets/flags/je.svg
@@ -0,0 +1,62 @@
+
diff --git a/assets/flags/jm.svg b/assets/flags/jm.svg
new file mode 100644
index 0000000..269df03
--- /dev/null
+++ b/assets/flags/jm.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/jo.svg b/assets/flags/jo.svg
new file mode 100644
index 0000000..d6f927d
--- /dev/null
+++ b/assets/flags/jo.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/flags/jp.svg b/assets/flags/jp.svg
new file mode 100644
index 0000000..cc1c181
--- /dev/null
+++ b/assets/flags/jp.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/flags/ke.svg b/assets/flags/ke.svg
new file mode 100644
index 0000000..3a67ca3
--- /dev/null
+++ b/assets/flags/ke.svg
@@ -0,0 +1,23 @@
+
diff --git a/assets/flags/kg.svg b/assets/flags/kg.svg
new file mode 100644
index 0000000..e26db95
--- /dev/null
+++ b/assets/flags/kg.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/kh.svg b/assets/flags/kh.svg
new file mode 100644
index 0000000..a7d52f2
--- /dev/null
+++ b/assets/flags/kh.svg
@@ -0,0 +1,61 @@
+
diff --git a/assets/flags/ki.svg b/assets/flags/ki.svg
new file mode 100644
index 0000000..fda03f3
--- /dev/null
+++ b/assets/flags/ki.svg
@@ -0,0 +1,36 @@
+
diff --git a/assets/flags/km.svg b/assets/flags/km.svg
new file mode 100644
index 0000000..414d65e
--- /dev/null
+++ b/assets/flags/km.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/flags/kn.svg b/assets/flags/kn.svg
new file mode 100644
index 0000000..47fe64d
--- /dev/null
+++ b/assets/flags/kn.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/kp.svg b/assets/flags/kp.svg
new file mode 100644
index 0000000..ad1b713
--- /dev/null
+++ b/assets/flags/kp.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/kr.svg b/assets/flags/kr.svg
new file mode 100644
index 0000000..6947eab
--- /dev/null
+++ b/assets/flags/kr.svg
@@ -0,0 +1,24 @@
+
diff --git a/assets/flags/kw.svg b/assets/flags/kw.svg
new file mode 100644
index 0000000..3dd89e9
--- /dev/null
+++ b/assets/flags/kw.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/ky.svg b/assets/flags/ky.svg
new file mode 100644
index 0000000..aeaa7e0
--- /dev/null
+++ b/assets/flags/ky.svg
@@ -0,0 +1,103 @@
+
diff --git a/assets/flags/kz.svg b/assets/flags/kz.svg
new file mode 100644
index 0000000..2fac45b
--- /dev/null
+++ b/assets/flags/kz.svg
@@ -0,0 +1,36 @@
+
diff --git a/assets/flags/la.svg b/assets/flags/la.svg
new file mode 100644
index 0000000..6aea6b7
--- /dev/null
+++ b/assets/flags/la.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/flags/lb.svg b/assets/flags/lb.svg
new file mode 100644
index 0000000..bde2581
--- /dev/null
+++ b/assets/flags/lb.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/lc.svg b/assets/flags/lc.svg
new file mode 100644
index 0000000..bb25654
--- /dev/null
+++ b/assets/flags/lc.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/li.svg b/assets/flags/li.svg
new file mode 100644
index 0000000..7a4d183
--- /dev/null
+++ b/assets/flags/li.svg
@@ -0,0 +1,43 @@
+
diff --git a/assets/flags/lk.svg b/assets/flags/lk.svg
new file mode 100644
index 0000000..cbd660a
--- /dev/null
+++ b/assets/flags/lk.svg
@@ -0,0 +1,22 @@
+
diff --git a/assets/flags/lr.svg b/assets/flags/lr.svg
new file mode 100644
index 0000000..e482ab9
--- /dev/null
+++ b/assets/flags/lr.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/ls.svg b/assets/flags/ls.svg
new file mode 100644
index 0000000..a7c01a9
--- /dev/null
+++ b/assets/flags/ls.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/lt.svg b/assets/flags/lt.svg
new file mode 100644
index 0000000..90ec5d2
--- /dev/null
+++ b/assets/flags/lt.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/lu.svg b/assets/flags/lu.svg
new file mode 100644
index 0000000..cc12206
--- /dev/null
+++ b/assets/flags/lu.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/lv.svg b/assets/flags/lv.svg
new file mode 100644
index 0000000..f6decec
--- /dev/null
+++ b/assets/flags/lv.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/ly.svg b/assets/flags/ly.svg
new file mode 100644
index 0000000..1eaa51e
--- /dev/null
+++ b/assets/flags/ly.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/ma.svg b/assets/flags/ma.svg
new file mode 100644
index 0000000..7ce56ef
--- /dev/null
+++ b/assets/flags/ma.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/mc.svg b/assets/flags/mc.svg
new file mode 100644
index 0000000..9cb6c9e
--- /dev/null
+++ b/assets/flags/mc.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/md.svg b/assets/flags/md.svg
new file mode 100644
index 0000000..e9ba506
--- /dev/null
+++ b/assets/flags/md.svg
@@ -0,0 +1,70 @@
+
diff --git a/assets/flags/me.svg b/assets/flags/me.svg
new file mode 100644
index 0000000..297888c
--- /dev/null
+++ b/assets/flags/me.svg
@@ -0,0 +1,116 @@
+
diff --git a/assets/flags/mf.svg b/assets/flags/mf.svg
new file mode 100644
index 0000000..6305edc
--- /dev/null
+++ b/assets/flags/mf.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/mg.svg b/assets/flags/mg.svg
new file mode 100644
index 0000000..5fa2d24
--- /dev/null
+++ b/assets/flags/mg.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/mh.svg b/assets/flags/mh.svg
new file mode 100644
index 0000000..7b9f490
--- /dev/null
+++ b/assets/flags/mh.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/mk.svg b/assets/flags/mk.svg
new file mode 100644
index 0000000..4f5cae7
--- /dev/null
+++ b/assets/flags/mk.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/ml.svg b/assets/flags/ml.svg
new file mode 100644
index 0000000..6f6b716
--- /dev/null
+++ b/assets/flags/ml.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/mm.svg b/assets/flags/mm.svg
new file mode 100644
index 0000000..42b4dee
--- /dev/null
+++ b/assets/flags/mm.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/flags/mn.svg b/assets/flags/mn.svg
new file mode 100644
index 0000000..6a38a71
--- /dev/null
+++ b/assets/flags/mn.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/mo.svg b/assets/flags/mo.svg
new file mode 100644
index 0000000..f638b6c
--- /dev/null
+++ b/assets/flags/mo.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/mp.svg b/assets/flags/mp.svg
new file mode 100644
index 0000000..26bfa22
--- /dev/null
+++ b/assets/flags/mp.svg
@@ -0,0 +1,86 @@
+
diff --git a/assets/flags/mq.svg b/assets/flags/mq.svg
new file mode 100644
index 0000000..b221951
--- /dev/null
+++ b/assets/flags/mq.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/mr.svg b/assets/flags/mr.svg
new file mode 100644
index 0000000..d859972
--- /dev/null
+++ b/assets/flags/mr.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/ms.svg b/assets/flags/ms.svg
new file mode 100644
index 0000000..4367505
--- /dev/null
+++ b/assets/flags/ms.svg
@@ -0,0 +1,29 @@
+
diff --git a/assets/flags/mt.svg b/assets/flags/mt.svg
new file mode 100644
index 0000000..5d5d7c8
--- /dev/null
+++ b/assets/flags/mt.svg
@@ -0,0 +1,58 @@
+
diff --git a/assets/flags/mu.svg b/assets/flags/mu.svg
new file mode 100644
index 0000000..82d7a3b
--- /dev/null
+++ b/assets/flags/mu.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/mv.svg b/assets/flags/mv.svg
new file mode 100644
index 0000000..10450f9
--- /dev/null
+++ b/assets/flags/mv.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/mw.svg b/assets/flags/mw.svg
new file mode 100644
index 0000000..137ff87
--- /dev/null
+++ b/assets/flags/mw.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/flags/mx.svg b/assets/flags/mx.svg
new file mode 100644
index 0000000..e3ec2bc
--- /dev/null
+++ b/assets/flags/mx.svg
@@ -0,0 +1,382 @@
+
diff --git a/assets/flags/my.svg b/assets/flags/my.svg
new file mode 100644
index 0000000..115f864
--- /dev/null
+++ b/assets/flags/my.svg
@@ -0,0 +1,26 @@
+
diff --git a/assets/flags/mz.svg b/assets/flags/mz.svg
new file mode 100644
index 0000000..0f94c3a
--- /dev/null
+++ b/assets/flags/mz.svg
@@ -0,0 +1,21 @@
+
diff --git a/assets/flags/na.svg b/assets/flags/na.svg
new file mode 100644
index 0000000..35b9f78
--- /dev/null
+++ b/assets/flags/na.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/flags/nc.svg b/assets/flags/nc.svg
new file mode 100644
index 0000000..fa15551
--- /dev/null
+++ b/assets/flags/nc.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/ne.svg b/assets/flags/ne.svg
new file mode 100644
index 0000000..39a82b8
--- /dev/null
+++ b/assets/flags/ne.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/nf.svg b/assets/flags/nf.svg
new file mode 100644
index 0000000..fd61b25
--- /dev/null
+++ b/assets/flags/nf.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/ng.svg b/assets/flags/ng.svg
new file mode 100644
index 0000000..81eb35f
--- /dev/null
+++ b/assets/flags/ng.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/ni.svg b/assets/flags/ni.svg
new file mode 100644
index 0000000..e4861f5
--- /dev/null
+++ b/assets/flags/ni.svg
@@ -0,0 +1,129 @@
+
diff --git a/assets/flags/nl.svg b/assets/flags/nl.svg
new file mode 100644
index 0000000..e90f5b0
--- /dev/null
+++ b/assets/flags/nl.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/no.svg b/assets/flags/no.svg
new file mode 100644
index 0000000..a5f2a15
--- /dev/null
+++ b/assets/flags/no.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/np.svg b/assets/flags/np.svg
new file mode 100644
index 0000000..6242856
--- /dev/null
+++ b/assets/flags/np.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/nr.svg b/assets/flags/nr.svg
new file mode 100644
index 0000000..ff394c4
--- /dev/null
+++ b/assets/flags/nr.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/flags/nu.svg b/assets/flags/nu.svg
new file mode 100644
index 0000000..4067baf
--- /dev/null
+++ b/assets/flags/nu.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/flags/nz.svg b/assets/flags/nz.svg
new file mode 100644
index 0000000..935d8a7
--- /dev/null
+++ b/assets/flags/nz.svg
@@ -0,0 +1,36 @@
+
diff --git a/assets/flags/om.svg b/assets/flags/om.svg
new file mode 100644
index 0000000..4f1461a
--- /dev/null
+++ b/assets/flags/om.svg
@@ -0,0 +1,115 @@
+
diff --git a/assets/flags/pa.svg b/assets/flags/pa.svg
new file mode 100644
index 0000000..9ab733f
--- /dev/null
+++ b/assets/flags/pa.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/pc.svg b/assets/flags/pc.svg
new file mode 100644
index 0000000..5202d6d
--- /dev/null
+++ b/assets/flags/pc.svg
@@ -0,0 +1,33 @@
+
diff --git a/assets/flags/pe.svg b/assets/flags/pe.svg
new file mode 100644
index 0000000..33e6cfd
--- /dev/null
+++ b/assets/flags/pe.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/pf.svg b/assets/flags/pf.svg
new file mode 100644
index 0000000..bea0354
--- /dev/null
+++ b/assets/flags/pf.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/flags/pg.svg b/assets/flags/pg.svg
new file mode 100644
index 0000000..7b7e77a
--- /dev/null
+++ b/assets/flags/pg.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/ph.svg b/assets/flags/ph.svg
new file mode 100644
index 0000000..b910e24
--- /dev/null
+++ b/assets/flags/ph.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/pk.svg b/assets/flags/pk.svg
new file mode 100644
index 0000000..4ddc19f
--- /dev/null
+++ b/assets/flags/pk.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/pl.svg b/assets/flags/pl.svg
new file mode 100644
index 0000000..42d2b0c
--- /dev/null
+++ b/assets/flags/pl.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/pm.svg b/assets/flags/pm.svg
new file mode 100644
index 0000000..19a9330
--- /dev/null
+++ b/assets/flags/pm.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/pn.svg b/assets/flags/pn.svg
new file mode 100644
index 0000000..209ea71
--- /dev/null
+++ b/assets/flags/pn.svg
@@ -0,0 +1,53 @@
+
diff --git a/assets/flags/pr.svg b/assets/flags/pr.svg
new file mode 100644
index 0000000..ec51831
--- /dev/null
+++ b/assets/flags/pr.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/ps.svg b/assets/flags/ps.svg
new file mode 100644
index 0000000..362d435
--- /dev/null
+++ b/assets/flags/ps.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/pt.svg b/assets/flags/pt.svg
new file mode 100644
index 0000000..2767cd4
--- /dev/null
+++ b/assets/flags/pt.svg
@@ -0,0 +1,57 @@
+
diff --git a/assets/flags/pw.svg b/assets/flags/pw.svg
new file mode 100644
index 0000000..9f89c5f
--- /dev/null
+++ b/assets/flags/pw.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/flags/py.svg b/assets/flags/py.svg
new file mode 100644
index 0000000..abccd87
--- /dev/null
+++ b/assets/flags/py.svg
@@ -0,0 +1,157 @@
+
diff --git a/assets/flags/qa.svg b/assets/flags/qa.svg
new file mode 100644
index 0000000..901f3fa
--- /dev/null
+++ b/assets/flags/qa.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/re.svg b/assets/flags/re.svg
new file mode 100644
index 0000000..64e788e
--- /dev/null
+++ b/assets/flags/re.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/ro.svg b/assets/flags/ro.svg
new file mode 100644
index 0000000..fda0f7b
--- /dev/null
+++ b/assets/flags/ro.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/rs.svg b/assets/flags/rs.svg
new file mode 100644
index 0000000..6d4f74d
--- /dev/null
+++ b/assets/flags/rs.svg
@@ -0,0 +1,292 @@
+
diff --git a/assets/flags/ru.svg b/assets/flags/ru.svg
new file mode 100644
index 0000000..cf24301
--- /dev/null
+++ b/assets/flags/ru.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/rw.svg b/assets/flags/rw.svg
new file mode 100644
index 0000000..06e26ae
--- /dev/null
+++ b/assets/flags/rw.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/sa.svg b/assets/flags/sa.svg
new file mode 100644
index 0000000..596cf48
--- /dev/null
+++ b/assets/flags/sa.svg
@@ -0,0 +1,25 @@
+
diff --git a/assets/flags/sb.svg b/assets/flags/sb.svg
new file mode 100644
index 0000000..6066f94
--- /dev/null
+++ b/assets/flags/sb.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/sc.svg b/assets/flags/sc.svg
new file mode 100644
index 0000000..9a46b36
--- /dev/null
+++ b/assets/flags/sc.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/sd.svg b/assets/flags/sd.svg
new file mode 100644
index 0000000..12818b4
--- /dev/null
+++ b/assets/flags/sd.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/se.svg b/assets/flags/se.svg
new file mode 100644
index 0000000..8ba745a
--- /dev/null
+++ b/assets/flags/se.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/sg.svg b/assets/flags/sg.svg
new file mode 100644
index 0000000..c4dd4ac
--- /dev/null
+++ b/assets/flags/sg.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/sh-ac.svg b/assets/flags/sh-ac.svg
new file mode 100644
index 0000000..c43b301
--- /dev/null
+++ b/assets/flags/sh-ac.svg
@@ -0,0 +1,689 @@
+
diff --git a/assets/flags/sh-hl.svg b/assets/flags/sh-hl.svg
new file mode 100644
index 0000000..2150bf6
--- /dev/null
+++ b/assets/flags/sh-hl.svg
@@ -0,0 +1,164 @@
+
diff --git a/assets/flags/sh-ta.svg b/assets/flags/sh-ta.svg
new file mode 100644
index 0000000..ba39063
--- /dev/null
+++ b/assets/flags/sh-ta.svg
@@ -0,0 +1,76 @@
+
diff --git a/assets/flags/sh.svg b/assets/flags/sh.svg
new file mode 100644
index 0000000..7aba0ae
--- /dev/null
+++ b/assets/flags/sh.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/si.svg b/assets/flags/si.svg
new file mode 100644
index 0000000..1bbdd94
--- /dev/null
+++ b/assets/flags/si.svg
@@ -0,0 +1,18 @@
+
diff --git a/assets/flags/sj.svg b/assets/flags/sj.svg
new file mode 100644
index 0000000..bb2799c
--- /dev/null
+++ b/assets/flags/sj.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/sk.svg b/assets/flags/sk.svg
new file mode 100644
index 0000000..676018e
--- /dev/null
+++ b/assets/flags/sk.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/sl.svg b/assets/flags/sl.svg
new file mode 100644
index 0000000..a07baf7
--- /dev/null
+++ b/assets/flags/sl.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/sm.svg b/assets/flags/sm.svg
new file mode 100644
index 0000000..e41d2f7
--- /dev/null
+++ b/assets/flags/sm.svg
@@ -0,0 +1,75 @@
+
diff --git a/assets/flags/sn.svg b/assets/flags/sn.svg
new file mode 100644
index 0000000..7c0673d
--- /dev/null
+++ b/assets/flags/sn.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/so.svg b/assets/flags/so.svg
new file mode 100644
index 0000000..a581ac6
--- /dev/null
+++ b/assets/flags/so.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/flags/sr.svg b/assets/flags/sr.svg
new file mode 100644
index 0000000..5e71c40
--- /dev/null
+++ b/assets/flags/sr.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/ss.svg b/assets/flags/ss.svg
new file mode 100644
index 0000000..b257aa0
--- /dev/null
+++ b/assets/flags/ss.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/st.svg b/assets/flags/st.svg
new file mode 100644
index 0000000..1294bcb
--- /dev/null
+++ b/assets/flags/st.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/flags/sv.svg b/assets/flags/sv.svg
new file mode 100644
index 0000000..cbc674a
--- /dev/null
+++ b/assets/flags/sv.svg
@@ -0,0 +1,593 @@
+
diff --git a/assets/flags/sx.svg b/assets/flags/sx.svg
new file mode 100644
index 0000000..ac78561
--- /dev/null
+++ b/assets/flags/sx.svg
@@ -0,0 +1,56 @@
+
diff --git a/assets/flags/sy.svg b/assets/flags/sy.svg
new file mode 100644
index 0000000..97c05cf
--- /dev/null
+++ b/assets/flags/sy.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/sz.svg b/assets/flags/sz.svg
new file mode 100644
index 0000000..eb538e4
--- /dev/null
+++ b/assets/flags/sz.svg
@@ -0,0 +1,34 @@
+
diff --git a/assets/flags/tc.svg b/assets/flags/tc.svg
new file mode 100644
index 0000000..1258971
--- /dev/null
+++ b/assets/flags/tc.svg
@@ -0,0 +1,50 @@
+
diff --git a/assets/flags/td.svg b/assets/flags/td.svg
new file mode 100644
index 0000000..fa3bd92
--- /dev/null
+++ b/assets/flags/td.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/tf.svg b/assets/flags/tf.svg
new file mode 100644
index 0000000..fba2335
--- /dev/null
+++ b/assets/flags/tf.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/flags/tg.svg b/assets/flags/tg.svg
new file mode 100644
index 0000000..9d6ea6c
--- /dev/null
+++ b/assets/flags/tg.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/flags/th.svg b/assets/flags/th.svg
new file mode 100644
index 0000000..1e93a61
--- /dev/null
+++ b/assets/flags/th.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/tj.svg b/assets/flags/tj.svg
new file mode 100644
index 0000000..f8c9a03
--- /dev/null
+++ b/assets/flags/tj.svg
@@ -0,0 +1,22 @@
+
diff --git a/assets/flags/tk.svg b/assets/flags/tk.svg
new file mode 100644
index 0000000..05d3e86
--- /dev/null
+++ b/assets/flags/tk.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/tl.svg b/assets/flags/tl.svg
new file mode 100644
index 0000000..3d0701a
--- /dev/null
+++ b/assets/flags/tl.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/tm.svg b/assets/flags/tm.svg
new file mode 100644
index 0000000..4154ed7
--- /dev/null
+++ b/assets/flags/tm.svg
@@ -0,0 +1,204 @@
+
diff --git a/assets/flags/tn.svg b/assets/flags/tn.svg
new file mode 100644
index 0000000..5735c19
--- /dev/null
+++ b/assets/flags/tn.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/to.svg b/assets/flags/to.svg
new file mode 100644
index 0000000..d072337
--- /dev/null
+++ b/assets/flags/to.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/flags/tr.svg b/assets/flags/tr.svg
new file mode 100644
index 0000000..b96da21
--- /dev/null
+++ b/assets/flags/tr.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/tt.svg b/assets/flags/tt.svg
new file mode 100644
index 0000000..bc24938
--- /dev/null
+++ b/assets/flags/tt.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/tv.svg b/assets/flags/tv.svg
new file mode 100644
index 0000000..675210e
--- /dev/null
+++ b/assets/flags/tv.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/tw.svg b/assets/flags/tw.svg
new file mode 100644
index 0000000..57fd98b
--- /dev/null
+++ b/assets/flags/tw.svg
@@ -0,0 +1,34 @@
+
diff --git a/assets/flags/tz.svg b/assets/flags/tz.svg
new file mode 100644
index 0000000..a2cfbca
--- /dev/null
+++ b/assets/flags/tz.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/flags/ua.svg b/assets/flags/ua.svg
new file mode 100644
index 0000000..03daa19
--- /dev/null
+++ b/assets/flags/ua.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/flags/ug.svg b/assets/flags/ug.svg
new file mode 100644
index 0000000..520eee5
--- /dev/null
+++ b/assets/flags/ug.svg
@@ -0,0 +1,30 @@
+
diff --git a/assets/flags/um.svg b/assets/flags/um.svg
new file mode 100644
index 0000000..9e9edda
--- /dev/null
+++ b/assets/flags/um.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/un.svg b/assets/flags/un.svg
new file mode 100644
index 0000000..632bbb4
--- /dev/null
+++ b/assets/flags/un.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/flags/us.svg b/assets/flags/us.svg
new file mode 100644
index 0000000..9cfd0c9
--- /dev/null
+++ b/assets/flags/us.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/flags/uy.svg b/assets/flags/uy.svg
new file mode 100644
index 0000000..62c36f8
--- /dev/null
+++ b/assets/flags/uy.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/flags/uz.svg b/assets/flags/uz.svg
new file mode 100644
index 0000000..0ccca1b
--- /dev/null
+++ b/assets/flags/uz.svg
@@ -0,0 +1,30 @@
+
diff --git a/assets/flags/va.svg b/assets/flags/va.svg
new file mode 100644
index 0000000..3e297d6
--- /dev/null
+++ b/assets/flags/va.svg
@@ -0,0 +1,190 @@
+
diff --git a/assets/flags/vc.svg b/assets/flags/vc.svg
new file mode 100644
index 0000000..f26c2d8
--- /dev/null
+++ b/assets/flags/vc.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/flags/ve.svg b/assets/flags/ve.svg
new file mode 100644
index 0000000..314e7f5
--- /dev/null
+++ b/assets/flags/ve.svg
@@ -0,0 +1,26 @@
+
diff --git a/assets/flags/vg.svg b/assets/flags/vg.svg
new file mode 100644
index 0000000..ac90088
--- /dev/null
+++ b/assets/flags/vg.svg
@@ -0,0 +1,59 @@
+
diff --git a/assets/flags/vi.svg b/assets/flags/vi.svg
new file mode 100644
index 0000000..d88d68f
--- /dev/null
+++ b/assets/flags/vi.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/flags/vn.svg b/assets/flags/vn.svg
new file mode 100644
index 0000000..7e4bac8
--- /dev/null
+++ b/assets/flags/vn.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/flags/vu.svg b/assets/flags/vu.svg
new file mode 100644
index 0000000..326d29e
--- /dev/null
+++ b/assets/flags/vu.svg
@@ -0,0 +1,21 @@
+
diff --git a/assets/flags/wf.svg b/assets/flags/wf.svg
new file mode 100644
index 0000000..054c57d
--- /dev/null
+++ b/assets/flags/wf.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/ws.svg b/assets/flags/ws.svg
new file mode 100644
index 0000000..0e758a7
--- /dev/null
+++ b/assets/flags/ws.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/xk.svg b/assets/flags/xk.svg
new file mode 100644
index 0000000..0e8958d
--- /dev/null
+++ b/assets/flags/xk.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/xx.svg b/assets/flags/xx.svg
new file mode 100644
index 0000000..9333be3
--- /dev/null
+++ b/assets/flags/xx.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/flags/ye.svg b/assets/flags/ye.svg
new file mode 100644
index 0000000..1c9e6d6
--- /dev/null
+++ b/assets/flags/ye.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/flags/yt.svg b/assets/flags/yt.svg
new file mode 100644
index 0000000..e7776b3
--- /dev/null
+++ b/assets/flags/yt.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/flags/za.svg b/assets/flags/za.svg
new file mode 100644
index 0000000..d563adb
--- /dev/null
+++ b/assets/flags/za.svg
@@ -0,0 +1,17 @@
+
diff --git a/assets/flags/zm.svg b/assets/flags/zm.svg
new file mode 100644
index 0000000..360f37a
--- /dev/null
+++ b/assets/flags/zm.svg
@@ -0,0 +1,27 @@
+
diff --git a/assets/flags/zw.svg b/assets/flags/zw.svg
new file mode 100644
index 0000000..93aac4f
--- /dev/null
+++ b/assets/flags/zw.svg
@@ -0,0 +1,21 @@
+
diff --git a/assets/icons/YALI_icon_LIGHT.svg b/assets/icons/YALI_icon_LIGHT.svg
new file mode 100644
index 0000000..dd35f53
--- /dev/null
+++ b/assets/icons/YALI_icon_LIGHT.svg
@@ -0,0 +1,265 @@
+
+
+
+
diff --git a/assets/icons/check.png b/assets/icons/check.png
new file mode 100644
index 0000000..0ad0409
Binary files /dev/null and b/assets/icons/check.png differ
diff --git a/assets/icons/check.svg b/assets/icons/check.svg
new file mode 100644
index 0000000..6d795f3
--- /dev/null
+++ b/assets/icons/check.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/assets/icons/eye-hidden.png b/assets/icons/eye-hidden.png
new file mode 100644
index 0000000..cc35425
Binary files /dev/null and b/assets/icons/eye-hidden.png differ
diff --git a/assets/icons/eye.png b/assets/icons/eye.png
new file mode 100644
index 0000000..0109806
Binary files /dev/null and b/assets/icons/eye.png differ
diff --git a/assets/icons/language-icon.svg b/assets/icons/language-icon.svg
new file mode 100644
index 0000000..2fae488
--- /dev/null
+++ b/assets/icons/language-icon.svg
@@ -0,0 +1,62 @@
+
+
+
diff --git a/assets/icons/language-icon.zip b/assets/icons/language-icon.zip
new file mode 100644
index 0000000..011ebcd
Binary files /dev/null and b/assets/icons/language-icon.zip differ
diff --git a/assets/icons/pngwing.com.png b/assets/icons/pngwing.com.png
new file mode 100644
index 0000000..ffdcbc8
Binary files /dev/null and b/assets/icons/pngwing.com.png differ
diff --git a/assets/icons/simit.png b/assets/icons/simit.png
new file mode 100644
index 0000000..5793ae7
Binary files /dev/null and b/assets/icons/simit.png differ
diff --git a/assets/icons/x.png b/assets/icons/x.png
new file mode 100644
index 0000000..4e5da0f
Binary files /dev/null and b/assets/icons/x.png differ
diff --git a/branding.toml b/branding.toml
index 76e4905..8181834 100644
--- a/branding.toml
+++ b/branding.toml
@@ -13,7 +13,7 @@
# ──────────────────────────────────────────────────────────────────
[general]
# Sol kenar çubuğu için Yali logosu
-yali_logo = "assets/yali.png"
+yali_logo = "assets/icons/YALI_icon_LIGHT.svg"
# Kurulum ana sayfası için PisiLinux dağıtım logosu
pisi_logo_dark = "assets/pisi-logo-dark.png"
diff --git a/branding_en.toml b/branding_en.toml
index 063e8b5..8e3be1b 100644
--- a/branding_en.toml
+++ b/branding_en.toml
@@ -8,7 +8,7 @@
# ──────────────────────────────────────────────────────────────────
[general]
# Sidebar logo (Yali)
-yali_logo = "assets/yali.png"
+yali_logo = "assets/icons/YALI_icon_LIGHT.svg"
# Main page logo (PisiLinux distribution)
pisi_logo_dark = "assets/pisi-logo-dark.png"
diff --git a/branding_tr.toml b/branding_tr.toml
index 80ddfd0..0e2478e 100644
--- a/branding_tr.toml
+++ b/branding_tr.toml
@@ -13,7 +13,7 @@
# ──────────────────────────────────────────────────────────────────
[general]
# Sol kenar çubuğu için Yali logosu
-yali_logo = "assets/yali.png"
+yali_logo = "assets/icons/YALI_icon_LIGHT.svg"
# Kurulum ana sayfası için PisiLinux dağıtım logosu
pisi_logo_dark = "assets/pisi-logo-dark.png"
diff --git a/locales/en.toml b/locales/en.toml
index cc25c68..41797d6 100644
--- a/locales/en.toml
+++ b/locales/en.toml
@@ -4,6 +4,10 @@ back = "Back"
next = "Next"
cancel = "Cancel"
confirm = "Confirm"
+cancel_confirm_title = "Cancel Installation"
+cancel_confirm_msg = "The installation will be cancelled. Are you sure?"
+cancel_confirm_yes = "Yes, Cancel"
+cancel_confirm_no = "No, Continue"
# ── Welcome ───────────────────────────────────────────────
welcome = "Welcome"
@@ -53,7 +57,7 @@ users_title = "User Account"
users_description = "Create a user account for your system."
real_name_label = "Full Name"
username_label = "Username"
-password_label = "Password"
+password_label = "Password (at least 8 characters...)"
password_confirm_label = "Confirm password"
hostname_label = "Computer name"
username_invalid = "Invalid username. Must start with a lowercase letter or underscore, max 32 characters."
diff --git a/locales/tr.toml b/locales/tr.toml
index d685ea7..acb3711 100644
--- a/locales/tr.toml
+++ b/locales/tr.toml
@@ -4,6 +4,10 @@ back = "Geri"
next = "İleri"
cancel = "İptal"
confirm = "Onayla"
+cancel_confirm_title = "Kurulumu İptal Et"
+cancel_confirm_msg = "Kurulum iptal edilecek. Emin misiniz?"
+cancel_confirm_yes = "Evet, İptal Et"
+cancel_confirm_no = "Hayır, Devam Et"
# ── Welcome ───────────────────────────────────────────────
welcome = "Hoş Geldiniz"
@@ -51,14 +55,14 @@ erase_warning = "UYARI: Seçilen diskteki tüm veriler silinecektir"
users = "Kullanıcı"
users_title = "Kullanıcı Bilgileri"
users_description = "Sisteminiz için bir kullanıcı hesabı oluşturun."
-real_name_label = "Ad Soyad"
+real_name_label = "Gerçek Adınız."
username_label = "Kullanıcı adı"
-password_label = "Şifre"
-password_confirm_label = "Şifre (tekrar)"
+password_label = "Parola (en az 8 karakter olmalıdır...)"
+password_confirm_label = "Parola (tekrar)"
hostname_label = "Bilgisayar adı"
username_invalid = "Geçersiz kullanıcı adı. Küçük harf veya alt çizgi ile başlamalı, en fazla 32 karakter."
hostname_invalid = "Geçersiz bilgisayar adı. Yalnızca harf, rakam ve tire içerebilir."
-passwords_no_match = "Şifreler eşleşmiyor"
+passwords_no_match = "Parolalar eşleşmiyor"
# ── Summary ───────────────────────────────────────────────
summary = "Özet"
@@ -111,7 +115,7 @@ summary_custom_partitions = "Manuel Bölümler"
mp_size_remaining = "Kalan Alan"
# ── UI / Genel ────────────────────────────────────────────
-installer = "YALI Kurulum Aracı"
+installer = "PisiLinux Kurulum Aracı"
app_name = "YALI"
# ── Hata ekranı ───────────────────────────────────────────
diff --git a/src/autoinstall/mod.rs b/src/autoinstall/mod.rs
index 36183c2..6378ebe 100644
--- a/src/autoinstall/mod.rs
+++ b/src/autoinstall/mod.rs
@@ -125,7 +125,9 @@ pub fn apply_to_state(af: &AnswerFile, state: &mut crate::installer::GlobalState
let model = parts.collect::>().join(" ");
Some(DiskInfo {
name: format!("/dev/{}", name),
+ vendor: String::new(),
model: if model.is_empty() { "Unknown".to_string() } else { model },
+ drive_type: String::new(),
size_gb: bytes / 1_073_741_824,
size_bytes: bytes,
})
diff --git a/src/branding.rs b/src/branding.rs
index d8beb3f..98c9be3 100644
--- a/src/branding.rs
+++ b/src/branding.rs
@@ -136,7 +136,7 @@ pub struct OemConfig {
fn default_title() -> String { "YALI Installation Tool".to_string() }
fn default_subtitle() -> String { "PiSi GNU/LINUX".to_string() }
-fn default_yali_logo() -> String { "assets/yali.png".to_string() }
+fn default_yali_logo() -> String { "assets/icons/YALI_icon_LIGHT.svg".to_string() }
fn default_pisi_logo_dark() -> String { "assets/pisi-logo-dark.png".to_string() }
fn default_pisi_logo_light() -> String { "assets/pisi-logo-light.png".to_string() }
fn default_interval() -> u64 { 6 }
diff --git a/src/funct.rs b/src/funct.rs
new file mode 100644
index 0000000..459500b
--- /dev/null
+++ b/src/funct.rs
@@ -0,0 +1,135 @@
+use eframe::egui;
+
+#[macro_export]
+macro_rules! draw_icon {
+ ($ui:expr, $path:literal, $size:expr, $color:expr) => {
+ $ui.add(
+ eframe::egui::Image::new(eframe::egui::include_image!($path))
+ .max_width($size)
+ .max_height($size)
+ .tint($color),
+ )
+ };
+}
+
+pub fn form_input_text(
+ ui: &mut eframe::egui::Ui,
+ text: &mut String,
+)-> eframe::egui::Response {
+
+ let width_percent = 0.90; // Mevcut genişliğin %90'ı
+ let height = 32.0; // Standart yükseklik
+ let hesaplanan_genislik = ui.available_width() * width_percent;
+ let boyut = eframe::egui::vec2(hesaplanan_genislik, height);
+
+ ui.spacing_mut().button_padding = eframe::egui::vec2(10.0, 10.0);
+ ui.add_sized(
+ boyut,
+ eframe::egui::TextEdit::singleline(text)
+ .vertical_align(eframe::egui::Align::Center)
+ )
+}
+
+pub fn form_input_password(
+ ui: &mut eframe::egui::Ui,
+ text: &mut String,
+ show_password: &mut bool,
+) -> eframe::egui::Response {
+ let width_percent = 0.90;
+ let height = 32.0;
+ let toplam_genislik = ui.available_width() * width_percent;
+ let dugme_genislik = 40.0;
+ let alan_genislik = toplam_genislik - dugme_genislik - 4.0;
+ let boyut = eframe::egui::vec2(alan_genislik, height);
+
+ ui.spacing_mut().button_padding = eframe::egui::vec2(10.0, 10.0);
+
+ ui.horizontal(|ui| {
+ let r = ui.add_sized(
+ boyut,
+ eframe::egui::TextEdit::singleline(text)
+ .password(!*show_password)
+ .vertical_align(eframe::egui::Align::Center),
+ );
+ let göz = if *show_password { "🙈" } else { "👁" };
+ if ui.add(
+ eframe::egui::Button::new(göz)
+ .min_size(eframe::egui::vec2(dugme_genislik, height))
+ ).clicked() {
+ *show_password = !*show_password;
+ }
+ r
+ }).inner
+}
+
+pub fn form_label(ui: &mut eframe::egui::Ui, text: &str) {
+ ui.label(
+ eframe::egui::RichText::new(text)
+ .strong()
+ .color(crate::ui::theme::c_text()) // Atomic temandan rengi çekiyor
+ );
+}
+
+pub fn form_checkbox(ui: &mut eframe::egui::Ui, checked: &mut bool, text: &str) {
+ ui.checkbox(checked, eframe::egui::RichText::new(text).strong().color(crate::ui::theme::c_text()));
+}
+
+
+
+pub fn language_selector_ui(ui: &mut eframe::egui::Ui, state: &mut crate::installer::GlobalState) {
+ ui.horizontal(|ui| {
+ // Satır yüksekliğini tam olarak 32px'e eşitliyoruz
+ ui.set_height(32.0);
+
+ // 1. Sol taraftaki ikon alanı
+ ui.vertical(|ui| {
+ ui.add_space(4.0);
+ ui.add(
+ eframe::egui::Image::new(eframe::egui::include_image!("../assets/icons/language-icon.svg"))
+ .max_width(40.0)
+ );
+ });
+
+ ui.add_space(6.0);
+
+ // 2. ComboBox alanı (%90 genişlik payı)
+ let available_width = ui.available_width() * 0.90;
+ let current_lang_label = if state.language == "tr" { "Türkçe" } else { "English" };
+
+ let languages = [
+ ("tr", "Türkçe", eframe::egui::include_image!("../assets/flags/tr.svg")),
+ ("en", "English", eframe::egui::include_image!("../assets/flags/us.svg")),
+ ];
+
+ // Standart egui makrosu - Tema motoru sayesinde otomatik olarak oval ve renk geçişli hissi verir
+ eframe::egui::ComboBox::from_id_source("language_select_combo")
+ .selected_text(current_lang_label)
+ .width(available_width) // Seçim kutusunu yatayda genişletir
+ .show_ui(ui, |ui| {
+ // Açılan alt listenin genişliğini de üst butonla eşitliyoruz (HTML SelectBox Mantığı)
+ ui.set_min_width(available_width);
+ ui.set_max_width(available_width);
+
+ for (code, label, image_source) in languages.iter() {
+ let item_height = 28.0;
+
+ // Eleman kutularını sarmalayarak tam genişlikte tıklanabilir yapıyoruz
+ ui.add_sized([available_width, item_height], |ui: &mut egui::Ui| {
+ ui.horizontal(|ui| {
+ ui.add_space(6.0); // İç sol boşluk
+ ui.add(eframe::egui::Image::new(image_source.clone()).max_width(18.0));
+ ui.add_space(4.0);
+
+ let mut current_lang = state.language.clone();
+ let resp = ui.selectable_value(&mut current_lang, code.to_string(), *label);
+
+ if resp.clicked() {
+ state.language = code.to_string();
+ }
+ resp
+ }).response
+ });
+ }
+ });
+ });
+}
\ No newline at end of file
diff --git a/src/installer.rs b/src/installer.rs
index 96dad24..d8d855b 100644
--- a/src/installer.rs
+++ b/src/installer.rs
@@ -74,7 +74,10 @@ pub trait InstallerStep {
#[derive(Clone, Debug)]
pub struct DiskInfo {
pub name: String, // ör. "/dev/sda"
+ pub vendor: String, // "ATA", "INTEL", vb.
pub model: String,
+ #[allow(dead_code)]
+ pub drive_type: String, // "NVMe SSD", "SSD", "HDD", "USB", "MMC/SD", vb.
pub size_gb: u64,
pub size_bytes: u64,
}
@@ -274,7 +277,7 @@ impl Default for GlobalState {
install_log: Vec::new(),
install_current_file: None,
demo_mode: false,
- is_dark: true,
+ is_dark: false,
rescue_mode: false,
bootloader_device: String::new(),
bootloader_timeout: 5,
@@ -313,6 +316,7 @@ impl Default for GlobalState {
// WELCOME STEP (sistem gereksinimleri + dil seçimi)
// ─────────────────────────────────────────────
+use crate::funct::language_selector_ui;
use crate::autoinstall::checker::{CheckResult, CheckStatus, run_all, all_passed};
pub struct WelcomeStep {
@@ -404,16 +408,17 @@ impl InstallerStep for WelcomeStep {
ui.add_space(12.0);
// Dil seçimi (Açılır Liste / ComboBox)
- ui.horizontal(|ui| {
- ui.label(t!("select_language"));
- let current_lang_label = if state.language == "tr" { "🇹🇷 Türkçe" } else { "🇺🇸 English" };
- egui::ComboBox::from_id_source("language_select")
- .selected_text(current_lang_label)
- .show_ui(ui, |ui| {
- ui.selectable_value(&mut state.language, "tr".to_string(), "🇹🇷 Türkçe");
- ui.selectable_value(&mut state.language, "en".to_string(), "🇺🇸 English");
- });
- });
+ // ui.horizontal(|ui| {
+ // ui.label(t!("select_language"));
+ // let current_lang_label = if state.language == "tr" { "🇹🇷 Türkçe" } else { "🇺🇸 English" };
+ // egui::ComboBox::from_id_source("language_select")
+ // .selected_text(current_lang_label)
+ // .show_ui(ui, |ui| {
+ // ui.selectable_value(&mut state.language, "tr".to_string(), "🇹🇷 Türkçe");
+ // ui.selectable_value(&mut state.language, "en".to_string(), "🇺🇸 English");
+ // });
+ // });
+ language_selector_ui(ui, state);
ui.add_space(14.0);
ui.separator();
@@ -425,7 +430,20 @@ impl InstallerStep for WelcomeStep {
.strong()
.color(theme::c_text()),
);
- ui.add_space(6.0);
+ ui.add_space(10.0);
+
+ // Hata varsa uyarı
+ ui.add_space(10.0);
+ let has_fail = self.checks.iter().any(|c| c.status == CheckStatus::Fail);
+ if has_fail {
+ theme::error_box(ui, &t!("check_fail_warning"));
+ } else if self.checks.iter().any(|c| c.status == CheckStatus::Warn) {
+ theme::warning_box(ui, &t!("check_warn_notice"));
+ } else if !self.checks.is_empty() {
+ theme::success_box(ui, &t!("check_all_pass"));
+ }
+
+ ui.add_space(10.0);
// Kontrol tablosu
egui::Grid::new("checks_grid")
@@ -452,42 +470,37 @@ impl InstallerStep for WelcomeStep {
// Rescue mode butonu
ui.add_space(10.0);
- ui.horizontal(|ui| {
- let rescue_available = detect_existing_linux();
- if rescue_available {
- ui.colored_label(
- egui::Color32::from_rgb(80, 170, 80),
- "🛟",
- );
- if ui.add(theme::secondary_button(&t!("rescue_button"))).clicked() {
- state.rescue_mode = true;
- }
- } else {
- ui.label(
- egui::RichText::new(t!("rescue_not_available"))
- .size(12.0)
- .color(egui::Color32::from_rgb(120, 120, 140)),
- );
+
+ ui.allocate_ui(
+ egui::vec2(ui.available_width(), 30.0), // Genişlik tam, Yükseklik sadece 24px
+ |ui| {
+ // Şimdi dikeyde ortalayarak soldan sağa diziyoruz
+ ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| {
+ let rescue_available = detect_existing_linux();
+ if rescue_available {
+ if theme::secondary_button(ui, &t!("rescue_button")).clicked() {
+ state.rescue_mode = true;
+ }
+
+ if theme::secondary_button(ui, &t!("recheck")).clicked() {
+ self.checked = false;
+ self.on_enter(state);
+ }
+ } else {
+ ui.label(
+ egui::RichText::new(t!("rescue_not_available"))
+ .size(12.0)
+ .color(egui::Color32::from_rgb(120, 120, 140)),
+ );
+ }
+ });
}
- });
+ );
- // Hata varsa uyarı
- ui.add_space(10.0);
- let has_fail = self.checks.iter().any(|c| c.status == CheckStatus::Fail);
- if has_fail {
- theme::error_box(ui, &t!("check_fail_warning"));
- } else if self.checks.iter().any(|c| c.status == CheckStatus::Warn) {
- theme::warning_box(ui, &t!("check_warn_notice"));
- } else if !self.checks.is_empty() {
- theme::success_box(ui, &t!("check_all_pass"));
- }
- // Yeniden tara butonu
- ui.add_space(8.0);
- if ui.add(theme::secondary_button(&t!("recheck"))).clicked() {
- self.checked = false;
- self.on_enter(state);
- }
+
+
+
}
fn is_complete(&self, state: &GlobalState) -> bool {
diff --git a/src/jobs/mod.rs b/src/jobs/mod.rs
index dc153c8..a50deb3 100644
--- a/src/jobs/mod.rs
+++ b/src/jobs/mod.rs
@@ -922,7 +922,7 @@ impl Job for PartitionJob {
let end_mb = next_mb + self.plan.efi_mb;
ui.log(format!("EFI bölümü oluşturuluyor: {}–{} MB", next_mb, end_mb));
run_parted(&[
- "-s", disk, "mkpart", "primary", "fat32",
+ "-s", disk, "mkpart", "fat32",
&format!("{}MB", next_mb), &format!("{}MB", end_mb),
]).await?;
run_parted(&["-s", disk, "set", "1", "esp", "on"]).await?;
@@ -934,7 +934,7 @@ impl Job for PartitionJob {
let swap_num: u32 = if self.plan.efi_mb > 0 { 2 } else { 1 };
ui.log(format!("Swap bölümü oluşturuluyor: {}–{} MB", next_mb, swap_end));
run_parted(&[
- "-s", disk, "mkpart", "primary", "linux-swap",
+ "-s", disk, "mkpart", "linux-swap",
&format!("{}MB", next_mb), &format!("{}MB", swap_end),
]).await?;
next_mb = swap_end;
@@ -943,7 +943,7 @@ impl Job for PartitionJob {
let root_num: u32 = if self.plan.efi_mb > 0 { 3 } else { 2 };
ui.log(format!("Kök bölümü oluşturuluyor: {}MB – disk sonu", next_mb));
run_parted(&[
- "-s", disk, "mkpart", "primary", "ext4",
+ "-s", disk, "mkpart", "ext4",
&format!("{}MB", next_mb), "100%",
]).await?;
@@ -1945,6 +1945,10 @@ impl Job for CustomPartitionJob {
// 0. Diski hazırla: bağlamaları ayır, kernel tablosunu temizle
prepare_disk(&self.disk, ui).await;
+ let is_gpt = is_uefi; // Genellikle UEFI ise GPT kullanılır
+ // MBR'de "primary" zorunludur, GPT'de ise bu alan isim (label) alanıdır.
+ let part_type_or_name = if is_gpt { "" } else { "primary" };
+
// 1. Bölüm tablosu oluştur
let table_label = if is_uefi { "gpt" } else { "msdos" };
ui.log(format!("parted {} mktable {}", self.disk, table_label));
@@ -1981,7 +1985,7 @@ impl Job for CustomPartitionJob {
part_num, start_str, end_str, fs_label
));
run_parted(&[
- "-s", &self.disk, "mkpart", "primary", fs_label,
+ "-s", &self.disk, "mkpart", part_type_or_name, fs_label,
&start_str, &end_str
]).await?;
@@ -2389,4 +2393,3 @@ pub fn build_custom_job_queue(
JobQueue::new(jobs)
}
-
diff --git a/src/main.rs b/src/main.rs
index 84ad9d1..e592c60 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,7 @@ mod jobs;
mod ui;
mod autoinstall;
mod branding;
+mod funct;
use installer::{GlobalState, InstallerStep, WelcomeStep, LocationStep};
use steps::{KeyboardStep, UsersStep, SummaryStep, ExecutionStep, FinishStep, PartitionStep, BootloaderStep, NetworkStep, DisplayManagerStep};
@@ -16,6 +17,7 @@ fn main() -> eframe::Result<()> {
// ── CLI: otomatik kurulum modu ───────────────────────
let args: Vec = std::env::args().collect();
let demo_mode = args.contains(&"--demo".to_string());
+
if let Some(pos) = args.iter().position(|a| a == "--auto-install") {
if let Some(path) = args.get(pos + 1) {
@@ -31,6 +33,7 @@ fn main() -> eframe::Result<()> {
/// Grafik arayüzü başlatır (normal mod).
fn run_gui(demo_mode: bool) -> eframe::Result<()> {
+
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_inner_size([1200.0, 900.0])
@@ -45,8 +48,8 @@ fn run_gui(demo_mode: bool) -> eframe::Result<()> {
Box::new(move |cc| {
// Görsel yükleyicileri etkinleştir (PNG desteği)
egui_extras::install_image_loaders(&cc.egui_ctx);
-
- ui::theme::apply(&cc.egui_ctx, true);
+ ui::theme::set_theme_mode(false);
+ ui::theme::apply(&cc.egui_ctx, false);
let mut app = YaliApp::default();
app.state.demo_mode = demo_mode;
Box::new(app)
@@ -202,12 +205,13 @@ fn run_auto_install(path: &str, demo_mode: bool) -> eframe::Result<()> {
}
struct YaliApp {
- state: GlobalState,
- steps: Vec>,
- rescue_step: Option>,
- last_step: usize,
- branding: branding::BrandingConfig,
- loaded_language: String,
+ state: GlobalState,
+ steps: Vec>,
+ rescue_step: Option>,
+ last_step: usize,
+ branding: branding::BrandingConfig,
+ loaded_language: String,
+ show_cancel_dialog: bool,
}
impl Default for YaliApp {
@@ -233,6 +237,7 @@ impl Default for YaliApp {
last_step: usize::MAX,
branding: branding.clone(),
loaded_language: String::new(),
+ show_cancel_dialog: false,
};
// OEM modu: varsayılan değerleri ata ve step engelleme
@@ -347,17 +352,17 @@ impl eframe::App for YaliApp {
);
}
ui.add_space(8.0);
- ui.label(
- egui::RichText::new(t!("app_name"))
- .strong()
- .size(16.0)
- .color(ui::theme::c_text_dim()),
- );
+ // ui.label(
+ // egui::RichText::new(t!("app_name"))
+ // .strong()
+ // .size(16.0)
+ // .color(ui::theme::c_text_dim()),
+ // );
- ui.colored_label(
- egui::Color32::from_rgb(60, 60, 90),
- format!("{}: {}", t!("version"), env!("CARGO_PKG_VERSION")),
- );
+ // ui.colored_label(
+ // egui::Color32::from_rgb(60, 60, 90),
+ // format!("{}: {}", t!("version"), env!("CARGO_PKG_VERSION")),
+ // );
});
ui.add_space(16.0);
@@ -366,7 +371,8 @@ impl eframe::App for YaliApp {
// Adım listesi
for (i, step) in self.steps.iter().enumerate() {
- let label = format!("{}. {}", i + 1, step.name());
+ //let label = format!("{}. {}", i + 1, step.name());
+ let label = step.name();
egui::Frame::none()
.fill(if i == cur {
@@ -374,23 +380,23 @@ impl eframe::App for YaliApp {
} else {
egui::Color32::TRANSPARENT
})
- .rounding(egui::Rounding::same(6.0))
+ //.rounding(egui::Rounding::same(6.0))
.inner_margin(egui::Margin::symmetric(10.0, 5.0))
.show(ui, |ui| {
ui.set_width(175.0);
if i == cur {
ui.horizontal(|ui| {
ui.colored_label(ui::theme::c_accent(), "▶");
- ui.colored_label(ui::theme::c_text(), label);
+ ui.colored_label(ui::theme::c_sidebar_text(), label);
});
} else if i < cur {
ui.horizontal(|ui| {
ui.colored_label(ui::theme::c_success(), "✅");
- ui.colored_label(ui::theme::c_text_dim(), label);
+ ui.colored_label(ui::theme::c_sidebar_text(), label);
});
} else {
ui.colored_label(
- egui::Color32::from_rgb(80, 80, 100),
+ egui::Color32::from_rgb(255, 255, 255),
format!(" {}", label),
);
}
@@ -400,39 +406,35 @@ impl eframe::App for YaliApp {
}
// Alt kısım: tema değiştirme
- ui.with_layout(egui::Layout::bottom_up(egui::Align::Center), |ui| {
- ui.add_space(6.0);
+ // ui.with_layout(egui::Layout::bottom_up(egui::Align::Center), |ui| {
+ // ui.add_space(6.0);
- let theme_icon = if self.state.is_dark { "☀" } else { "🌙" };
- let theme_label = if self.state.is_dark { "Light" } else { "Dark" };
- if ui.add(
- egui::Button::new(
- egui::RichText::new(format!("{} {}", theme_icon, theme_label))
- .size(12.0)
- )
- .rounding(egui::Rounding::same(6.0))
- .min_size(egui::Vec2::new(100.0, 28.0))
- ).clicked() {
- self.state.is_dark = !self.state.is_dark;
- ui::theme::set_theme_mode(self.state.is_dark);
- ui::theme::apply(ctx, self.state.is_dark);
- }
- });
+ // let theme_icon = if self.state.is_dark { "☀" } else { "🌙" };
+ // let theme_label = if self.state.is_dark { "Light" } else { "Dark" };
+ // if ui.add(
+ // egui::Button::new(
+ // egui::RichText::new(format!("{} {}", theme_icon, theme_label))
+ // .size(12.0)
+ // )
+ // .rounding(egui::Rounding::same(6.0))
+ // .min_size(egui::Vec2::new(100.0, 28.0))
+ // ).clicked() {
+ // self.state.is_dark = !self.state.is_dark;
+ // ui::theme::set_theme_mode(self.state.is_dark);
+ // ui::theme::apply(ctx, self.state.is_dark);
+ // }
+ // });
});
// ── Alt panel: navigasyon ────────────────────────────
egui::TopBottomPanel::bottom("footer")
.frame(egui::Frame::none()
- .fill(ui::theme::c_bg_panel())
- .stroke(egui::Stroke::new(1.0, ui::theme::c_border())))
+ .fill(ui::theme::c_footer_bg())
+ .stroke(egui::Stroke::new(1.0, ui::theme::c_footer_bg())))
.show(ctx, |ui| {
ui.add_space(10.0);
ui.horizontal(|ui| {
- ui.add_space(8.0);
-
- if !is_exec && !is_finish && ui.add(ui::theme::secondary_button(&t!("cancel"))).clicked() {
- ctx.send_viewport_cmd(egui::ViewportCommand::Close);
- }
+ ui.add_space(8.0);
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.add_space(8.0);
@@ -449,19 +451,22 @@ impl eframe::App for YaliApp {
} else {
t!("next")
};
- let btn = if is_valid {
- ui::theme::primary_button(&next_label)
- } else {
- ui::theme::secondary_button(&next_label)
+ if !is_exec && !is_finish && ui::theme::danger_button(ui, &t!("cancel")).clicked() {
+ self.show_cancel_dialog = true;
};
- if ui.add_enabled(is_valid, btn).clicked() {
+ let next_clicked = if is_valid {
+ ui::theme::primary_button(ui, &next_label).clicked()
+ } else {
+ ui::theme::secondary_button(ui, &next_label).clicked()
+ };
+ if next_clicked {
self.state.current_step += 1;
}
}
if cur > 0 && !is_exec {
ui.add_space(8.0);
- if ui.add(ui::theme::secondary_button(&t!("back"))).clicked() {
+ if ui::theme::secondary_button(ui, &t!("back")).clicked() {
self.state.current_step -= 1;
}
}
@@ -471,6 +476,26 @@ impl eframe::App for YaliApp {
ui.add_space(10.0);
});
+ // ── İptal onay diyaloğu ───────────────────────────────
+ if self.show_cancel_dialog {
+ egui::Window::new(t!("cancel_confirm_title"))
+ .collapsible(false)
+ .resizable(false)
+ .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0])
+ .show(ctx, |ui| {
+ ui.label(t!("cancel_confirm_msg"));
+ ui.add_space(12.0);
+ ui.horizontal(|ui| {
+ if ui.button(t!("cancel_confirm_yes")).clicked() {
+ ctx.send_viewport_cmd(egui::ViewportCommand::Close);
+ }
+ if ui.button(t!("cancel_confirm_no")).clicked() {
+ self.show_cancel_dialog = false;
+ }
+ });
+ });
+ }
+
// ── Merkez panel ─────────────────────────────────────
egui::CentralPanel::default()
.frame(egui::Frame::none()
diff --git a/src/steps/finish.rs b/src/steps/finish.rs
index 4ca82b4..f1b76cc 100644
--- a/src/steps/finish.rs
+++ b/src/steps/finish.rs
@@ -24,7 +24,7 @@ impl InstallerStep for FinishStep {
.size(24.0)
.strong()
.color(theme::c_text()),
- );
+ );
ui.add_space(8.0);
ui.label(
egui::RichText::new(t!("finish_description"))
@@ -35,26 +35,18 @@ impl InstallerStep for FinishStep {
ui.add_space(32.0);
// Yeniden Başlat — ana eylem butonu
- if ui.add(
- theme::primary_button(&t!("finish_restart"))
- .min_size(egui::vec2(200.0, 44.0)),
- ).clicked() {
+ if theme::primary_button(ui, &t!("finish_restart")).clicked() {
+ let _ = std::process::Command::new("sync").status();
+ let _ = std::process::Command::new("reboot")
+ .arg("-f")
+ .spawn();
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
- std::thread::spawn(|| {
- std::thread::sleep(std::time::Duration::from_millis(500));
- let _ = std::process::Command::new("reboot")
- .arg("-f")
- .spawn();
- });
}
ui.add_space(12.0);
// Canlı masaüstüne dön — ikincil eylem
- if ui.add(
- theme::secondary_button(&t!("finish_live"))
- .min_size(egui::vec2(200.0, 36.0)),
- ).clicked() {
+ if theme::secondary_button(ui, &t!("finish_live")).clicked() {
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
}
});
diff --git a/src/steps/partition.rs b/src/steps/partition.rs
index d255a48..b5e7693 100644
--- a/src/steps/partition.rs
+++ b/src/steps/partition.rs
@@ -81,10 +81,36 @@ fn read_existing_partitions(disk_path: &str) -> Vec String {
+ if name.starts_with("nvme") {
+ return "NVMe SSD".into();
+ }
+ if name.starts_with("mmcblk") {
+ return "MMC/SD".into();
+ }
+ // removable ortam (USB flash bellek)
+ let removable_path = format!("/sys/block/{}/removable", name);
+ if let Ok(val) = std::fs::read_to_string(&removable_path) {
+ if val.trim() == "1" {
+ return "USB".into();
+ }
+ }
+ // döner disk mi? (rotational=1 → HDD, 0 → SSD)
+ let rotational_path = format!("/sys/block/{}/queue/rotational", name);
+ if let Ok(val) = std::fs::read_to_string(&rotational_path) {
+ if val.trim() == "0" {
+ return "SSD".into();
+ }
+ }
+ "HDD".into()
+}
+
/// lsblk'dan gelen çıktı akıllıca ayrıştırılır; başarısız olursa /sys/block fallback devreye girer.
-fn list_block_devices() -> Vec {
+pub fn list_block_devices() -> Vec {
+ // Önce -P (key=value pairs) ile dene, boşluklu MODEL/VENDOR güvenli
let out = std::process::Command::new("lsblk")
- .args(["-d", "-o", "NAME,SIZE,MODEL", "-b", "--noheadings"])
+ .args(["-d", "-o", "NAME,SIZE,MODEL,VENDOR", "-b", "--noheadings", "-P"])
.output();
let mut disks = Vec::new();
@@ -93,45 +119,46 @@ fn list_block_devices() -> Vec {
if o.status.success() {
let text = String::from_utf8_lossy(&o.stdout);
for line in text.lines() {
- // split_whitespace ardışık tüm boşlukları tek bir ayırıcı gibi yakalar
- let mut tokens = line.split_whitespace();
-
- let name_raw = match tokens.next() {
- Some(n) => n,
- None => continue,
- };
+ // NAME="sda" SIZE="42949672960" MODEL="VBOX HARDDISK" VENDOR="ATA"
+ let mut name_raw = String::new();
+ let mut vendor = String::new();
+ let mut model = String::new();
+ let mut size = 0u64;
+
+ for pair in line.split_ascii_whitespace() {
+ let mut parts = pair.splitn(2, '=');
+ let key = parts.next().unwrap_or("");
+ let val = parts.next().unwrap_or("").trim_matches('"');
+ match key {
+ "NAME" => name_raw = val.to_string(),
+ "SIZE" => size = val.parse().unwrap_or(0),
+ "VENDOR"=> vendor = val.to_string(),
+ "MODEL" => model = val.to_string(),
+ _ => {}
+ }
+ }
+
+ if name_raw.is_empty() || size == 0 { continue; }
- // loop, ram, sr (CD-ROM) ve zram aygıtlarını atla
if name_raw.starts_with("loop")
|| name_raw.starts_with("ram")
|| name_raw.starts_with("sr")
|| name_raw.starts_with("zram")
{ continue; }
- let size_str = match tokens.next() {
- Some(s) => s,
- None => continue,
- };
-
- let size_bytes: u64 = size_str.parse().unwrap_or(0);
- // Eğer boyut 0 ise ekleme yapma ki lsblk patlarsa fallback çalışabilsin
- if size_bytes == 0 { continue; }
-
- // Kalan tüm token'lar model ismidir (örn: ["VBOX", "HARDDISK"])
- let model_tokens: Vec<&str> = tokens.collect();
- let model = model_tokens.join(" ");
-
disks.push(crate::installer::DiskInfo {
name: format!("/dev/{}", name_raw),
+ vendor,
model,
- size_gb: size_bytes / 1_073_741_824,
- size_bytes,
+ drive_type: detect_drive_type(&name_raw),
+ size_gb: size / 1_073_741_824,
+ size_bytes: size,
});
}
}
}
- // lsblk başarısız olduysa veya geçerli disk bulamadıysa temiz /sys/block fallback'i çalışır
+ // lsblk başarısız olduysa /sys/block fallback
if disks.is_empty() {
if let Ok(rd) = std::fs::read_dir("/sys/block") {
for entry in rd.flatten() {
@@ -149,13 +176,19 @@ fn list_block_devices() -> Vec {
let size_bytes = size_sectors * 512;
if size_bytes == 0 { continue; }
+ let vendor_path = format!("/sys/block/{}/device/vendor", name);
+ let vendor = std::fs::read_to_string(&vendor_path)
+ .unwrap_or_default().trim().to_string();
+
let model_path = format!("/sys/block/{}/device/model", name);
let model = std::fs::read_to_string(&model_path)
.unwrap_or_default().trim().to_string();
disks.push(crate::installer::DiskInfo {
name: format!("/dev/{}", name),
+ vendor,
model,
+ drive_type: detect_drive_type(&name),
size_gb: size_bytes / 1_073_741_824,
size_bytes,
});
@@ -359,22 +392,91 @@ impl PartitionStep {
fn show_auto_mode(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) {
ui.group(|ui| {
ui.label(t!("select_disk_label"));
- ui.add_space(4.0);
+ ui.add_space(8.0);
let disks = state.available_disks.clone();
- for disk in &disks {
- let too_small = disk.size_gb < MIN_DISK_GB;
- let label = egui::RichText::new(format!("{} — {} GB ({})", disk.name, disk.size_gb, disk.model)).strong().color(crate::ui::theme::c_accent());
- ui.add_enabled_ui(!too_small, |ui| {
- let selected = state.selected_disk.as_deref() == Some(&disk.name);
- if ui.radio(selected, label).clicked() {
- state.selected_disk = Some(disk.name.clone());
- state.partition_plan = make_plan(disk, self.is_uefi);
+ let kart_genislik = 180.0;
+ let kart_yukseklik = 160.0;
+
+ egui::Grid::new("disk_grid")
+ .min_col_width(kart_genislik + 12.0)
+ .spacing([12.0, 12.0])
+ .show(ui, |ui| {
+ for (i, disk) in disks.iter().enumerate() {
+ let too_small = disk.size_gb < MIN_DISK_GB;
+ let selected = state.selected_disk.as_deref() == Some(&disk.name);
+
+ let (rect, response) = ui.allocate_exact_size(
+ egui::vec2(kart_genislik, kart_yukseklik),
+ egui::Sense::click(),
+ );
+ let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
+
+ // arka plan
+ egui::Frame::none()
+ .fill(if selected {
+ crate::ui::theme::c_accent_dim()
+ } else if response.hovered() {
+ egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
+ } else if too_small {
+ egui::Color32::from_rgba_unmultiplied(60, 30, 30, 180)
+ } else {
+ crate::ui::theme::c_bg_widget()
+ })
+ .stroke(egui::Stroke::new(
+ if selected { 2.0 } else { 1.0 },
+ if selected { crate::ui::theme::c_accent() } else { crate::ui::theme::c_border() },
+ ))
+ .rounding(egui::Rounding::same(8.0))
+ .inner_margin(egui::Margin::same(8.0))
+ .show(child_ui, |ui| {
+ ui.set_min_size(egui::vec2(kart_genislik - 16.0, kart_yukseklik - 16.0));
+ ui.add_space(8.0);
+ ui.add(
+ egui::Image::new(egui::include_image!("../../assets/disk.png"))
+ .max_width(64.0)
+ .max_height(64.0)
+ .rounding(egui::Rounding::same(6.0))
+ .tint(if too_small {
+ egui::Color32::from_gray(80)
+ } else {
+ egui::Color32::WHITE
+ }),
+ );
+ ui.add_space(6.0);
+ let marka = if disk.vendor.is_empty() {
+ &disk.model
+ } else {
+ &disk.vendor
+ };
+ ui.label(
+ egui::RichText::new(format!("{} GB", disk.size_gb))
+ .size(14.0)
+ .strong()
+ .color(crate::ui::theme::c_text()),
+ );
+ ui.label(
+ egui::RichText::new(marka)
+ .size(11.0)
+ .color(crate::ui::theme::c_text_dim()),
+ );
+ if too_small {
+ ui.colored_label(
+ crate::ui::theme::c_error(),
+ t!("disk_too_small"),
+ );
+ }
+ });
+
+ if response.clicked() && !too_small {
+ state.selected_disk = Some(disk.name.clone());
+ state.partition_plan = make_plan(disk, self.is_uefi);
+ }
+
+ if (i + 1) % 3 == 0 {
+ ui.end_row();
+ }
}
});
- if too_small {
- ui.small(t!("disk_min_required", err = t!("disk_too_small"), n = MIN_DISK_GB.to_string()));
- }
- }
});
if let Some(ref plan) = state.partition_plan {
@@ -386,34 +488,96 @@ impl PartitionStep {
partition_bar(ui, plan);
ui.add_space(8.0);
- egui::Grid::new("plan_grid")
+ // Bootstrap 5 tarzı tablo
+ let col_widths = [0.40, 0.25, 0.35];
+ let tam_genislik = ui.available_width();
+ let header_color = egui::Color32::from_rgb(33, 37, 41); // dark bg
+ let header_text = egui::Color32::WHITE;
+ let _border_stroke = egui::Stroke::new(1.0, crate::ui::theme::c_border());
+
+ let grid = egui::Grid::new("plan_grid")
.num_columns(3)
- .spacing([20.0, 6.0])
- .striped(true)
- .show(ui, |ui| {
- ui.label(egui::RichText::new(t!("plan_col_part")).strong().color(crate::ui::theme::c_text()));
- ui.label(egui::RichText::new(t!("plan_col_fs")).strong().color(crate::ui::theme::c_text()));
- ui.label(egui::RichText::new(t!("plan_col_size")).strong().color(crate::ui::theme::c_text()));
- ui.end_row();
+ .spacing([0.0, 0.0])
+ .min_col_width(0.0);
- if plan.efi_mb > 0 {
- ui.label(format!("{}1 (EFI)", plan.disk));
- ui.label("FAT32");
- ui.label(format!("{} MB", plan.efi_mb));
- ui.end_row();
- }
- let swap_part = if plan.efi_mb > 0 { 2 } else { 1 };
- ui.label(format!("{}{} (swap)", plan.disk, swap_part));
- ui.label("swap");
- ui.label(format!("{} MB", plan.swap_mb));
- ui.end_row();
+ grid.show(ui, |ui| {
+ // ── Başlık satırı ─────────────────────────────────
+ let headers = [t!("plan_col_part"), t!("plan_col_fs"), t!("plan_col_size")];
+ for (j, h) in headers.into_iter().enumerate() {
+ let (rect, _) = ui.allocate_exact_size(
+ egui::vec2(tam_genislik * col_widths[j], 30.0),
+ egui::Sense::hover(),
+ );
+ let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
+ egui::Frame::none()
+ .fill(header_color)
+ .stroke(egui::Stroke::new(1.0, header_color))
+ .inner_margin(egui::Margin::symmetric(8.0, 4.0))
+ .show(child_ui, |ui| {
+ ui.vertical_centered(|ui| {
+ ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0));
+ });
+ });
+ }
+ ui.end_row();
- let root_part = swap_part + 1;
- ui.label(format!("{}{}{}", plan.disk, root_part, t!("plan_root_suffix")));
- ui.label("ext4");
- ui.label(format!("{:.1} GB", plan.root_mb as f64 / 1024.0));
- ui.end_row();
+ // ── Veri satırları ────────────────────────────────
+ struct Satir {
+ part: String,
+ fs: &'static str,
+ size: String,
+ }
+ let mut satirlar = Vec::new();
+ if plan.efi_mb > 0 {
+ satirlar.push(Satir {
+ part: format!("{}1 (EFI)", plan.disk),
+ fs: "FAT32",
+ size: format!("{} MB", plan.efi_mb),
+ });
+ }
+ let swap_part = if plan.efi_mb > 0 { 2 } else { 1 };
+ satirlar.push(Satir {
+ part: format!("{}{} (swap)", plan.disk, swap_part),
+ fs: "swap",
+ size: format!("{} MB", plan.swap_mb),
});
+ let root_part = swap_part + 1;
+ satirlar.push(Satir {
+ part: format!("{}{}{}", plan.disk, root_part, t!("plan_root_suffix")),
+ fs: "ext4",
+ size: format!("{:.1} GB", plan.root_mb as f64 / 1024.0),
+ });
+
+ for (row_idx, satir) in satirlar.iter().enumerate() {
+ let row_bg = if row_idx % 2 == 0 {
+ egui::Color32::from_rgba_unmultiplied(60, 60, 80, 60)
+ } else {
+ egui::Color32::TRANSPARENT
+ };
+ let hucreler: [&str; 3] = [&satir.part, satir.fs, &satir.size];
+ for (j, deger) in hucreler.iter().enumerate() {
+ let (rect, _) = ui.allocate_exact_size(
+ egui::vec2(tam_genislik * col_widths[j], 34.0),
+ egui::Sense::hover(),
+ );
+ let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
+ egui::Frame::none()
+ .fill(row_bg)
+ .stroke(egui::Stroke::new(0.0, egui::Color32::TRANSPARENT))
+ .inner_margin(egui::Margin::symmetric(8.0, 4.0))
+ .show(child_ui, |ui| {
+ ui.vertical_centered(|ui| {
+ ui.label(egui::RichText::new(*deger).size(13.0).color(crate::ui::theme::c_text()));
+ });
+ });
+ }
+ // satır alt çizgisi
+ if row_idx < satirlar.len() - 1 {
+ ui.separator();
+ }
+ ui.end_row();
+ }
+ });
ui.add_space(8.0);
ui.label(format!("{}: {}", t!("partition_table_type"), plan.table_type));
@@ -464,23 +628,81 @@ impl PartitionStep {
impl PartitionStep {
fn show_manual_mode(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) {
let accent = crate::ui::theme::c_accent();
+ let kart_genislik = 180.0;
+ let kart_yukseklik = 160.0;
// ── Disk seçimi (hedef disk) ────────────────────────────
ui.group(|ui| {
ui.label(t!("select_disk_label"));
- ui.add_space(4.0);
+ ui.add_space(8.0);
let disks = state.available_disks.clone();
- for disk in &disks {
- let selected = state.selected_disk.as_deref() == Some(&disk.name);
- let label = egui::RichText::new(format!("{} — {} GB ({})", disk.name, disk.size_gb, disk.model)).strong().color(crate::ui::theme::c_accent());
- if ui.radio(selected, label).clicked() {
- state.selected_disk = Some(disk.name.clone());
- // Disk değişince mevcut bölümleri oku ve listeyi güncelle.
- // Böylece kullanıcı diskin mevcut düzenini görebilir.
- state.custom_partitions = read_existing_partitions(&disk.name);
- self.manual.error = None;
- }
- }
+
+ egui::Grid::new("manual_disk_grid")
+ .min_col_width(kart_genislik + 12.0)
+ .spacing([12.0, 12.0])
+ .show(ui, |ui| {
+ for (i, disk) in disks.iter().enumerate() {
+ let selected = state.selected_disk.as_deref() == Some(&disk.name);
+
+ let (rect, response) = ui.allocate_exact_size(
+ egui::vec2(kart_genislik, kart_yukseklik),
+ egui::Sense::click(),
+ );
+ let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
+
+ egui::Frame::none()
+ .fill(if selected {
+ crate::ui::theme::c_accent_dim()
+ } else if response.hovered() {
+ egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
+ } else {
+ crate::ui::theme::c_bg_widget()
+ })
+ .stroke(egui::Stroke::new(
+ if selected { 2.0 } else { 1.0 },
+ if selected { crate::ui::theme::c_accent() } else { crate::ui::theme::c_border() },
+ ))
+ .rounding(egui::Rounding::same(8.0))
+ .inner_margin(egui::Margin::same(8.0))
+ .show(child_ui, |ui| {
+ ui.set_min_size(egui::vec2(kart_genislik - 16.0, kart_yukseklik - 16.0));
+ ui.add_space(8.0);
+ ui.add(
+ egui::Image::new(egui::include_image!("../../assets/disk.png"))
+ .max_width(64.0)
+ .max_height(64.0)
+ .rounding(egui::Rounding::same(6.0)),
+ );
+ ui.add_space(6.0);
+ let marka = if disk.vendor.is_empty() {
+ &disk.model
+ } else {
+ &disk.vendor
+ };
+ ui.label(
+ egui::RichText::new(format!("{} GB", disk.size_gb))
+ .size(14.0)
+ .strong()
+ .color(crate::ui::theme::c_text()),
+ );
+ ui.label(
+ egui::RichText::new(marka)
+ .size(11.0)
+ .color(crate::ui::theme::c_text_dim()),
+ );
+ });
+
+ if response.clicked() {
+ state.selected_disk = Some(disk.name.clone());
+ state.custom_partitions = read_existing_partitions(&disk.name);
+ self.manual.error = None;
+ }
+
+ if (i + 1) % 3 == 0 {
+ ui.end_row();
+ }
+ }
+ });
});
ui.add_space(8.0);
@@ -495,46 +717,114 @@ impl PartitionStep {
// ── Mevcut bölüm listesi tablosu ───────────────────────
ui.label(egui::RichText::new(t!("mp_plan_title")).strong().color(crate::ui::theme::c_text()));
- ui.add_space(4.0);
+ ui.add_space(6.0);
let mut delete_idx: Option = None;
- egui::Grid::new("manual_parts_grid")
+ let col_widths = [0.28, 0.12, 0.18, 0.27, 0.15];
+ let tam_genislik = ui.available_width();
+ let header_color = egui::Color32::from_rgb(33, 37, 41);
+ let header_text = egui::Color32::WHITE;
+ let _border_stroke = egui::Stroke::new(1.0, crate::ui::theme::c_border());
+
+ let grid = egui::Grid::new("manual_parts_grid")
.num_columns(5)
- .spacing([12.0, 6.0])
- .striped(true)
- .show(ui, |ui| {
- // Başlık
- ui.label(egui::RichText::new(t!("mp_device")).strong().color(crate::ui::theme::c_text()));
- ui.label(egui::RichText::new(t!("mp_size")).strong().color(crate::ui::theme::c_text()));
- ui.label(egui::RichText::new(t!("mp_fstype")).strong().color(crate::ui::theme::c_text()));
- ui.label(egui::RichText::new(t!("mp_mountpoint")).strong().color(crate::ui::theme::c_text()));
- ui.label(egui::RichText::new(t!("mp_action")).strong().color(crate::ui::theme::c_text()));
- ui.end_row();
+ .spacing([0.0, 0.0])
+ .min_col_width(0.0);
- for (i, part) in state.custom_partitions.iter().enumerate() {
- let size_str = if part.size_mb == 0 {
- t!("mp_size_remaining").to_string()
- } else if part.size_mb >= 1024 {
- format!("{:.1} GB", part.size_mb as f64 / 1024.0)
- } else {
- format!("{} MB", part.size_mb)
- };
+ grid.show(ui, |ui| {
+ // ── Başlık satırı ─────────────────────────────────
+ let headers: [String; 5] = [
+ t!("mp_device").to_string(),
+ t!("mp_size").to_string(),
+ t!("mp_fstype").to_string(),
+ t!("mp_mountpoint").to_string(),
+ t!("mp_action").to_string(),
+ ];
+ for (j, h) in headers.into_iter().enumerate() {
+ let (rect, _) = ui.allocate_exact_size(
+ egui::vec2(tam_genislik * col_widths[j], 30.0),
+ egui::Sense::hover(),
+ );
+ let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
+ egui::Frame::none()
+ .fill(header_color)
+ .stroke(egui::Stroke::new(1.0, header_color))
+ .inner_margin(egui::Margin::symmetric(8.0, 4.0))
+ .show(child_ui, |ui| {
+ ui.vertical_centered(|ui| {
+ ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0));
+ });
+ });
+ }
+ ui.end_row();
- ui.label(&part.device);
- let mut fstype_label = part.fstype.label().to_string();
- if part.encrypt {
- fstype_label = format!("🔐 {}", fstype_label);
- }
- ui.label(&size_str);
- ui.label(fstype_label);
- ui.label(&part.mountpoint);
- if ui.small_button("🗑").on_hover_text(t!("mp_delete")).clicked() {
- delete_idx = Some(i);
- }
- ui.end_row();
+ // ── Veri satırları ────────────────────────────────
+ for (row_idx, part) in state.custom_partitions.iter().enumerate() {
+ let row_bg = if row_idx % 2 == 0 {
+ egui::Color32::from_rgba_unmultiplied(60, 60, 80, 60)
+ } else {
+ egui::Color32::TRANSPARENT
+ };
+
+ let size_str = if part.size_mb == 0 {
+ t!("mp_size_remaining").to_string()
+ } else if part.size_mb >= 1024 {
+ format!("{:.1} GB", part.size_mb as f64 / 1024.0)
+ } else {
+ format!("{} MB", part.size_mb)
+ };
+
+ let mut fstype_label = part.fstype.label().to_string();
+ if part.encrypt {
+ fstype_label = format!("🔐 {}", fstype_label);
}
- });
+
+ let hucreler: [(String, bool); 5] = [
+ (part.device.clone(), false),
+ (size_str, false),
+ (fstype_label, false),
+ (part.mountpoint.clone(), false),
+ (String::new(), true), // action column - button
+ ];
+
+ for (j, (deger, is_action)) in hucreler.iter().enumerate() {
+ let (rect, _response) = ui.allocate_exact_size(
+ egui::vec2(tam_genislik * col_widths[j], 34.0),
+ egui::Sense::click(),
+ );
+ let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
+
+ if *is_action {
+ egui::Frame::none()
+ .fill(row_bg)
+ .stroke(egui::Stroke::new(0.0, egui::Color32::TRANSPARENT))
+ .inner_margin(egui::Margin::symmetric(8.0, 4.0))
+ .show(child_ui, |ui| {
+ ui.vertical_centered(|ui| {
+ if ui.small_button("🗑").on_hover_text(t!("mp_delete")).clicked() {
+ delete_idx = Some(row_idx);
+ }
+ });
+ });
+ } else {
+ egui::Frame::none()
+ .fill(row_bg)
+ .stroke(egui::Stroke::new(0.0, egui::Color32::TRANSPARENT))
+ .inner_margin(egui::Margin::symmetric(8.0, 4.0))
+ .show(child_ui, |ui| {
+ ui.vertical_centered(|ui| {
+ ui.label(egui::RichText::new(deger).size(13.0).color(crate::ui::theme::c_text()));
+ });
+ });
+ }
+ }
+ if row_idx < state.custom_partitions.len() - 1 {
+ ui.separator();
+ }
+ ui.end_row();
+ }
+ });
// Silme onayı
if let Some(idx) = delete_idx {
diff --git a/src/steps/rescue.rs b/src/steps/rescue.rs
index aeb48d6..0b5c96d 100644
--- a/src/steps/rescue.rs
+++ b/src/steps/rescue.rs
@@ -238,18 +238,15 @@ impl RescueStep {
// İşlem butonları
ui.horizontal(|ui| {
// 1. Bağla
- if ui.add_enabled(
- self.selected.is_some() && !self.mount_done,
- theme::secondary_button("📂 /mnt'a Bağla"),
- ).clicked() {
+ let cond = self.selected.is_some() && !self.mount_done;
+ let resp = theme::secondary_button(ui, "📂 /mnt'a Bağla");
+ if cond && resp.clicked() {
self.mount_selected();
}
// 2. Chroot
- if ui.add_enabled(
- self.mount_done,
- theme::secondary_button(&t!("rescue_chroot")),
- ).clicked() {
+ let resp = theme::secondary_button(ui, &t!("rescue_chroot"));
+ if self.mount_done && resp.clicked() {
self.log.push(t!("rescue_chroot_start").to_string());
match Self::run_rescue_cmd("chroot", &["/mnt", "/bin/bash", "-c", "echo 'chroot OK'"]) {
Ok(msg) => self.log.push(format!("✓ {}", msg)),
@@ -258,10 +255,8 @@ impl RescueStep {
}
// 3. GRUB yeniden yükle
- if ui.add_enabled(
- self.mount_done,
- theme::secondary_button(&t!("rescue_grub")),
- ).clicked() {
+ let resp = theme::secondary_button(ui, &t!("rescue_grub"));
+ if self.mount_done && resp.clicked() {
self.log.push(t!("rescue_grub_start").to_string());
let boot_dev = state.bootloader_device.clone();
let steps: &[(&str, &[&str])] = &[
@@ -311,7 +306,7 @@ impl RescueStep {
// Tara butonu
ui.horizontal(|ui| {
- if ui.add(theme::secondary_button(&t!("rescue_pisi_history_scan"))).clicked() {
+ if theme::secondary_button(ui, &t!("rescue_pisi_history_scan")).clicked() {
self.scan_pisi_history();
}
if self.pisi.scanned {
@@ -392,7 +387,8 @@ impl RescueStep {
// Geri al butonu
let can_takeback = self.pisi.selected.is_some() && !self.pisi.running;
- if ui.add_enabled(can_takeback, theme::primary_button(&t!("rescue_pisi_takeback"))).clicked() {
+ let resp = theme::primary_button(ui, &t!("rescue_pisi_takeback"));
+ if can_takeback && resp.clicked() {
if let Some(idx) = self.pisi.selected {
let op = self.pisi.entries[idx].op;
self.run_takeback(op);
@@ -430,7 +426,7 @@ impl InstallerStep for RescueStep {
if self.detected.is_empty() {
theme::warning_box(ui, &t!("rescue_no_installations"));
ui.add_space(6.0);
- if ui.add(theme::secondary_button(&t!("rescue_scan"))).clicked() {
+ if theme::secondary_button(ui, &t!("rescue_scan")).clicked() {
self.detect_installations();
}
return;
@@ -505,7 +501,7 @@ impl InstallerStep for RescueStep {
// Geri dön butonu
ui.add_space(8.0);
- if ui.add(theme::secondary_button(&t!("rescue_return"))).clicked() {
+ if theme::secondary_button(ui, &t!("rescue_return")).clicked() {
state.rescue_mode = false;
}
}
diff --git a/src/steps/users.rs b/src/steps/users.rs
index 939caab..af3aace 100644
--- a/src/steps/users.rs
+++ b/src/steps/users.rs
@@ -1,24 +1,21 @@
use eframe::egui;
use rust_i18n::t;
use crate::installer::{GlobalState, InstallerStep};
+use crate::funct::{ form_input_text, form_input_password, form_label, form_checkbox };
/// Kullanıcı adı, şifre, hostname ve yönetici (root) şifresi ayarları adımı.
pub struct UsersStep {
+ use_same_for_admin: bool,
show_password: bool,
show_password_confirm: bool,
- show_root_password: bool,
- show_root_password_confirm: bool,
- use_same_for_admin: bool,
}
impl Default for UsersStep {
fn default() -> Self {
Self {
+ use_same_for_admin: true,
show_password: false,
show_password_confirm: false,
- show_root_password: false,
- show_root_password_confirm: false,
- use_same_for_admin: true,
}
}
}
@@ -152,47 +149,47 @@ impl InstallerStep for UsersStep {
);
ui.add_space(12.0);
- // ─── Kullanıcı Bilgileri Grubu ──────────────────────────────────
+ // ─── Kullanıcı Bilgileri Formu ──────────────────────────────────
egui::Frame::group(ui.style())
.fill(theme::c_bg_widget())
.rounding(6.0)
- .inner_margin(egui::Margin::same(12.0))
+ .inner_margin(egui::Margin::symmetric(10.0, 10.0))
.show(ui, |ui| {
ui.set_width(ui.available_width());
- egui::Grid::new("users_grid")
- .num_columns(2)
- .spacing([12.0, 10.0])
- .show(ui, |ui| {
- // Gerçek ad
- ui.label(egui::RichText::new(t!("real_name_label")).strong().color(theme::c_text()));
- ui.horizontal(|ui| {
- let prev = state.real_name.clone();
- ui.text_edit_singleline(&mut state.real_name);
- if state.real_name != prev && !state.real_name.is_empty() {
- state.username = derive_username(&state.real_name);
- }
- if !state.real_name.is_empty() {
- ui.colored_label(theme::c_success(), "✓");
- }
- });
- ui.end_row();
+ ui.horizontal(|ui| {
+ ui.vertical(|ui| {
+ ui.add_space(10.0);
+
+ // Gerçek ad
+ form_label(ui, &t!("real_name_label"));
+ {
+ let prev = state.real_name.clone();
+ form_input_text(ui, &mut state.real_name);
+ if state.real_name != prev && !state.real_name.is_empty() {
+ state.username = derive_username(&state.real_name);
+ }
+ }
+ if !state.real_name.is_empty() {
+ ui.colored_label(theme::c_success(), "✅");
+ } else {
+ ui.colored_label(theme::c_error(), "❌");
+ }
+ ui.add_space(6.0);
- // Kullanıcı adı (otomatik türetilir, düzenlenebilir)
- ui.label(egui::RichText::new(t!("username_label")).strong().color(theme::c_text()));
- ui.horizontal(|ui| {
- ui.text_edit_singleline(&mut state.username);
- if !state.username.is_empty() {
- if is_valid_username(&state.username) {
- ui.colored_label(theme::c_success(), "✓");
- } else {
- ui.colored_label(theme::c_error(), "✗");
- }
- }
- });
- ui.end_row();
+ // Kullanıcı adı (otomatik türetilir, düzenlenebilir)
+ form_label(ui, &t!("username_label"));
+ form_input_text(ui, &mut state.username);
+ if !state.username.is_empty() {
+ if is_valid_username(&state.username) {
+ ui.colored_label(theme::c_success(), "✅");
+ } else {
+ ui.colored_label(theme::c_warning(), t!("username_invalid"));
+ }
+ }
+ ui.add_space(6.0);
// Şifre
- ui.label(egui::RichText::new(t!("password_label")).strong().color(theme::c_text()));
+ form_label(ui, &t!("password_label"));
// OEM modunda varsayılan şifre uyarısı göster
if state.oem_mode && !state.oem_password_changed {
ui.colored_label(
@@ -200,68 +197,56 @@ impl InstallerStep for UsersStep {
t!("oem_change_password_warning"),
);
}
- ui.horizontal(|ui| {
+ {
+ let show_pwd = &mut self.show_password;
let before = state.password.clone();
- if self.show_password {
- ui.text_edit_singleline(&mut state.password);
- } else {
- ui.add(egui::TextEdit::singleline(&mut state.password).password(true));
- }
+ form_input_password(ui, &mut state.password, show_pwd);
// Kullanıcı şifreyi değiştirdiyse OEM bayrağını kaldır
if state.oem_mode && state.password != before {
state.oem_password_changed = true;
}
- if ui.small_button(if self.show_password { "🙈" } else { "👁" }).clicked() {
- self.show_password = !self.show_password;
- }
- if !state.password.is_empty() {
- let (label, color) = password_strength(&state.password);
- ui.colored_label(color, label);
- }
- });
- ui.end_row();
+ }
+ if !state.password.is_empty() {
+ let (label, color) = password_strength(&state.password);
+ ui.colored_label(color, label);
+ }
+ ui.add_space(6.0);
// Şifre doğrulama
- ui.label(egui::RichText::new(t!("password_confirm_label")).strong().color(theme::c_text()));
- ui.horizontal(|ui| {
- if self.show_password_confirm {
- ui.text_edit_singleline(&mut state.password_confirm);
+ form_label(ui, &t!("password_confirm_label"));
+ {
+ let show_pwd = &mut self.show_password_confirm;
+ form_input_password(ui, &mut state.password_confirm, show_pwd);
+ }
+ if !state.password_confirm.is_empty() {
+ if state.password == state.password_confirm {
+ ui.colored_label(theme::c_success(), "✅");
} else {
- ui.add(egui::TextEdit::singleline(&mut state.password_confirm).password(true));
+ ui.colored_label(theme::c_warning(), t!("passwords_no_match"));
}
- if ui.small_button(if self.show_password_confirm { "🙈" } else { "👁" }).clicked() {
- self.show_password_confirm = !self.show_password_confirm;
- }
- if !state.password_confirm.is_empty() {
- if state.password == state.password_confirm {
- ui.colored_label(theme::c_success(), "✓");
- } else {
- ui.colored_label(theme::c_error(), t!("passwords_no_match"));
- }
- }
- });
- ui.end_row();
+ }
+ ui.add_space(6.0);
// Hostname
- ui.label(egui::RichText::new(t!("hostname_label")).strong().color(theme::c_text()));
- ui.horizontal(|ui| {
- ui.text_edit_singleline(&mut state.hostname);
- if !state.hostname.is_empty() {
- if is_valid_hostname(&state.hostname) {
- ui.colored_label(theme::c_success(), "✓");
- } else {
- ui.colored_label(theme::c_error(), "✗");
- }
+ form_label(ui, &t!("hostname_label"));
+ form_input_text(ui, &mut state.hostname);
+ if !state.hostname.is_empty() {
+ if is_valid_hostname(&state.hostname) {
+ ui.colored_label(theme::c_success(), "✅");
+ } else {
+ ui.colored_label(theme::c_warning(), t!("hostname_invalid"));
}
- });
- ui.end_row();
+ }
+
});
+ ui.add_space(10.0);
+ });
});
ui.add_space(14.0);
// ─── Yönetici (root) Ayarları ─────────────────────────────────────
- ui.checkbox(&mut self.use_same_for_admin, egui::RichText::new(t!("use_same_for_admin")).strong().color(theme::c_text()));
+ form_checkbox(ui, &mut self.use_same_for_admin, &t!("use_same_for_admin"));
if self.use_same_for_admin {
state.root_password = state.password.clone();
@@ -277,59 +262,42 @@ impl InstallerStep for UsersStep {
ui.label(egui::RichText::new(t!("admin_description")).size(12.0).color(theme::c_text_dim()));
ui.add_space(8.0);
- egui::Grid::new("admin_grid")
- .num_columns(2)
- .spacing([12.0, 10.0])
- .show(ui, |ui| {
- // Root şifresi
- ui.label(egui::RichText::new(t!("admin_password_label")).strong().color(theme::c_text()));
- ui.horizontal(|ui| {
- if self.show_root_password {
- ui.text_edit_singleline(&mut state.root_password);
- } else {
- ui.add(egui::TextEdit::singleline(&mut state.root_password).password(true));
- }
- if ui.small_button(if self.show_root_password { "🙈" } else { "👁" }).clicked() {
- self.show_root_password = !self.show_root_password;
- }
- if !state.root_password.is_empty() && state.root_password.len() < 8 {
- ui.colored_label(theme::c_error(), t!("admin_password_short"));
- }
- });
- ui.end_row();
+ // Root şifresi
+
+ ui.label(egui::RichText::new(t!("admin_password_label")).strong().color(theme::c_text()));
+ ui.horizontal(|ui| {
+ ui.add(
+ eframe::egui::TextEdit::singleline(&mut state.root_password)
+ .password(true)
+ .desired_width(f32::INFINITY)
+ .min_size(eframe::egui::vec2(0.0, 32.0))
+ );
- // Şifre doğrulama
- ui.label(egui::RichText::new(t!("admin_password_confirm_label")).strong().color(theme::c_text()));
- ui.horizontal(|ui| {
- if self.show_root_password_confirm {
- ui.text_edit_singleline(&mut state.root_password_confirm);
- } else {
- ui.add(egui::TextEdit::singleline(&mut state.root_password_confirm).password(true));
- }
- if ui.small_button(if self.show_root_password_confirm { "🙈" } else { "👁" }).clicked() {
- self.show_root_password_confirm = !self.show_root_password_confirm;
- }
- if !state.root_password_confirm.is_empty() {
- if state.root_password == state.root_password_confirm {
- ui.colored_label(theme::c_success(), "✓");
- } else {
- ui.colored_label(theme::c_error(), t!("passwords_no_match"));
- }
- }
- });
- ui.end_row();
- });
+ if !state.root_password.is_empty() && state.root_password.len() < 8 {
+ ui.colored_label(theme::c_error(), t!("admin_password_short"));
+ }
+ });
+ ui.add_space(8.0);
+
+ // Şifre doğrulama
+ ui.label(egui::RichText::new(t!("admin_password_confirm_label")).strong().color(theme::c_text()));
+
+ ui.horizontal(|ui| {
+ ui.add(
+ eframe::egui::TextEdit::singleline(&mut state.root_password_confirm)
+ .password(true)
+ .desired_width(f32::INFINITY)
+ .min_size(eframe::egui::vec2(0.0, 32.0))
+ );
+ });
+ if state.root_password == state.root_password_confirm {
+ ui.colored_label(theme::c_success(), "✅");
+ } else {
+ ui.colored_label(theme::c_error(), t!("passwords_no_match"));
+ }
});
}
- // Hata mesajları gösterimi
- ui.add_space(8.0);
- if !state.username.is_empty() && !is_valid_username(&state.username) {
- ui.colored_label(theme::c_error(), t!("username_invalid"));
- }
- if !state.hostname.is_empty() && !is_valid_hostname(&state.hostname) {
- ui.colored_label(theme::c_error(), t!("hostname_invalid"));
- }
}
fn is_complete(&self, state: &GlobalState) -> bool {
diff --git a/src/ui/error_screen.rs b/src/ui/error_screen.rs
index 8be4dc3..7d78a1c 100644
--- a/src/ui/error_screen.rs
+++ b/src/ui/error_screen.rs
@@ -136,13 +136,13 @@ impl ErrorScreen {
let side = (ui.available_width() - total) / 2.0;
ui.add_space(side.max(0.0));
- if ui.add(theme::danger_button(&t!("error_quit"))).clicked() {
+ if theme::danger_button(ui, &t!("error_quit")).clicked() {
on_quit();
}
ui.add_space(gap);
- if ui.add(theme::primary_button(&t!("error_retry"))).clicked() {
+ if theme::primary_button(ui, &t!("error_retry")).clicked() {
on_retry();
}
});
diff --git a/src/ui/theme.rs b/src/ui/theme.rs
index 71a36b4..060d3af 100644
--- a/src/ui/theme.rs
+++ b/src/ui/theme.rs
@@ -23,6 +23,10 @@ static WARNING: AtomicU32 = AtomicU32::new(0xFF9800);
static ERROR: AtomicU32 = AtomicU32::new(0xF44336);
static SIDEBAR: AtomicU32 = AtomicU32::new(0x0B0B0D);
static ACCENT_COLOR: AtomicU32 = AtomicU32::new(0xd9005b); // Pisi Premium Vurgu (#d9005b)
+static SIDEBAR_TEXT: AtomicU32 = AtomicU32::new(0x000000);
+
+
+
// Helper to convert hex to Color32
fn color_from_hex(rgb: u32) -> Color32 {
@@ -39,6 +43,8 @@ pub fn c_success() -> Color32 { color_from_hex(SUCCESS.load(Ordering::Relaxed)
pub fn c_warning() -> Color32 { color_from_hex(WARNING.load(Ordering::Relaxed)) }
pub fn c_error() -> Color32 { color_from_hex(ERROR.load(Ordering::Relaxed)) }
pub fn c_sidebar() -> Color32 { color_from_hex(SIDEBAR.load(Ordering::Relaxed)) }
+pub fn c_sidebar_text() -> Color32 { color_from_hex(SIDEBAR_TEXT.load(Ordering::Relaxed)) }
+pub fn c_footer_bg() -> Color32 { color_from_hex(0xf7f7f7) }
pub fn set_theme_mode(is_dark: bool) {
if is_dark {
@@ -50,13 +56,19 @@ pub fn set_theme_mode(is_dark: bool) {
TEXT_DIM.store(0x9E9EAF, Ordering::Relaxed);
SIDEBAR.store(0x0B0B0D, Ordering::Relaxed);
} else {
- BG_DARK.store(0xF0F0F5, Ordering::Relaxed);
- BG_PANEL.store(0xFFFFFF, Ordering::Relaxed);
- BG_WIDGET.store(0xE8E8EE, Ordering::Relaxed);
- BORDER.store(0xD0D0DA, Ordering::Relaxed);
- TEXT.store(0x20202A, Ordering::Relaxed);
- TEXT_DIM.store(0x60606A, Ordering::Relaxed);
- SIDEBAR.store(0xE4E4EA, Ordering::Relaxed);
+ BG_DARK.store(0xf7f7f7, Ordering::Relaxed);
+ SIDEBAR.store(0x292f34, Ordering::Relaxed);
+ TEXT.store(0x000000, Ordering::Relaxed);
+ TEXT_DIM.store(0x000000, Ordering::Relaxed);
+ SIDEBAR_TEXT.store(0xffffff, Ordering::Relaxed);
+
+ // BG_DARK.store(0xF0F0F5, Ordering::Relaxed);
+ // BG_PANEL.store(0xFFFFFF, Ordering::Relaxed);
+ // BG_WIDGET.store(0xE8E8EE, Ordering::Relaxed);
+ // BORDER.store(0xD0D0DA, Ordering::Relaxed);
+ // TEXT.store(0x20202A, Ordering::Relaxed);
+ // TEXT_DIM.store(0x60606A, Ordering::Relaxed);
+ // SIDEBAR.store(0xE4E4EA, Ordering::Relaxed);
}
}
@@ -85,32 +97,59 @@ pub fn apply(ctx: &egui::Context, is_dark: bool) {
fn setup_fonts(ctx: &egui::Context) {
let mut fonts = egui::FontDefinitions::default();
- // egui'nin yerleşik fontlarına ek olarak sistem fontunu dene.
- // ISO ortamında genellikle DejaVu veya Noto bulunur.
- // Bulunamazsa egui varsayılanı kullanılır.
- for path in [
- "/usr/share/fonts/exo-2/Exo2-Medium.ttf",
- "/usr/share/fonts/exo-2/Exo2-Regular.ttf",
- "/usr/share/fonts/google-exo2/Exo2-Medium.ttf",
- "/usr/share/fonts/google-exo2/Exo2-Regular.ttf",
+ // 1. ADIM: Sadece Metin (Text) Fontunu Bul ve Yükle
+ let text_font_paths = [
+ "/usr/share/fonts/TTF/OpenSans-Regular.ttf",
+ "/usr/share/fonts/noto/NotoSans-Regular.ttf",
+ "/usr/share/fonts/exo-1/Exo-Regular.otf",
"/usr/share/fonts/exo-1/Exo2-Medium.ttf",
"/usr/share/fonts/exo-1/Exo-Medium.otf",
- "/usr/share/fonts/exo-1/Exo-Regular.otf",
- "/usr/share/fonts/truetype/exo2/Exo2-Medium.ttf",
- "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
- "/usr/share/fonts/noto/NotoSans-Regular.ttf",
- "/usr/share/fonts/TTF/DejaVuSans.ttf",
- ] {
+ ];
+
+ for path in text_font_paths {
if let Ok(data) = std::fs::read(path) {
fonts.font_data.insert(
- "system_font".to_owned(),
+ "system_text_font".to_owned(),
egui::FontData::from_owned(data),
);
+
+ // Metin fontunu en başa (0. indeks) koyuyoruz ki varsayılan olarak bu kullanılsın
fonts
.families
.entry(egui::FontFamily::Proportional)
.or_default()
- .insert(0, "system_font".to_owned());
+ .insert(0, "system_text_font".to_owned());
+ break;
+ }
+ }
+
+ // 2. ADIM: Renkli Emoji Fontunu Ara ve "Fallback" (Yedek) Olarak Sona Ekle
+ // ISO ortamlarında Noto Color Emoji genellikle bu yollardan birinde olur
+ let emoji_font_paths = [
+ "/usr/share/fonts/noto/NotoColorEmoji.ttf",
+ ];
+
+ for path in emoji_font_paths {
+ if let Ok(data) = std::fs::read(path) {
+ fonts.font_data.insert(
+ "system_emoji_font".to_owned(),
+ egui::FontData::from_owned(data),
+ );
+
+ // ÖNEMLİ: Emojiyi listenin SONUNA (push ile) ekliyoruz.
+ // Böylece egui normal harfleri sistem fontuyla yazacak,
+ // harf sistem fontunda yoksa (yani emojiyse) gidip bu fonttan alacak.
+ fonts
+ .families
+ .entry(egui::FontFamily::Proportional)
+ .or_default()
+ .push("system_emoji_font".to_owned());
+
+ fonts
+ .families
+ .entry(egui::FontFamily::Monospace)
+ .or_default()
+ .insert(0, "system_emoji_font".to_owned());
break;
}
}
@@ -118,6 +157,57 @@ fn setup_fonts(ctx: &egui::Context) {
ctx.set_fonts(fonts);
}
+// fn build_visuals(is_dark: bool) -> Visuals {
+// let mut v = if is_dark { Visuals::dark() } else { Visuals::light() };
+
+// // Genel arka planlar
+// v.window_fill = c_bg_dark();
+// v.panel_fill = c_bg_panel();
+// v.faint_bg_color = c_bg_widget();
+// v.extreme_bg_color = c_sidebar();
+// v.code_bg_color = if is_dark { Color32::from_rgb(0x18, 0x18, 0x28) } else { Color32::from_rgb(0xEE, 0xEE, 0xF5) };
+
+// // Metin
+// v.override_text_color = None;
+
+// // Kenarlıklar
+// v.widgets.noninteractive.bg_stroke = Stroke::new(1.0, c_border());
+// v.widgets.inactive.bg_stroke = Stroke::new(1.0, c_border());
+// v.widgets.hovered.bg_stroke = Stroke::new(1.5, c_accent());
+// v.widgets.active.bg_stroke = Stroke::new(2.0, c_accent());
+
+// // Widget dolguları
+// v.widgets.noninteractive.bg_fill = c_bg_widget();
+// v.widgets.inactive.bg_fill = c_bg_widget();
+// v.widgets.hovered.bg_fill = if is_dark { Color32::from_rgb(0x35, 0x35, 0x55) } else { Color32::from_rgb(0xD5, 0xD5, 0xE5) };
+// v.widgets.active.bg_fill = c_accent_dim();
+
+// // Metin renkleri
+// v.widgets.noninteractive.fg_stroke = Stroke::new(1.0, c_text());
+// v.widgets.inactive.fg_stroke = Stroke::new(1.0, c_text());
+// v.widgets.hovered.fg_stroke = Stroke::new(1.5, c_text());
+// v.widgets.active.fg_stroke = Stroke::new(2.0, Color32::WHITE);
+
+// // Yuvarlak köşeler
+// v.widgets.noninteractive.rounding = Rounding::same(6.0);
+// v.widgets.inactive.rounding = Rounding::same(6.0);
+// v.widgets.hovered.rounding = Rounding::same(6.0);
+// v.widgets.active.rounding = Rounding::same(6.0);
+
+// // Seçim rengi
+// v.selection.bg_fill = c_accent_dim();
+// v.selection.stroke = Stroke::new(1.0, c_accent());
+
+// // Hyperlink
+// v.hyperlink_color = c_accent();
+
+// // Pencere kenarlığı
+// v.window_stroke = Stroke::new(1.0, c_border());
+// v.window_rounding = Rounding::same(8.0);
+
+// v
+// }
+
fn build_visuals(is_dark: bool) -> Visuals {
let mut v = if is_dark { Visuals::dark() } else { Visuals::light() };
@@ -131,25 +221,31 @@ fn build_visuals(is_dark: bool) -> Visuals {
// Metin
v.override_text_color = None;
- // Kenarlıklar
+ // ─── KENARLIKLAR (Calamares Uyumu için İnce İnce Yumuşatıldı) ───────────────────
v.widgets.noninteractive.bg_stroke = Stroke::new(1.0, c_border());
- v.widgets.inactive.bg_stroke = Stroke::new(1.0, c_border());
+ v.widgets.inactive.bg_stroke = Stroke::new(1.0, Color32::from_rgba_unmultiplied(255, 255, 255, 30)); // Buton etrafında hafif saydam parlaklık
v.widgets.hovered.bg_stroke = Stroke::new(1.5, c_accent());
v.widgets.active.bg_stroke = Stroke::new(2.0, c_accent());
- // Widget dolguları
+ // ─── WIDGET DOLGULARI (Burası ComboBox ve Butonların Kaderini Belirliyor) ───────
v.widgets.noninteractive.bg_fill = c_bg_widget();
- v.widgets.inactive.bg_fill = c_bg_widget();
- v.widgets.hovered.bg_fill = if is_dark { Color32::from_rgb(0x35, 0x35, 0x55) } else { Color32::from_rgb(0xD5, 0xD5, 0xE5) };
- v.widgets.active.bg_fill = c_accent_dim();
+
+ // Pasif Hali: Calamares Mavisi (İstiyorsan c_accent() ile Pisi Vişne Rengine de Çekebilirsin)
+ v.widgets.inactive.bg_fill = Color32::from_rgb(46, 124, 219);
+
+ // Üzerine Gelme Hali: Parlayan Açık Mavi
+ v.widgets.hovered.bg_fill = Color32::from_rgb(59, 144, 240);
+
+ // Tıklanma/Açık Kalma Hali: Koyu Lacivert/Mavi
+ v.widgets.active.bg_fill = Color32::from_rgb(20, 70, 140);
- // Metin renkleri
+ // ─── METİN RENKLERİ ────────────────────────────────────────────────────────────
v.widgets.noninteractive.fg_stroke = Stroke::new(1.0, c_text());
- v.widgets.inactive.fg_stroke = Stroke::new(1.0, c_text());
- v.widgets.hovered.fg_stroke = Stroke::new(1.5, c_text());
+ v.widgets.inactive.fg_stroke = Stroke::new(1.0, Color32::WHITE); // Mavi üstüne beyaz metin okunaklı kılar
+ v.widgets.hovered.fg_stroke = Stroke::new(1.5, Color32::WHITE);
v.widgets.active.fg_stroke = Stroke::new(2.0, Color32::WHITE);
- // Yuvarlak köşeler
+ // ─── YUVARLAK KÖŞELER (Zaten 6.0'dı, Tam İstediğin Calamares Kıvamında) ─────────
v.widgets.noninteractive.rounding = Rounding::same(6.0);
v.widgets.inactive.rounding = Rounding::same(6.0);
v.widgets.hovered.rounding = Rounding::same(6.0);
@@ -193,31 +289,90 @@ fn build_style() -> egui::Style {
// ─── Yardımcı widget'lar ─────────────────────────────────────────
-/// Vurgulu "ana eylem" butonu (mavi dolgu).
-pub fn primary_button(text: &str) -> egui::Button<'_> {
- egui::Button::new(egui::RichText::new(text).color(Color32::WHITE))
- .fill(c_accent())
- .stroke(Stroke::new(1.0, c_accent()))
- .rounding(Rounding::same(6.0))
- .min_size(Vec2::new(100.0, 32.0))
+fn lerp_color(a: Color32, b: Color32, t: f32) -> Color32 {
+ Color32::from_rgba_premultiplied(
+ (a.r() as f32 + (b.r() as f32 - a.r() as f32) * t) as u8,
+ (a.g() as f32 + (b.g() as f32 - a.g() as f32) * t) as u8,
+ (a.b() as f32 + (b.b() as f32 - a.b() as f32) * t) as u8,
+ (a.a() as f32 + (b.a() as f32 - a.a() as f32) * t) as u8,
+ )
}
-/// İkincil "iptal/geri" butonu (şeffaf dolgu).
-pub fn secondary_button(text: &str) -> egui::Button<'_> {
- egui::Button::new(egui::RichText::new(text).color(c_text_dim()))
- .fill(Color32::TRANSPARENT)
- .stroke(Stroke::new(1.0, c_border()))
- .rounding(Rounding::same(6.0))
- .min_size(Vec2::new(80.0, 32.0))
+fn gradient_button(ui: &mut egui::Ui, text: &str, top_color: Color32, bottom_color: Color32, text_color: Color32) -> egui::Response {
+ let rounding = Rounding::same(6.0);
+ let min_size = Vec2::new(100.0, 32.0);
+ let padding = Vec2::new(12.0, 6.0);
+
+ let font_id = ui.style().text_styles.get(&egui::TextStyle::Button)
+ .cloned().unwrap_or(FontId::proportional(14.0));
+ let galley = ui.painter().layout_no_wrap(
+ text.to_string(),
+ font_id,
+ text_color,
+ );
+
+ let size = Vec2::new(
+ min_size.x.max(galley.size().x + 2.0 * padding.x),
+ min_size.y.max(galley.size().y + 2.0 * padding.y),
+ );
+
+ let (rect, response) = ui.allocate_exact_size(size, egui::Sense::click());
+
+ // Gradient arka plan (16 yatay şerit)
+ let n_strips = 16;
+ for i in 0..n_strips {
+ let t = i as f32 / n_strips as f32;
+ let t2 = (i + 1) as f32 / n_strips as f32;
+ let c = lerp_color(top_color, bottom_color, (t + t2) * 0.5);
+ let y0 = rect.top() + rect.height() * t;
+ let y1 = rect.top() + rect.height() * t2;
+ let strip_rect = egui::Rect::from_min_max(
+ egui::pos2(rect.left(), y0),
+ egui::pos2(rect.right(), y1),
+ );
+ ui.painter().rect(strip_rect, Rounding::ZERO, c, Stroke::NONE);
+ }
+
+ // Yuvarlak köşe efekti için border
+ ui.painter().rect(rect, rounding, Color32::TRANSPARENT, Stroke::new(1.0, bottom_color));
+
+ // Hover efekti
+ if response.hovered() {
+ ui.painter().rect(rect, rounding, Color32::WHITE.linear_multiply(0.10), Stroke::NONE);
+ }
+
+ // Metin
+ ui.painter().galley(
+ egui::pos2(rect.center().x - galley.size().x / 2.0, rect.center().y - galley.size().y / 2.0),
+ galley,
+ text_color,
+ );
+
+ response
}
-/// Kırmızı "tehlikeli eylem" butonu (disk silme onayı vb.).
-pub fn danger_button(text: &str) -> egui::Button<'_> {
- egui::Button::new(egui::RichText::new(text).color(Color32::WHITE))
- .fill(Color32::from_rgb(0xC6, 0x28, 0x28))
- .stroke(Stroke::new(1.0, c_error()))
- .rounding(Rounding::same(6.0))
- .min_size(Vec2::new(100.0, 32.0))
+/// Ana eylem butonu (mavi gradient).
+pub fn primary_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
+ gradient_button(ui, text,
+ Color32::from_rgb(50, 130, 255), // üst: açık mavi
+ Color32::from_rgb(13, 110, 253), // alt: koyu mavi
+ Color32::WHITE)
+}
+
+/// İkincil buton (gri gradient).
+pub fn secondary_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
+ gradient_button(ui, text,
+ Color32::from_rgb(130, 140, 150), // üst: açık gri
+ Color32::from_rgb(100, 110, 120), // alt: koyu gri
+ c_text_dim())
+}
+
+/// İptal/Danger butonu (kırmızı gradient).
+pub fn danger_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
+ gradient_button(ui, text,
+ Color32::from_rgb(240, 83, 99), // üst: açık kırmızı
+ Color32::from_rgb(200, 40, 60), // alt: koyu kırmızı
+ Color32::WHITE)
}
/// Bölüm başlığı — büyük, açık renkli, alt çizgisiz.
@@ -246,7 +401,7 @@ pub fn error_box(ui: &mut egui::Ui, msg: &str) {
.inner_margin(egui::Margin::same(10.0))
.show(ui, |ui| {
ui.horizontal(|ui| {
- ui.colored_label(c_error(), "✗");
+ ui.colored_label(c_error(), "❌");
ui.colored_label(c_error(), msg);
});
});
@@ -261,7 +416,7 @@ pub fn warning_box(ui: &mut egui::Ui, msg: &str) {
.inner_margin(egui::Margin::same(10.0))
.show(ui, |ui| {
ui.horizontal(|ui| {
- ui.colored_label(c_warning(), "⚠");
+ ui.colored_label(c_warning(), "⚠️");
ui.colored_label(c_warning(), msg);
});
});
@@ -276,7 +431,7 @@ pub fn success_box(ui: &mut egui::Ui, msg: &str) {
.inner_margin(egui::Margin::same(10.0))
.show(ui, |ui| {
ui.horizontal(|ui| {
- ui.colored_label(c_success(), "✓");
+ ui.colored_label(c_success(), "✅");
ui.colored_label(c_success(), msg);
});
});