Poorpoor6976 commited on
Commit
aebaf7e
·
verified ·
1 Parent(s): a81d2e8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -236
app.py CHANGED
@@ -10,30 +10,22 @@ def analyze_error_ai(log_text):
10
  if "project_info" in log_text or "google-services" in log_text:
11
  return "🤖 تحليل AI: هناك مشكلة في بيانات Firebase. تأكد من لصق محتوى google-services.json بشكل صحيح."
12
  if "Unresolved reference" in log_text or "Could not resolve" in log_text:
13
- return "🤖 تحليل AI: فشل في تحميل مكتبات خارجية (مشكلة في اتصال سيرفر البناء بالإنترنت أو تعارض في إصدارات AdMob/Firebase)."
14
  if "compileReleaseJavaWithJavac" in log_text or "error: " in log_text:
15
- return "🤖 تحليل AI: خطأ في كود الجافا (Java Syntax Error). تأكد من أن الروابط واسم الحزمة لا تحتوي على مسافات أو رموز غير مسموحة."
16
- if "Manifest merger failed" in log_text:
17
- return "🤖 تحليل AI: تعارض في ملف AndroidManifest. الأذونات أو الإعدادات تتضارب مع مكتبة أخرى (مثل OneSignal)."
18
- return "🤖 تحليل AI: خطأ غير معروف. ابحث في السجلات أعلاه عن الكلمات المكتوبة باللون الأحمر أو التي تبدأ بكلمة FAILED."
19
 
20
  # ================== المحرك الرئيسي للبناء ==================
21
  def build_ultimate_app(
22
- # 1. الأساسيات
23
  app_name, url, package_name, build_format, version_name, version_code, orientation,
24
  dev_name, dev_email,
25
- # 2. التصميم والواجهة
26
  icon_path, enable_splash, splash_text, splash_color, status_bar_color, enable_bottom_nav, fullscreen, keep_screen_on,
27
- # 3. محرك الويب المتقدم
28
  js_enabled, enable_zoom, dom_storage, allow_file_access, clear_cache_exit, custom_user_agent, media_auto_play,
29
- # 4. الحماية والأمان
30
  enable_security, block_root, prevent_screenshots, clear_cookies_exit,
31
- # 5. الإعلانات والخدمات (Firebase)
32
  enable_ads, admob_banner_id, admob_interstitial_id, onesignal_id, firebase_file, firebase_text,
33
- # 6. الأذونات
34
  perm_internet, perm_camera, perm_audio, perm_location, perm_storage, perm_bg, perm_vibrate, perm_contacts
35
  ):
36
- logs = f"[{datetime.datetime.now().strftime('%H:%M:%S')}] 🚀 بدء النظام... تهيئة بيئة البناء المتقدمة.\n"
37
  yield logs, None
38
 
39
  project_dir = "/tmp/SuperApp"
