Jdjdk / main.py
Hw83jd's picture
Update main.py
0f29698 verified
Raw
History Blame Contribute Delete
14.3 kB
import flet as ft
from datetime import datetime
# قاعدة بيانات المستخدمين (تتحدث عند التسجيل)
db = {"admin": "123"}
COLORS = {
"bg_dark": "#0d1117",
"bg_panel": "#161b22",
"bg_card": "#21262d",
"accent": "#238636",
"my_bubble": "#1f4e6e",
"other_bubble": "#272e3b",
"border": "#30363d",
"text_primary": "#e6edf3",
"text_muted": "#8b949e",
"text_name": "#58a6ff",
"danger": "#f85149",
"call_btn": "#388bfd",
"warning": "#d29922",
}
def main(page: ft.Page):
page.title = "Dardasha 3TX"
page.theme_mode = ft.ThemeMode.DARK
page.rtl = True
page.padding = 0
page.bgcolor = COLORS["bg_dark"]
state = {"user": ""}
# ── avatar دائري بحرف ────────────────────────────────────
def avatar(name: str, size: int = 36) -> ft.Container:
palette = ["#1f6feb","#388bfd","#238636","#d29922",
"#8957e5","#db61a2","#f0883e"]
bg = palette[sum(ord(c) for c in name) % len(palette)]
return ft.Container(
content=ft.Text(name[0].upper(), size=int(size * 0.45),
weight="bold", color="white"),
width=size, height=size, border_radius=size,
bgcolor=bg, alignment=ft.alignment.center,
)
def now() -> str:
return datetime.now().strftime("%H:%M")
# ── pubsub ───────────────────────────────────────────────
def on_broadcast(data):
t = data.get("t")
if t == "c":
is_me = data["u"] == state["user"]
bubble = ft.Container(
content=ft.Column([
ft.Text(data["u"], size=11, weight="bold",
color="#a5d6ff" if is_me else COLORS["text_name"]),
ft.Text(data["m"], size=15, color=COLORS["text_primary"],
selectable=True),
ft.Text(data.get("ts", ""), size=10,
color=COLORS["text_muted"],
text_align=ft.TextAlign.RIGHT),
], spacing=3, tight=True),
bgcolor=COLORS["my_bubble"] if is_me else COLORS["other_bubble"],
padding=ft.padding.symmetric(horizontal=14, vertical=10),
border_radius=ft.border_radius.only(
top_left=14, top_right=14,
bottom_left=0 if is_me else 4,
bottom_right=4 if is_me else 0,
),
border=ft.border.all(1, COLORS["border"]),
max_width=280,
)
chat_list.controls.append(
ft.Row(
controls=[ft.Container(width=4), bubble]
if is_me else [avatar(data["u"]), bubble],
alignment=ft.MainAxisAlignment.END if is_me
else ft.MainAxisAlignment.START,
vertical_alignment=ft.CrossAxisAlignment.END,
)
)
elif t == "join":
_sys(f"✦ {data['u']} انضمّ للمحادثة")
elif t == "leave":
_sys(f"✦ {data['u']} غادر المحادثة")
elif t == "call" and data["u"] != state["user"]:
page.snack_bar = ft.SnackBar(
content=ft.Text(f"📞 مكالمة واردة من: {data['u']}",
color="white"),
bgcolor="#1a3a52", open=True,
)
page.update()
def _sys(text: str):
chat_list.controls.append(
ft.Row([
ft.Container(
content=ft.Text(text, size=11,
color=COLORS["text_muted"], italic=True),
padding=ft.padding.symmetric(horizontal=12, vertical=4),
bgcolor=COLORS["bg_card"], border_radius=20,
)
], alignment=ft.MainAxisAlignment.CENTER)
)
page.update()
page.pubsub.subscribe(on_broadcast)
# ── شاشة الشات ───────────────────────────────────────────
chat_list = ft.ListView(
expand=True, spacing=8, auto_scroll=True,
padding=ft.padding.symmetric(horizontal=10, vertical=12),
)
msg_in = ft.TextField(
hint_text="اكتب رسالتك...", expand=True,
border_radius=24, filled=True,
fill_color=COLORS["bg_card"],
border_color=COLORS["border"],
focused_border_color=COLORS["accent"],
hint_style=ft.TextStyle(color=COLORS["text_muted"]),
text_style=ft.TextStyle(color=COLORS["text_primary"], size=15),
content_padding=ft.padding.symmetric(horizontal=18, vertical=12),
on_submit=lambda _: send(None),
shift_enter=True,
)
def send(e):
txt = msg_in.value.strip()
if not txt:
return
payload = {"t": "c", "u": state["user"], "m": txt, "ts": now()}
page.pubsub.send_all(payload) # ← send_all بدل send_all_on_thread
msg_in.value = ""
msg_in.focus()
page.update()
def logout():
page.pubsub.send_all({"t": "leave", "u": state["user"]})
state["user"] = ""
chat_list.controls.clear()
page.controls.clear()
page.add(login_view)
page.update()
header = ft.Container(
content=ft.Row([
ft.Text("💬 3TX Chat", size=18, weight="bold",
color=COLORS["text_primary"]),
ft.Row([
ft.ElevatedButton(
"📞 اتصال",
on_click=lambda _: page.pubsub.send_all(
{"t": "call", "u": state["user"]}),
bgcolor=COLORS["call_btn"], color="white",
style=ft.ButtonStyle(
shape=ft.RoundedRectangleBorder(radius=20)),
),
ft.ElevatedButton(
"🚪 خروج", on_click=lambda _: logout(),
bgcolor=COLORS["danger"], color="white",
style=ft.ButtonStyle(
shape=ft.RoundedRectangleBorder(radius=20)),
),
], spacing=8),
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
padding=ft.padding.symmetric(horizontal=16, vertical=10),
bgcolor=COLORS["bg_panel"],
border=ft.border.only(
bottom=ft.border.BorderSide(1, COLORS["border"])),
)
input_row = ft.Container(
content=ft.Row([
msg_in,
ft.ElevatedButton(
"➤", on_click=send,
bgcolor=COLORS["accent"], color="white",
style=ft.ButtonStyle(shape=ft.CircleBorder()),
width=48, height=48,
),
], spacing=10, vertical_alignment=ft.CrossAxisAlignment.CENTER),
padding=ft.padding.symmetric(horizontal=12, vertical=10),
bgcolor=COLORS["bg_panel"],
border=ft.border.only(top=ft.border.BorderSide(1, COLORS["border"])),
)
chat_view = ft.Column([
header,
ft.Container(chat_list, expand=True, bgcolor=COLORS["bg_dark"]),
input_row,
], expand=True, spacing=0)
# ── شاشة تسجيل الدخول ────────────────────────────────────
u_in = ft.TextField(
label="اسم المستخدم", border_radius=12, filled=True,
fill_color=COLORS["bg_card"], border_color=COLORS["border"],
focused_border_color=COLORS["accent"],
label_style=ft.TextStyle(color=COLORS["text_muted"]),
text_style=ft.TextStyle(color=COLORS["text_primary"]),
width=320,
)
p_in = ft.TextField(
label="كلمة المرور", password=True, can_reveal_password=True,
border_radius=12, filled=True,
fill_color=COLORS["bg_card"], border_color=COLORS["border"],
focused_border_color=COLORS["accent"],
label_style=ft.TextStyle(color=COLORS["text_muted"]),
text_style=ft.TextStyle(color=COLORS["text_primary"]),
width=320, on_submit=lambda _: login(None),
)
login_err = ft.Text("", color=COLORS["danger"], size=13)
def login(e):
u = u_in.value.strip()
p = p_in.value
if not u or not p:
login_err.value = "⚠ أدخل اليوزر وكلمة المرور"
page.update()
return
if u in db and db[u] == p:
state["user"] = u
page.pubsub.send_all({"t": "join", "u": u})
page.controls.clear()
page.add(chat_view)
else:
login_err.value = "⚠ اسم المستخدم أو كلمة المرور غلط"
page.update()
def go_register(e):
page.controls.clear()
page.add(register_view)
page.update()
login_view = ft.Container(
content=ft.Column([
ft.Text("💬", size=60),
ft.Text("Dardasha 3TX", size=28, weight="bold",
color=COLORS["text_primary"]),
ft.Text("سجّل دخولك للمتابعة", size=14,
color=COLORS["text_muted"]),
ft.Container(height=8),
u_in, p_in, login_err,
ft.Container(height=4),
ft.ElevatedButton(
"دخول", on_click=login, width=320, height=48,
bgcolor=COLORS["accent"], color="white",
style=ft.ButtonStyle(
shape=ft.RoundedRectangleBorder(radius=12)),
),
ft.TextButton(
"ما عندك حساب؟ سجّل الآن",
on_click=go_register,
style=ft.ButtonStyle(color=COLORS["text_name"]),
),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=10),
expand=True, alignment=ft.alignment.center,
bgcolor=COLORS["bg_dark"],
padding=ft.padding.symmetric(horizontal=30, vertical=40),
)
# ── شاشة إنشاء حساب ──────────────────────────────────────
ru_in = ft.TextField(
label="اسم المستخدم الجديد", border_radius=12, filled=True,
fill_color=COLORS["bg_card"], border_color=COLORS["border"],
focused_border_color=COLORS["accent"],
label_style=ft.TextStyle(color=COLORS["text_muted"]),
text_style=ft.TextStyle(color=COLORS["text_primary"]),
width=320,
)
rp_in = ft.TextField(
label="كلمة المرور", password=True, can_reveal_password=True,
border_radius=12, filled=True,
fill_color=COLORS["bg_card"], border_color=COLORS["border"],
focused_border_color=COLORS["accent"],
label_style=ft.TextStyle(color=COLORS["text_muted"]),
text_style=ft.TextStyle(color=COLORS["text_primary"]),
width=320,
)
rp2_in = ft.TextField(
label="تأكيد كلمة المرور", password=True, can_reveal_password=True,
border_radius=12, filled=True,
fill_color=COLORS["bg_card"], border_color=COLORS["border"],
focused_border_color=COLORS["accent"],
label_style=ft.TextStyle(color=COLORS["text_muted"]),
text_style=ft.TextStyle(color=COLORS["text_primary"]),
width=320,
)
reg_msg = ft.Text("", size=13)
def register(e):
u = ru_in.value.strip()
p = rp_in.value
p2 = rp2_in.value
if not u or not p or not p2:
reg_msg.color = COLORS["danger"]
reg_msg.value = "⚠ أكمل جميع الحقول"
elif len(u) < 3:
reg_msg.color = COLORS["danger"]
reg_msg.value = "⚠ اليوزر لازم 3 أحرف على الأقل"
elif len(p) < 3:
reg_msg.color = COLORS["danger"]
reg_msg.value = "⚠ كلمة المرور لازم 3 أحرف على الأقل"
elif p != p2:
reg_msg.color = COLORS["danger"]
reg_msg.value = "⚠ كلمتا المرور ما تطابقتا"
elif u in db:
reg_msg.color = COLORS["danger"]
reg_msg.value = "⚠ اليوزر مأخوذ، اختر اسماً آخر"
else:
db[u] = p
reg_msg.color = COLORS["accent"]
reg_msg.value = "✅ تم إنشاء الحساب! ادخل الآن"
ru_in.value = rp_in.value = rp2_in.value = ""
page.update()
def go_login(e):
reg_msg.value = ""
page.controls.clear()
page.add(login_view)
page.update()
register_view = ft.Container(
content=ft.Column([
ft.Text("✨", size=50),
ft.Text("إنشاء حساب جديد", size=26, weight="bold",
color=COLORS["text_primary"]),
ft.Text("انضم لـ 3TX الآن", size=13, color=COLORS["text_muted"]),
ft.Container(height=8),
ru_in, rp_in, rp2_in, reg_msg,
ft.Container(height=4),
ft.ElevatedButton(
"إنشاء الحساب", on_click=register, width=320, height=48,
bgcolor=COLORS["accent"], color="white",
style=ft.ButtonStyle(
shape=ft.RoundedRectangleBorder(radius=12)),
),
ft.TextButton(
"عندك حساب؟ سجّل دخول",
on_click=go_login,
style=ft.ButtonStyle(color=COLORS["text_name"]),
),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=10),
expand=True, alignment=ft.alignment.center,
bgcolor=COLORS["bg_dark"],
padding=ft.padding.symmetric(horizontal=30, vertical=40),
)
page.add(login_view)
if __name__ == "__main__":
ft.app(target=main, view=ft.AppView.WEB_BROWSER, port=7860, host="0.0.0.0")