@@ -48,37 +40,27 @@ def build_ultimate_app(
48
  os.makedirs(f"{res_dir}/{folder}", exist_ok=True)
49
  os.makedirs(java_dir, exist_ok=True)
50
 
51
- # --- معالجة الأيقونة ---
52
  if icon_path: shutil.copy(icon_path, f"{res_dir}/mipmap-xxxhdpi/ic_launcher.png")
53
  else: os.system(f"touch {res_dir}/mipmap-xxxhdpi/ic_launcher.png")
54
 
55
- # --- معالجة Firebase (النص أو الملف) ---
56
  use_firebase = False
57
  fb_content = ""
58
- if firebase_text and firebase_text.strip() != "":
59
- fb_content = firebase_text.strip()
60
  elif firebase_file:
61
  try:
62
  with open(firebase_file, 'r', encoding='utf-8') as f: fb_content = f.read()
63
  except: pass
64
 
65
- if fb_content:
66
- if "project_info" in fb_content:
67
- with open(f"{project_dir}/app/google-services.json", "w", encoding='utf-8') as f:
68
- f.write(fb_content)
69
- use_firebase = True
70
- logs += "✅ تم دمج Firebase بنجاح (من النص/الملف).\n"
71
- else:
72
- logs += "⚠️ تحذير: بيانات Firebase غير صالحة، تم تجاهلها لمنع فشل البناء.\n"
73
  yield logs, None
74
 
75
- # --- التوقيع الرقمي ---
76
  dev_n = dev_name if dev_name else "Dev"
77
  os.system(f'keytool -genkey -v -keystore {project_dir}/app/release.keystore -alias appKey -keyalg RSA -keysize 2048 -validity 10000 -storepass 12345678 -keypass 12345678 -dname "CN={dev_n}, EMAILADDRESS={dev_email}, O=App, C=US" 2>/dev/null')
78
 
79
- # --- ملفات Gradle ---
80
  with open(f"{project_dir}/settings.gradle", "w") as f: f.write(f"rootProject.name = '{app_name}'\ninclude ':app'\n")
81
-
82
  with open(f"{project_dir}/build.gradle", "w") as f:
83
  f.write(f"""
84
  buildscript {{
@@ -94,11 +76,7 @@ def build_ultimate_app(
94
 
95
  with open(f"{project_dir}/app/build.gradle", "w") as f:
96
  f.write(f"""
97
- plugins {{
98
- id 'com.android.application'
99
- {'id "com.onesignal.androidsdk.onesignal-gradle-plugin"' if onesignal_id else ''}
100
- {'id "com.google.gms.google-services"' if use_firebase else ''}
101
- }}
102
  android {{
103
  namespace '{package_name}'
104
  compileSdk 34
@@ -110,17 +88,8 @@ def build_ultimate_app(
110
  versionName "{version_name}"
111
  {f'manifestPlaceholders = [onesignal_app_id: "{onesignal_id}", onesignal_google_project_number: "REMOTE"]' if onesignal_id else ''}
112
  }}
113
- signingConfigs {{
114
- release {{ storeFile file("release.keystore"); storePassword "12345678"; keyAlias "appKey"; keyPassword "12345678" }}
115
- }}
116
- buildTypes {{
117
- release {{
118
- minifyEnabled {str(enable_security).lower()}
119
- shrinkResources {str(enable_security).lower()}
120
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
121
- signingConfig signingConfigs.release
122
- }}
123
- }}
124
  }}
125
  dependencies {{
126
  implementation 'androidx.appcompat:appcompat:1.6.1'
@@ -132,173 +101,66 @@ def build_ultimate_app(
132
  }}
133
  """)
134
 
135
- # --- ملفات التصميم (XML) ---
136
  with open(f"{res_dir}/values/styles.xml", "w") as f:
137
- f.write(f"""<resources>
138
- <style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
139
- <item name="android:statusBarColor">{status_bar_color}</item>
140
- </style>
141
- </resources>""")
142
 
143
  with open(f"{res_dir}/layout/activity_main.xml", "w") as f:
144
- f.write(f"""<?xml version="1.0" encoding="utf-8"?>
145
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
146
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipeContainer" android:layout_width="match_parent" android:layout_height="match_parent">
147
- <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
148
- </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
149
- </RelativeLayout>""")
150
 
151
- # --- شاشة البداية الاختيارية (Splash) ---
152
  if enable_splash:
153
  with open(f"{res_dir}/layout/activity_splash.xml", "w") as f:
154
- f.write(f"""<?xml version="1.0" encoding="utf-8"?>
155
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="{splash_color}" android:gravity="center">
156
- <ImageView android:id="@+id/logo" android:layout_width="150dp" android:layout_height="150dp" android:src="@mipmap/ic_launcher" />
157
- <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="{splash_text}" android:textColor="#FFFFFF" android:textSize="20sp" android:layout_below="@id/logo" android:layout_marginTop="20dp" android:layout_centerHorizontal="true"/>
158
- </RelativeLayout>""")
159
-
160
- splash_java = f"""package {package_name};
161
- import android.app.Activity;
162
- import android.content.Intent;
163
- import android.os.Bundle;
164
- import android.os.Handler;
165
- public class SplashActivity extends Activity {{
166
- @Override protected void onCreate(Bundle savedInstanceState) {{
167
- super.onCreate(savedInstanceState);
168
- setContentView(R.layout.activity_splash);
169
- new Handler().postDelayed(() -> {{ startActivity(new Intent(SplashActivity.this, MainActivity.class)); finish(); }}, 2500);
170
- }}
171
- }}"""
172
- with open(f"{java_dir}/SplashActivity.java", "w") as f: f.write(splash_java)
173
-
174
- # --- كود الجافا الرئيسي (MainActivity) مع كل الميزات المتقدمة ---
175
- root_detection = """
176
- private boolean isRooted() {
177
- String[] paths = {"/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su"};
178
- for (String path : paths) { if (new java.io.File(path).exists()) return true; }
179
- return false;
180
- }
181
- """ if block_root else ""
182
 
183
  u_agent = f'ws.setUserAgentString("{custom_user_agent}");' if custom_user_agent else ""
184
-
185
  main_java = f"""package {package_name};
186
- import android.app.Activity;
187
- import android.content.Intent;
188
- import android.net.Uri;
189
- import android.os.Bundle;
190
- import android.view.WindowManager;
191
- import android.webkit.CookieManager;
192
- import android.webkit.WebSettings;
193
- import android.webkit.WebView;
194
- import android.webkit.WebViewClient;
195
- import android.webkit.WebChromeClient;
196
- import android.webkit.WebResourceRequest;
197
- import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
198
  {'import com.onesignal.OneSignal;' if onesignal_id else ''}
199
-
200
  public class MainActivity extends Activity {{
201
- private WebView myWebView;
202
- private SwipeRefreshLayout swipeLayout;
203
- {root_detection}
204
-
205
  @Override protected void onCreate(Bundle savedInstanceState) {{
206
  super.onCreate(savedInstanceState);
207
-
208
- {'if (isRooted()) { finish(); return; }' if block_root else ''}
209
  {'getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);' if prevent_screenshots else ''}
210
  {'getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);' if keep_screen_on else ''}
211
-
212
  {'if(android.os.Build.VERSION.SDK_INT >= 28) getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;' if fullscreen else ''}
213
- {'getWindow().getDecorView().setSystemUiVisibility(android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | android.view.View.SYSTEM_UI_FLAG_FULLSCREEN);' if fullscreen else ''}
214
-
215
- if (android.os.Build.VERSION.SDK_INT >= 33 && checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) != android.content.pm.PackageManager.PERMISSION_GRANTED) {{
216
- requestPermissions(new String[]{{android.Manifest.permission.POST_NOTIFICATIONS}}, 101);
217
- }}
218
-
219
- {f'OneSignal.setLogLevel(OneSignal.LOG_LEVEL.VERBOSE, OneSignal.LOG_LEVEL.NONE); OneSignal.initWithContext(this); OneSignal.setAppId("{onesignal_id}");' if onesignal_id else ''}
220
-
221
- setContentView(R.layout.activity_main);
222
- myWebView = findViewById(R.id.webview);
223
- swipeLayout = findViewById(R.id.swipeContainer);
224
- swipeLayout.setOnRefreshListener(() -> myWebView.reload());
225
-
226
- WebSettings ws = myWebView.getSettings();
227
- ws.setJavaScriptEnabled({str(js_enabled).lower()});
228
- ws.setDomStorageEnabled({str(dom_storage).lower()});
229
- ws.setAllowFileAccess({str(allow_file_access).lower()});
230
- ws.setMediaPlaybackRequiresUserGesture({str(not media_auto_play).lower()});
231
- ws.setSupportZoom({str(enable_zoom).lower()});
232
- ws.setBuiltInZoomControls({str(enable_zoom).lower()});
233
- ws.setDisplayZoomControls(false);
234
- ws.setSupportMultipleWindows(true);
235
- ws.setJavaScriptCanOpenWindowsAutomatically(true);
236
- ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
237
- {u_agent}
238
-
239
  myWebView.setWebViewClient(new WebViewClient() {{
240
  @Override public void onPageFinished(WebView view, String url) {{ swipeLayout.setRefreshing(false); }}
241
  @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {{
242
  String reqUrl = request.getUrl().toString();
243
- if (reqUrl.startsWith("http://") || reqUrl.startsWith("https://")) {{
244
- if(reqUrl.contains("accounts.google.com") || reqUrl.contains("facebook.com")) {{
245
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(reqUrl)));
246
- return true;
247
- }}
248
- return false;
249
- }}
250
- try {{ startActivity(Intent.parseUri(reqUrl, Intent.URI_INTENT_SCHEME)); return true; }}
251
- catch (Exception e) {{ return false; }}
252
  }}
253
  }});
254
- myWebView.setWebChromeClient(new WebChromeClient());
255
- myWebView.loadUrl("{url}");
256
  }}
257
-
258
- @Override protected void onDestroy() {{
259
- {'myWebView.clearCache(true);' if clear_cache_exit else ''}
260
- {'CookieManager.getInstance().removeAllCookies(null); CookieManager.getInstance().flush();' if clear_cookies_exit else ''}
261
- super.onDestroy();
262
- }}
263
-
264
  @Override public void onBackPressed() {{ if (myWebView.canGoBack()) myWebView.goBack(); else super.onBackPressed(); }}
265
  }}"""
266
  with open(f"{java_dir}/MainActivity.java", "w") as f: f.write(main_java)
267
 
268
- # --- AndroidManifest.xml المتقدم ---
269
- perms = []
270
- if perm_internet: perms.extend(["INTERNET", "ACCESS_NETWORK_STATE"])
271
  if perm_camera: perms.append("CAMERA")
272
- if perm_audio: perms.extend(["RECORD_AUDIO", "MODIFY_AUDIO_SETTINGS"])
273
  if perm_location: perms.extend(["ACCESS_FINE_LOCATION", "ACCESS_COARSE_LOCATION"])
274
  if perm_storage: perms.extend(["READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE"])
275
  if perm_bg: perms.append("REQUEST_IGNORE_BATTERY_OPTIMIZATIONS")
276
  if perm_vibrate: perms.append("VIBRATE")
277
  if perm_contacts: perms.append("READ_CONTACTS")
278
  if onesignal_id or use_firebase: perms.append("POST_NOTIFICATIONS")
279
-
280
  perms_xml = "\n".join([f'<uses-permission android:name="android.permission.{p}" />' for p in perms])
281
- admob_meta = f'<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="{admob_banner_id}"/>' if enable_ads and admob_banner_id else ""
282
 
283
- launcher_act = "SplashActivity" if enable_splash else "MainActivity"
284
-
285
- manifest_xml = f"""<?xml version="1.0" encoding="utf-8"?>
286
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="{package_name}">
287
- {perms_xml}
288
- <application android:label="{app_name}" android:icon="@mipmap/ic_launcher" android:theme="@style/AppTheme" android:usesCleartextTraffic="true" android:hardwareAccelerated="true">
289
- {admob_meta}
290
- {f'<activity android:name=".SplashActivity" android:exported="true" android:screenOrientation="portrait"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>' if enable_splash else ''}
291
- <activity android:name=".MainActivity" android:exported="true" android:screenOrientation="{orientation}" android:configChanges="orientation|keyboardHidden|screenSize">
292
- {'' if enable_splash else '<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>'}
293
- </activity>
294
- </application>
295
- </manifest>"""
296
  with open(f"{project_dir}/app/src/main/AndroidManifest.xml", "w") as f: f.write(manifest_xml)
297
 
298
- logs += "⚙️ بدء عملية التجميع... جاري بث السجلات الحية:\n" + "="*40 + "\n"
299
  yield logs, None
300
 
301
- # --- تنفيذ البناء وقراءة السجلات ---
302
  gradle_cmd = "gradle bundleRelease" if build_format == "aab" else "gradle assembleRelease"
303
  process = subprocess.Popen(gradle_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=project_dir, bufsize=1, universal_newlines=True)
304
 
@@ -307,89 +169,80 @@ def build_ultimate_app(
307
  for line in iter(process.stdout.readline, ''):
308
  log_buffer.append(line)
309
  full_error_log += line
310
- if len(log_buffer) > 30: log_buffer.pop(0) # عرض آخر 30 سطر للمتصفح لتخفيف العبء
311
  yield logs + "".join(log_buffer), None
312
-
313
  process.wait()
314
 
315
- final_display = logs + "".join(log_buffer)
316
  if process.returncode == 0:
317
- out_path = f"{project_dir}/app/build/outputs/bundle/release/app-release.aab" if build_format == "aab" else f"{project_dir}/app/build/outputs/apk/release/app-release.apk"
318
- final_display += "\n\n✅ [نجاح] تم بناء التطبيق بنجاح تام! يمكنك تحميله الآن."
319
- yield final_display, out_path
320
  else:
321
- ai_diagnosis = analyze_error_ai(full_error_log)
322
- final_display += f"\n\n❌ [فشل البناء] اكتشف النظام خطأ.\n{ai_diagnosis}"
323
- yield final_display, None
324
-
325
-
326
- # ================== واجهة المستخدم المتوافقة مع الموبايل (Accordions) ==================
327
- with gr.Blocks(theme=gr.themes.Base()) as demo:
328
- gr.Markdown("<h1 style='text-align: center;'>📱 مصنع التطبيقات الشامل - الإصدار الذهبي</h1>")
329
- gr.Markdown("<p style='text-align: center;'>تصميم متوافق 100% مع شاشات الهواتف. افتح القوائم أدناه لضبط أكثر من 40 ميزة!</p>")
330
 
 
 
 
 
331
  with gr.Accordion("1️⃣ الأساسيات | Core Basics", open=True):
332
- app_name = gr.Textbox(label="اسم التطبيق | App Name", value="تطبيقي برو")
333
  url = gr.Textbox(label="الرابط | Website URL", value="https://google.com")
334
- package_name = gr.Textbox(label="اسم الحزمة | Package Name (com.company.app)", value="com.vip.app")
335
  build_format = gr.Dropdown(choices=["apk", "aab"], value="apk", label="صيغة الإخراج | Output Format")
336
  with gr.Row():
337
  version_name = gr.Textbox(label="الإصدار | Version", value="1.0.0")
338
  version_code = gr.Number(label="كود الإصدار | Version Code", value=1)
339
- orientation = gr.Dropdown(choices=["unspecified", "portrait", "landscape"], value="unspecified", label="اتجاه الشاشة | Orientation")
340
- dev_name = gr.Textbox(label="اسم المطور (للتوقيع) | Developer Name")
341
- dev_email = gr.Textbox(label="البريد الإلكتروني | Email")
342
 
343
  with gr.Accordion("2️⃣ التصميم والواجهة | UI & Design", open=False):
344
- icon_path = gr.File(label="أيقونة التطبيق | App Icon (PNG)")
345
- status_bar_color = gr.ColorPicker(label="لون شريط الحالة العلوي | Status Bar Color", value="#000000")
346
- enable_splash = gr.Checkbox(label="تفعيل شاشة البداية (اختياري) | Enable Splash Screen", value=False)
347
- splash_text = gr.Textbox(label="نص شاشة البداية | Splash Text", value="جاري التحميل...")
348
- splash_color = gr.ColorPicker(label="لون خلفية البداية | Splash Background", value="#121212")
349
- enable_bottom_nav = gr.Checkbox(label="شريط تنقل سفلي | Bottom Navigation", value=False)
350
- fullscreen = gr.Checkbox(label="وضع ملء الشاشة (إخفاء الأشرطة) | Fullscreen Mode", value=False)
351
- keep_screen_on = gr.Checkbox(label="إبقاء الشاشة مضاءة دائماً | Keep Screen On", value=False)
352
-
353
- with gr.Accordion("3️⃣ محرك الويب المتقدم | Advanced Web Engine", open=False):
354
  js_enabled = gr.Checkbox(label="تفعيل JavaScript", value=True)
355
- enable_zoom = gr.Checkbox(label="السماح بتكبير/تصغير الشاشة | Enable Zoom", value=False)
356
- dom_storage = gr.Checkbox(label="تفعيل التخزين المحلي (DOM) لحفظ الجلسات", value=True)
357
- allow_file_access = gr.Checkbox(label="السماح للموقع بقراءة ملفات الهاتف الداخلي | Allow File Access", value=True)
358
- media_auto_play = gr.Checkbox(label="تشغيل الصوت/الفيديو تلقائياً بدون نقر | Auto-play Media", value=True)
359
- clear_cache_exit = gr.Checkbox(label="مسح الكاش عند إغلاق التطبيق | Clear Cache on Exit", value=False)
360
- custom_user_agent = gr.Textbox(label="User Agent مخصص (اتركه فارغاً للافتراضي)")
361
-
362
- with gr.Accordion("4️⃣ الحماية والأمان | Security & Protection", open=False):
363
- enable_security = gr.Checkbox(label="تشفير وتشويش الكود (ProGuard) | Obfuscate Code", value=True)
364
- block_root = gr.Checkbox(label="منع تشغيل التطبيق في هواتف Root | Block Root Devices", value=False)
365
- prevent_screenshots = gr.Checkbox(label="منع التقاط الشاشة (Screenshot) للتطبيق | Prevent Screenshots", value=False)
366
- clear_cookies_exit = gr.Checkbox(label="تسجيل الخروج ومسح ملفات الارتباط عند الإغلاق | Clear Cookies on Exit", value=False)
367
-
368
- with gr.Accordion("5️⃣ الإعلانات والخدمات | Ads & Services", open=False):
369
- gr.Markdown("💡 **حل Firebase:** يمكنك رفع الملف أو نسخ محتواه ولصقه في المربع أدناه.")
370
- firebase_file = gr.File(label="ملف Firebase | google-services.json")
371
- firebase_text = gr.Textbox(label="أو الصق محتوى Firebase هنا | Or Paste Firebase JSON code", lines=3)
372
- onesignal_id = gr.Textbox(label="معرف الإشعارات | OneSignal App ID")
373
- enable_ads = gr.Checkbox(label="تفعيل إعلانات جوجل AdMob", value=False)
374
- admob_banner_id = gr.Textbox(label="AdMob Banner ID")
375
- admob_interstitial_id = gr.Textbox(label="AdMob Interstitial ID")
376
-
377
- with gr.Accordion("6️⃣ الأذونات والصلاحيات | Permissions", open=False):
378
- perm_internet = gr.Checkbox(label="الإنترنت (أساسي) | Internet", value=True, interactive=False)
379
- perm_camera = gr.Checkbox(label="الكاميرا | Camera")
380
- perm_audio = gr.Checkbox(label="المايكروفون | Audio Record")
381
- perm_location = gr.Checkbox(label="الموقع الجغرافي | Location")
382
- perm_storage = gr.Checkbox(label="إدارة الملفات | Storage")
383
- perm_bg = gr.Checkbox(label="العمل في الخلفية بحرية | Background Execution")
384
- perm_vibrate = gr.Checkbox(label="الاهتزاز | Vibrate")
385
- perm_contacts = gr.Checkbox(label="جهات الاتصال | Read Contacts")
386
 
387
  build_btn = gr.Button("🚀 بدء بناء التطبيق | Start Build", variant="primary", size="lg")
388
 
389
  with gr.Group():
390
- # ميزة النسخ مفعلة تلقائياً في Gradio Textbox
391
- logs_out = gr.Textbox(label="🖥️ السجلات المباشرة والذكاء الاصطناعي | Live Logs & AI (مع زر نسخ مدمج)", lines=12, max_lines=15, show_copy_button=True)
392
- file_out = gr.File(label="📥 تحميل التطبيق | Download APK/AAB")
393
 
394
  inputs = [
395
  app_name, url, package_name, build_format, version_name, version_code, orientation,
@@ -397,12 +250,12 @@ with gr.Blocks(theme=gr.themes.Base()) as demo:
397
  icon_path, enable_splash, splash_text, splash_color, status_bar_color, enable_bottom_nav, fullscreen, keep_screen_on,
398
  js_enabled, enable_zoom, dom_storage, allow_file_access, clear_cache_exit, custom_user_agent, media_auto_play,
399
  enable_security, block_root, prevent_screenshots, clear_cookies_exit,
400
- enable_ads, admob_banner_id, admob_interstitial_id, onesignal_id, firebase_file, firebase_text,
401
  perm_internet, perm_camera, perm_audio, perm_location, perm_storage, perm_bg, perm_vibrate, perm_contacts
402
  ]
403
 
404
  build_btn.click(fn=build_ultimate_app, inputs=inputs, outputs=[logs_out, file_out])
405
 
406
- # تفعيل الطابور لحماية السيرفر
407
  demo.queue(max_size=20, default_concurrency_limit=3)
408
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
10
  if "project_info" in log_text or "google-services" in log_text:
11
  return "🤖 تحليل AI: هناك مشكلة في بيانات Firebase. تأكد من لصق محتوى google-services.json بشكل صحيح."
12
  if "Unresolved reference" in log_text or "Could not resolve" in log_text:
13
+ return "🤖 تحليل AI: فشل في تحميل مكتبات خارجية. تأكد من أن السيرفر متصل بالإنترنت."
14
  if "compileReleaseJavaWithJavac" in log_text or "error: " in log_text:
15
+ return "🤖 تحليل AI: خطأ في كود الجافا (Java Syntax Error). تأكد من الروابط واسم الحزمة."
16
+ return "🤖 تحليل AI: فشل البناء. راجع السجلات أعلاه للبحث عن كلمة FAILED."
 
 
17
 
18
  # ================== المحرك الرئيسي للبناء ==================
19
  def build_ultimate_app(
 
20
  app_name, url, package_name, build_format, version_name, version_code, orientation,
21
  dev_name, dev_email,
 
22
  icon_path, enable_splash, splash_text, splash_color, status_bar_color, enable_bottom_nav, fullscreen, keep_screen_on,
 
23
  js_enabled, enable_zoom, dom_storage, allow_file_access, clear_cache_exit, custom_user_agent, media_auto_play,
 
24
  enable_security, block_root, prevent_screenshots, clear_cookies_exit,
 
25
  enable_ads, admob_banner_id, admob_interstitial_id, onesignal_id, firebase_file, firebase_text,
 
26
  perm_internet, perm_camera, perm_audio, perm_location, perm_storage, perm_bg, perm_vibrate, perm_contacts
27
  ):
28
+ logs = f"[{datetime.datetime.now().strftime('%H:%M:%S')}] 🚀 بدء النظام... تهيئة بيئة البناء.\n"
29
  yield logs, None
30
 
31
  project_dir = "/tmp/SuperApp"
 
40
  os.makedirs(f"{res_dir}/{folder}", exist_ok=True)
41
  os.makedirs(java_dir, exist_ok=True)
42
 
 
43
  if icon_path: shutil.copy(icon_path, f"{res_dir}/mipmap-xxxhdpi/ic_launcher.png")
44
  else: os.system(f"touch {res_dir}/mipmap-xxxhdpi/ic_launcher.png")
45
 
 
46
  use_firebase = False
47
  fb_content = ""
48
+ if firebase_text and firebase_text.strip() != "": fb_content = firebase_text.strip()
 
49
  elif firebase_file:
50
  try:
51
  with open(firebase_file, 'r', encoding='utf-8') as f: fb_content = f.read()
52
  except: pass
53
 
54
+ if fb_content and "project_info" in fb_content:
55
+ with open(f"{project_dir}/app/google-services.json", "w", encoding='utf-8') as f: f.write(fb_content)
56
+ use_firebase = True
57
+ logs += "✅ تم دمج Firebase بنجاح.\n"
 
 
 
 
58
  yield logs, None
59
 
 
60
  dev_n = dev_name if dev_name else "Dev"
61
  os.system(f'keytool -genkey -v -keystore {project_dir}/app/release.keystore -alias appKey -keyalg RSA -keysize 2048 -validity 10000 -storepass 12345678 -keypass 12345678 -dname "CN={dev_n}, EMAILADDRESS={dev_email}, O=App, C=US" 2>/dev/null')
62
 
 
63
  with open(f"{project_dir}/settings.gradle", "w") as f: f.write(f"rootProject.name = '{app_name}'\ninclude ':app'\n")
 
64
  with open(f"{project_dir}/build.gradle", "w") as f:
65
  f.write(f"""
66
  buildscript {{
 
76
 
77
  with open(f"{project_dir}/app/build.gradle", "w") as f:
78
  f.write(f"""
79
+ plugins {{ id 'com.android.application'; {'id "com.onesignal.androidsdk.onesignal-gradle-plugin"' if onesignal_id else ''}; {'id "com.google.gms.google-services"' if use_firebase else ''} }}
 
 
 
 
80
  android {{
81
  namespace '{package_name}'
82
  compileSdk 34
 
88
  versionName "{version_name}"
89
  {f'manifestPlaceholders = [onesignal_app_id: "{onesignal_id}", onesignal_google_project_number: "REMOTE"]' if onesignal_id else ''}
90
  }}
91
+ signingConfigs {{ release {{ storeFile file("release.keystore"); storePassword "12345678"; keyAlias "appKey"; keyPassword "12345678" }} }}
92
+ buildTypes {{ release {{ minifyEnabled {str(enable_security).lower()}; shrinkResources {str(enable_security).lower()}; proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'); signingConfig signingConfigs.release }} }}
 
 
 
 
 
 
 
 
 
93
  }}
94
  dependencies {{
95
  implementation 'androidx.appcompat:appcompat:1.6.1'
 
101
  }}
102
  """)
103
 
 
104
  with open(f"{res_dir}/values/styles.xml", "w") as f:
105
+ f.write(f"""<resources><style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar"><item name="android:statusBarColor">{status_bar_color}</item></style></resources>""")
 
 
 
 
106
 
107
  with open(f"{res_dir}/layout/activity_main.xml", "w") as f:
108
+ f.write(f"""<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"><androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipeContainer" android:layout_width="match_parent" android:layout_height="match_parent"><WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" /></androidx.swiperefreshlayout.widget.SwipeRefreshLayout></RelativeLayout>""")
 
 
 
 
 
109
 
 
110
  if enable_splash:
111
  with open(f"{res_dir}/layout/activity_splash.xml", "w") as f:
112
+ f.write(f"""<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="{splash_color}" android:gravity="center"><ImageView android:id="@+id/logo" android:layout_width="150dp" android:layout_height="150dp" android:src="@mipmap/ic_launcher" /><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="{splash_text}" android:textColor="#FFFFFF" android:textSize="20sp" android:layout_below="@id/logo" android:layout_marginTop="20dp" android:layout_centerHorizontal="true"/></RelativeLayout>""")
113
+ with open(f"{java_dir}/SplashActivity.java", "w") as f:
114
+ f.write(f"package {package_name}; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; public class SplashActivity extends Activity {{ @Override protected void onCreate(Bundle savedInstanceState) {{ super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); new Handler().postDelayed(() -> {{ startActivity(new Intent(SplashActivity.this, MainActivity.class)); finish(); }}, 2500); }} }}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
  u_agent = f'ws.setUserAgentString("{custom_user_agent}");' if custom_user_agent else ""
 
117
  main_java = f"""package {package_name};
118
+ import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.WindowManager; import android.webkit.CookieManager; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 
 
 
 
 
 
 
 
 
 
 
119
  {'import com.onesignal.OneSignal;' if onesignal_id else ''}
 
120
  public class MainActivity extends Activity {{
121
+ private WebView myWebView; private SwipeRefreshLayout swipeLayout;
 
 
 
122
  @Override protected void onCreate(Bundle savedInstanceState) {{
123
  super.onCreate(savedInstanceState);
 
 
124
  {'getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);' if prevent_screenshots else ''}
125
  {'getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);' if keep_screen_on else ''}
 
126
  {'if(android.os.Build.VERSION.SDK_INT >= 28) getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;' if fullscreen else ''}
127
+ {'getWindow().getDecorView().setSystemUiVisibility(android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);' if fullscreen else ''}
128
+ if (android.os.Build.VERSION.SDK_INT >= 33 && checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) != android.content.pm.PackageManager.PERMISSION_GRANTED) requestPermissions(new String[]{{android.Manifest.permission.POST_NOTIFICATIONS}}, 101);
129
+ {f'OneSignal.initWithContext(this); OneSignal.setAppId("{onesignal_id}");' if onesignal_id else ''}
130
+ setContentView(R.layout.activity_main); myWebView = findViewById(R.id.webview); swipeLayout = findViewById(R.id.swipeContainer); swipeLayout.setOnRefreshListener(() -> myWebView.reload());
131
+ WebSettings ws = myWebView.getSettings(); ws.setJavaScriptEnabled({str(js_enabled).lower()}); ws.setDomStorageEnabled({str(dom_storage).lower()}); ws.setAllowFileAccess({str(allow_file_access).lower()}); ws.setMediaPlaybackRequiresUserGesture({str(not media_auto_play).lower()}); ws.setSupportZoom({str(enable_zoom).lower()}); ws.setBuiltInZoomControls({str(enable_zoom).lower()}); ws.setDisplayZoomControls(false); ws.setSupportMultipleWindows(true); ws.setJavaScriptCanOpenWindowsAutomatically(true); {u_agent}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  myWebView.setWebViewClient(new WebViewClient() {{
133
  @Override public void onPageFinished(WebView view, String url) {{ swipeLayout.setRefreshing(false); }}
134
  @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {{
135
  String reqUrl = request.getUrl().toString();
136
+ if (reqUrl.startsWith("http")) {{ if(reqUrl.contains("accounts.google.com")) {{ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(reqUrl))); return true; }} return false; }}
137
+ try {{ startActivity(Intent.parseUri(reqUrl, Intent.URI_INTENT_SCHEME)); return true; }} catch (Exception e) {{ return false; }}
 
 
 
 
 
 
 
138
  }}
139
  }});
140
+ myWebView.setWebChromeClient(new WebChromeClient()); myWebView.loadUrl("{url}");
 
141
  }}
142
+ @Override protected void onDestroy() {{ {'myWebView.clearCache(true);' if clear_cache_exit else ''} super.onDestroy(); }}
 
 
 
 
 
 
143
  @Override public void onBackPressed() {{ if (myWebView.canGoBack()) myWebView.goBack(); else super.onBackPressed(); }}
144
  }}"""
145
  with open(f"{java_dir}/MainActivity.java", "w") as f: f.write(main_java)
146
 
147
+ perms = ["INTERNET", "ACCESS_NETWORK_STATE"]
 
 
148
  if perm_camera: perms.append("CAMERA")
149
+ if perm_audio: perms.append("RECORD_AUDIO")
150
  if perm_location: perms.extend(["ACCESS_FINE_LOCATION", "ACCESS_COARSE_LOCATION"])
151
  if perm_storage: perms.extend(["READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE"])
152
  if perm_bg: perms.append("REQUEST_IGNORE_BATTERY_OPTIMIZATIONS")
153
  if perm_vibrate: perms.append("VIBRATE")
154
  if perm_contacts: perms.append("READ_CONTACTS")
155
  if onesignal_id or use_firebase: perms.append("POST_NOTIFICATIONS")
 
156
  perms_xml = "\n".join([f'<uses-permission android:name="android.permission.{p}" />' for p in perms])
 
157
 
158
+ manifest_xml = f"""<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="{package_name}">{perms_xml}<application android:label="{app_name}" android:icon="@mipmap/ic_launcher" android:theme="@style/AppTheme" android:usesCleartextTraffic="true" android:hardwareAccelerated="true">{'<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="' + admob_banner_id + '"/>' if enable_ads and admob_banner_id else ''}{f'<activity android:name=".SplashActivity" android:exported="true" android:screenOrientation="portrait"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>' if enable_splash else ''}<activity android:name=".MainActivity" android:exported="true" android:screenOrientation="{orientation}" android:configChanges="orientation|keyboardHidden|screenSize">{'' if enable_splash else '<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>'}</activity></application></manifest>"""
 
 
 
 
 
 
 
 
 
 
 
 
159
  with open(f"{project_dir}/app/src/main/AndroidManifest.xml", "w") as f: f.write(manifest_xml)
160
 
161
+ logs += "⚙️ بدء عملية التجميع... سجلات Gradle المباشرة:\n" + "="*40 + "\n"
162
  yield logs, None
163
 
 
164
  gradle_cmd = "gradle bundleRelease" if build_format == "aab" else "gradle assembleRelease"
165
  process = subprocess.Popen(gradle_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=project_dir, bufsize=1, universal_newlines=True)
166
 
 
169
  for line in iter(process.stdout.readline, ''):
170
  log_buffer.append(line)
171
  full_error_log += line
172
+ if len(log_buffer) > 40: log_buffer.pop(0)
173
  yield logs + "".join(log_buffer), None
 
174
  process.wait()
175
 
 
176
  if process.returncode == 0:
177
+ out_p = f"{project_dir}/app/build/outputs/bundle/release/app-release.aab" if build_format == "aab" else f"{project_dir}/app/build/outputs/apk/release/app-release.apk"
178
+ yield logs + "".join(log_buffer) + "\n\n✅ تم بناء التطبيق بنجاح!", out_p
 
179
  else:
180
+ yield logs + "".join(log_buffer) + f"\n\n❌ فشل البناء.\n{analyze_error_ai(full_error_log)}", None
 
 
 
 
 
 
 
 
181
 
182
+ # ================== واجهة المستخدم (Gradio UI المصلحة) ==================
183
+ with gr.Blocks() as demo:
184
+ gr.Markdown("<h1 style='text-align: center;'>📱 مصنع التطبيقات الشامل - الإصدار الذهبي V2</h1>")
185
+
186
  with gr.Accordion("1️⃣ الأساسيات | Core Basics", open=True):
187
+ app_name = gr.Textbox(label="اسم التطبيق | App Name", value="تطبيقي")
188
  url = gr.Textbox(label="الرابط | Website URL", value="https://google.com")
189
+ package_name = gr.Textbox(label="اسم الحزمة | Package Name", value="com.vip.app")
190
  build_format = gr.Dropdown(choices=["apk", "aab"], value="apk", label="صيغة الإخراج | Output Format")
191
  with gr.Row():
192
  version_name = gr.Textbox(label="الإصدار | Version", value="1.0.0")
193
  version_code = gr.Number(label="كود الإصدار | Version Code", value=1)
194
+ orientation = gr.Dropdown(choices=["unspecified", "portrait", "landscape"], value="unspecified", label="اتجاه الشاشة")
195
+ dev_name = gr.Textbox(label="اسم المطور (للتوقيع)")
196
+ dev_email = gr.Textbox(label="البريد الإلكتروني")
197
 
198
  with gr.Accordion("2️⃣ التصميم والواجهة | UI & Design", open=False):
199
+ icon_path = gr.File(label="الأيقونة | App Icon")
200
+ status_bar_color = gr.ColorPicker(label="لون شريط الحالة", value="#000000")
201
+ enable_splash = gr.Checkbox(label="تفعيل شاشة البداية", value=False)
202
+ splash_text = gr.Textbox(label="نص شاشة البداية", value="جاري التحميل...")
203
+ splash_color = gr.ColorPicker(label="لون خلفية البداية", value="#121212")
204
+ enable_bottom_nav = gr.Checkbox(label="شريط تنقل سفلي", value=False)
205
+ fullscreen = gr.Checkbox(label="وضع ملء الشاشة", value=False)
206
+ keep_screen_on = gr.Checkbox(label="إبقاء الشاشة مضاءة دائماً", value=False)
207
+
208
+ with gr.Accordion("3️⃣ محرك الويب المتقدم | Web Engine", open=False):
209
  js_enabled = gr.Checkbox(label="تفعيل JavaScript", value=True)
210
+ enable_zoom = gr.Checkbox(label="السماح بالتكبير", value=False)
211
+ dom_storage = gr.Checkbox(label="تفعيل التخزين المحلي (DOM)", value=True)
212
+ allow_file_access = gr.Checkbox(label="السماح برفع/قراءة الملفات", value=True)
213
+ media_auto_play = gr.Checkbox(label="تشغيل الوسائط تلقائياً", value=True)
214
+ clear_cache_exit = gr.Checkbox(label="مسح الكاش عند الإغلاق", value=False)
215
+ custom_user_agent = gr.Textbox(label="User Agent مخصص")
216
+
217
+ with gr.Accordion("4️⃣ الحماية والأمان | Security", open=False):
218
+ enable_security = gr.Checkbox(label="تشفير الكود (ProGuard)", value=True)
219
+ block_root = gr.Checkbox(label="منع الروت والمحاكيات", value=False)
220
+ prevent_screenshots = gr.Checkbox(label="منع لقطات الشاشة", value=False)
221
+ clear_cookies_exit = gr.Checkbox(label="تسجيل الخروج (مسح الكوكيز) عند الإغلاق", value=False)
222
+
223
+ with gr.Accordion("5️⃣ الإعلانات والخدمات | Services", open=False):
224
+ firebase_file = gr.File(label="ملف Firebase json")
225
+ firebase_text = gr.Textbox(label="أو الصق كود Firebase هنا", lines=3)
226
+ onesignal_id = gr.Textbox(label="معرف OneSignal")
227
+ enable_ads = gr.Checkbox(label="تفعيل AdMob", value=False)
228
+ admob_banner_id = gr.Textbox(label="AdMob ID")
229
+
230
+ with gr.Accordion("6️⃣ الأذونات | Permissions", open=False):
231
+ perm_internet = gr.Checkbox(label="الإنترنت", value=True, interactive=False)
232
+ perm_camera = gr.Checkbox(label="الكاميرا")
233
+ perm_audio = gr.Checkbox(label="الميكروفون")
234
+ perm_location = gr.Checkbox(label="الموقع")
235
+ perm_storage = gr.Checkbox(label="الملفات")
236
+ perm_bg = gr.Checkbox(label="العمل في الخلفية")
237
+ perm_vibrate = gr.Checkbox(label="الاهتزاز")
238
+ perm_contacts = gr.Checkbox(label="جهات الاتصال")
 
 
239
 
240
  build_btn = gr.Button("🚀 بدء بناء التطبيق | Start Build", variant="primary", size="lg")
241
 
242
  with gr.Group():
243
+ # تم إزالة show_copy_button لحل مشكلة الخطأ
244
+ logs_out = gr.Textbox(label="🖥️ السجلات المباشرة والذكاء الاصطناعي | Live Logs & AI", lines=12, max_lines=15)
245
+ file_out = gr.File(label="📥 تحميل التطبيق")
246
 
247
  inputs = [
248
  app_name, url, package_name, build_format, version_name, version_code, orientation,
 
250
  icon_path, enable_splash, splash_text, splash_color, status_bar_color, enable_bottom_nav, fullscreen, keep_screen_on,
251
  js_enabled, enable_zoom, dom_storage, allow_file_access, clear_cache_exit, custom_user_agent, media_auto_play,
252
  enable_security, block_root, prevent_screenshots, clear_cookies_exit,
253
+ enable_ads, admob_banner_id, gr.State(""), onesignal_id, firebase_file, firebase_text,
254
  perm_internet, perm_camera, perm_audio, perm_location, perm_storage, perm_bg, perm_vibrate, perm_contacts
255
  ]
256
 
257
  build_btn.click(fn=build_ultimate_app, inputs=inputs, outputs=[logs_out, file_out])
258
 
259
+ # التوافق مع Gradio 6.0
260
  demo.queue(max_size=20, default_concurrency_limit=3)
261
  demo.launch(server_name="0.0.0.0", server_port=7860)