ayham909 commited on
Commit
81c0e16
·
verified ·
1 Parent(s): cf8ce9f

اضف امكانية متابعة الاخوة لرئية المنشورات - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +725 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Https Huggingface Co Organizations Towhed
3
- emoji: 🏢
4
  colorFrom: red
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: https-huggingface-co-organizations-towhed
3
+ emoji: 🐳
4
  colorFrom: red
5
+ colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,725 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Towhed Messaging App</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .message-bubble {
11
+ max-width: 70%;
12
+ border-radius: 1rem;
13
+ padding: 0.75rem 1rem;
14
+ margin-bottom: 0.5rem;
15
+ position: relative;
16
+ }
17
+ .message-bubble.sent {
18
+ background-color: #3b82f6;
19
+ color: white;
20
+ align-self: flex-end;
21
+ }
22
+ .message-bubble.received {
23
+ background-color: #e5e7eb;
24
+ color: #1f2937;
25
+ align-self: flex-start;
26
+ }
27
+ .message-time {
28
+ font-size: 0.75rem;
29
+ opacity: 0.8;
30
+ margin-top: 0.25rem;
31
+ text-align: right;
32
+ }
33
+ .app-bar {
34
+ height: 56px;
35
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
36
+ }
37
+ .chat-container {
38
+ height: calc(100vh - 56px - 64px);
39
+ overflow-y: auto;
40
+ }
41
+ .input-container {
42
+ height: 64px;
43
+ }
44
+ .floating-button {
45
+ position: fixed;
46
+ bottom: 1.5rem;
47
+ right: 1.5rem;
48
+ width: 56px;
49
+ height: 56px;
50
+ border-radius: 50%;
51
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ z-index: 10;
56
+ }
57
+ </style>
58
+ </head>
59
+ <body class="bg-gray-100 font-sans">
60
+ <!-- Login Screen -->
61
+ <div id="login-screen" class="fixed inset-0 bg-white flex flex-col items-center justify-center p-6 z-20">
62
+ <div class="w-full max-w-md">
63
+ <div class="text-center mb-8">
64
+ <h1 class="text-3xl font-bold text-blue-600">Towhed</h1>
65
+ <p class="text-gray-600 mt-2">Secure messaging with admin verification</p>
66
+ </div>
67
+
68
+ <div class="bg-white rounded-lg shadow-md p-6">
69
+ <h2 class="text-xl font-semibold mb-4 text-gray-800">Login</h2>
70
+
71
+ <div class="mb-6">
72
+ <label class="block text-gray-700 text-sm font-medium mb-2" for="code">
73
+ Admin Verification Code
74
+ </label>
75
+ <input id="code" type="text" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter 6-digit code">
76
+ <p class="text-xs text-gray-500 mt-1">You must get this code from the system admin</p>
77
+ </div>
78
+
79
+ <button onclick="login()" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition">
80
+ Login
81
+ </button>
82
+
83
+ <div class="mt-4 text-center">
84
+ <p class="text-sm text-gray-600">Don't have an account? <span class="text-blue-600 cursor-pointer" onclick="showAdminPanel()">Request admin access</span></p>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ </div>
89
+
90
+ <!-- Admin Panel (Hidden by default) -->
91
+ <div id="admin-panel" class="fixed inset-0 bg-white flex flex-col items-center justify-center p-6 z-20 hidden">
92
+ <div class="w-full max-w-md">
93
+ <div class="flex justify-between items-center mb-6">
94
+ <button onclick="hideAdminPanel()" class="text-gray-500 hover:text-gray-700">
95
+ <i class="fas fa-arrow-left"></i>
96
+ </button>
97
+ <h2 class="text-xl font-semibold text-gray-800">Admin Panel</h2>
98
+ <div class="w-6"></div> <!-- Spacer for alignment -->
99
+ </div>
100
+
101
+ <div class="bg-white rounded-lg shadow-md p-6">
102
+ <div class="mb-6">
103
+ <label class="block text-gray-700 text-sm font-medium mb-2" for="admin-username">
104
+ Admin Username
105
+ </label>
106
+ <input id="admin-username" type="text" class="w-full px-3 py-2 border border-gray-300 rounded-md mb-4 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter admin username">
107
+
108
+ <label class="block text-gray-700 text-sm font-medium mb-2" for="admin-password">
109
+ Admin Password
110
+ </label>
111
+ <input id="admin-password" type="password" class="w-full px-3 py-2 border border-gray-300 rounded-md mb-4 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter admin password">
112
+
113
+ <label class="block text-gray-700 text-sm font-medium mb-2" for="generate-code">
114
+ Generate Verification Code
115
+ </label>
116
+ <div class="flex mb-2">
117
+ <input id="generated-code" type="text" readonly class="flex-1 px-3 py-2 border border-gray-300 rounded-l-md bg-gray-100" placeholder="Code will appear here">
118
+ <button onclick="generateCode()" class="bg-blue-600 text-white px-4 py-2 rounded-r-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition">
119
+ Generate
120
+ </button>
121
+ </div>
122
+ <div class="flex justify-between items-center">
123
+ <span class="text-xs text-gray-500">Code expires in: <span id="code-expiry">5:00</span></span>
124
+ <button onclick="copyCode()" class="text-xs text-blue-600 hover:text-blue-800">
125
+ <i class="fas fa-copy mr-1"></i>Copy Code
126
+ </button>
127
+ </div>
128
+ </div>
129
+
130
+ <div class="mt-6 p-4 bg-blue-50 rounded-md">
131
+ <h3 class="font-medium text-blue-800 mb-2">Admin Instructions</h3>
132
+ <p class="text-sm text-blue-700">1. Enter admin credentials</p>
133
+ <p class="text-sm text-blue-700">2. Click "Generate" to create a code</p>
134
+ <p class="text-sm text-blue-700">3. Share this code securely with authorized users</p>
135
+ <p class="text-sm text-blue-700">4. Each code is valid for 5 minutes only</p>
136
+ </div>
137
+
138
+ <div class="mt-4 p-4 bg-gray-50 rounded-md">
139
+ <h3 class="font-medium text-gray-800 mb-2">Recent Codes</h3>
140
+ <div id="recent-codes" class="text-sm text-gray-700">
141
+ <!-- Generated codes will appear here -->
142
+ </div>
143
+ </div>
144
+ </div>
145
+ </div>
146
+ </div>
147
+
148
+ <!-- Main App Interface (Hidden until login) -->
149
+ <div id="app-interface" class="hidden">
150
+ <!-- App Bar with Tabs -->
151
+ <div class="app-bar bg-white flex flex-col fixed top-0 left-0 right-0 z-10">
152
+ <div class="flex items-center px-4 py-2">
153
+ <img src="https://via.placeholder.com/40" alt="Profile" class="rounded-full w-8 h-8 mr-3">
154
+ <div>
155
+ <h1 class="font-medium">Towhed</h1>
156
+ <p class="text-xs text-gray-500">My Profile</p>
157
+ <div class="flex space-x-4 text-xs mt-1">
158
+ <span><span class="font-medium">120</span> Posts</span>
159
+ <span><span class="font-medium">1.2K</span> Followers</span>
160
+ <span><span class="font-medium">350</span> Following</span>
161
+ </div>
162
+ </div>
163
+ <div class="ml-auto flex space-x-4">
164
+ <button class="text-gray-600 hover:text-gray-900">
165
+ <i class="fas fa-plus"></i>
166
+ </button>
167
+ <button class="text-gray-600 hover:text-gray-900">
168
+ <i class="fas fa-ellipsis-v"></i>
169
+ </button>
170
+ </div>
171
+ </div>
172
+ <div class="flex border-b border-gray-200">
173
+ <button onclick="showTab('posts')" class="flex-1 py-2 text-center font-medium text-blue-600 border-b-2 border-blue-600">
174
+ Posts
175
+ </button>
176
+ <button onclick="showTab('messages')" class="flex-1 py-2 text-center font-medium text-gray-500 hover:text-gray-700">
177
+ Messages
178
+ </button>
179
+ </div>
180
+ </div>
181
+
182
+ <!-- Content Area -->
183
+ <div class="chat-container pt-24 pb-16 overflow-y-auto">
184
+ <!-- Posts Tab -->
185
+ <div id="posts-tab" class="flex flex-col">
186
+ <!-- Posts Filter -->
187
+ <div class="bg-white p-3 border-b border-gray-200 flex items-center">
188
+ <span class="text-sm font-medium mr-2">Show:</span>
189
+ <select class="bg-gray-100 rounded-md px-2 py-1 text-sm focus:outline-none">
190
+ <option>Posts from everyone</option>
191
+ <option>Posts from people I follow</option>
192
+ <option>My posts only</option>
193
+ </select>
194
+ </div>
195
+
196
+ <!-- Create Post -->
197
+ <div class="bg-white p-4 border-b border-gray-200">
198
+ <div class="flex items-center mb-3">
199
+ <img src="https://via.placeholder.com/40" alt="Profile" class="rounded-full w-10 h-10 mr-3">
200
+ <input type="text" placeholder="What's on your mind?" class="flex-1 bg-gray-100 rounded-full py-2 px-4 focus:outline-none">
201
+ </div>
202
+ <button class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700">
203
+ Post
204
+ </button>
205
+ </div>
206
+
207
+ <!-- Sample Posts -->
208
+ <div class="bg-white p-4 mb-2 border-b border-gray-200">
209
+ <div class="flex items-center justify-between mb-3">
210
+ <div class="flex items-center">
211
+ <img src="https://via.placeholder.com/40" alt="Profile" class="rounded-full w-10 h-10 mr-3">
212
+ <div>
213
+ <h3 class="font-medium">User One</h3>
214
+ <p class="text-xs text-gray-500">2 hours ago</p>
215
+ </div>
216
+ </div>
217
+ <button class="text-xs bg-gray-100 hover:bg-gray-200 px-3 py-1 rounded-full">
218
+ <i class="fas fa-user-plus mr-1"></i>Follow
219
+ </button>
220
+ </div>
221
+ <p class="mb-3">This is my first post on Towhed! Excited to share my thoughts here.</p>
222
+ <div class="flex justify-between text-gray-500 border-t border-gray-200 pt-2">
223
+ <button class="flex items-center space-x-1 hover:text-blue-600">
224
+ <i class="far fa-thumbs-up"></i>
225
+ <span>Like (12)</span>
226
+ </button>
227
+ <button class="flex items-center space-x-1 hover:text-red-600">
228
+ <i class="far fa-thumbs-down"></i>
229
+ <span>Dislike (2)</span>
230
+ </button>
231
+ <button class="flex items-center space-x-1 hover:text-yellow-600">
232
+ <i class="far fa-surprise"></i>
233
+ <span>Surprised (5)</span>
234
+ </button>
235
+ </div>
236
+ </div>
237
+
238
+ <div class="bg-white p-4 mb-2 border-b border-gray-200">
239
+ <div class="flex items-center justify-between mb-3">
240
+ <div class="flex items-center">
241
+ <img src="https://via.placeholder.com/40" alt="Profile" class="rounded-full w-10 h-10 mr-3">
242
+ <div>
243
+ <h3 class="font-medium">User Two</h3>
244
+ <p class="text-xs text-gray-500">5 hours ago</p>
245
+ </div>
246
+ </div>
247
+ <button class="text-xs bg-gray-100 hover:bg-gray-200 px-3 py-1 rounded-full">
248
+ <i class="fas fa-user-plus mr-1"></i>Follow
249
+ </button>
250
+ </div>
251
+ <p class="mb-3">Check out this amazing view from my vacation!</p>
252
+ <img src="https://via.placeholder.com/600x300" alt="Post image" class="w-full rounded-md mb-3">
253
+ <div class="flex justify-between text-gray-500 border-t border-gray-200 pt-2">
254
+ <button class="flex items-center space-x-1 hover:text-blue-600">
255
+ <i class="far fa-thumbs-up"></i>
256
+ <span>Like (45)</span>
257
+ </button>
258
+ <button class="flex items-center space-x-1 hover:text-red-600">
259
+ <i class="far fa-thumbs-down"></i>
260
+ <span>Dislike (3)</span>
261
+ </button>
262
+ <button class="flex items-center space-x-1 hover:text-yellow-600">
263
+ <i class="far fa-surprise"></i>
264
+ <span>Surprised (8)</span>
265
+ </button>
266
+ </div>
267
+ </div>
268
+ </div>
269
+
270
+ <!-- Messages Tab (hidden by default) -->
271
+ <div id="messages-tab" class="hidden flex flex-col space-y-2 px-4">
272
+ <!-- Date divider -->
273
+ <div class="flex items-center my-4">
274
+ <div class="flex-1 border-t border-gray-200"></div>
275
+ <span class="px-3 text-sm text-gray-500">Today</span>
276
+ <div class="flex-1 border-t border-gray-200"></div>
277
+ </div>
278
+
279
+ <!-- Received message -->
280
+ <div class="flex">
281
+ <div class="message-bubble received">
282
+ <p>Hello! Welcome to Towhed messaging app.</p>
283
+ <div class="message-time">10:30 AM</div>
284
+ </div>
285
+ </div>
286
+
287
+ <!-- Sent message -->
288
+ <div class="flex justify-end">
289
+ <div class="message-bubble sent">
290
+ <p>Hi there! Thanks for the welcome.</p>
291
+ <div class="message-time">10:32 AM</div>
292
+ </div>
293
+ </div>
294
+ </div>
295
+ </div>
296
+
297
+ <!-- Input Area -->
298
+ <div class="input-container bg-white fixed bottom-0 left-0 right-0 flex items-center px-4 border-t border-gray-200">
299
+ <button class="text-gray-500 hover:text-gray-700 mr-2">
300
+ <i class="fas fa-paperclip"></i>
301
+ </button>
302
+ <input type="text" placeholder="Type a message" class="flex-1 py-2 px-3 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500">
303
+ <button class="ml-2 text-blue-600 hover:text-blue-800">
304
+ <i class="fas fa-paper-plane"></i>
305
+ </button>
306
+ </div>
307
+
308
+ <!-- Floating action button -->
309
+ <div class="floating-button bg-blue-600 text-white hover:bg-blue-700">
310
+ <i class="fas fa-comment-medical"></i>
311
+ </div>
312
+ </div>
313
+
314
+ <!-- Kotlin Code Section (Hidden by default) -->
315
+ <div id="kotlin-code" class="fixed inset-0 bg-white p-6 overflow-auto hidden z-30">
316
+ <div class="max-w-4xl mx-auto">
317
+ <div class="flex justify-between items-center mb-6">
318
+ <h2 class="text-2xl font-bold text-gray-800">Towhed Kotlin Implementation</h2>
319
+ <button onclick="hideKotlinCode()" class="text-gray-500 hover:text-gray-700 p-2">
320
+ <i class="fas fa-times"></i>
321
+ </button>
322
+ </div>
323
+
324
+ <div class="bg-gray-800 rounded-lg p-4 overflow-x-auto">
325
+ <pre class="text-gray-100 text-sm">
326
+ // MainActivity.kt
327
+ package com.example.towhed
328
+
329
+ import android.os.Bundle
330
+ import androidx.appcompat.app.AppCompatActivity
331
+ import androidx.recyclerview.widget.LinearLayoutManager
332
+ import com.example.towhed.databinding.ActivityMainBinding
333
+ import com.google.firebase.auth.FirebaseAuth
334
+ import com.google.firebase.firestore.FirebaseFirestore
335
+
336
+ class MainActivity : AppCompatActivity() {
337
+ private lateinit var binding: ActivityMainBinding
338
+ private lateinit var auth: FirebaseAuth
339
+ private lateinit var db: FirebaseFirestore
340
+ private lateinit var adapter: MessageAdapter
341
+ private val messages = mutableListOf&lt;Message&gt;()
342
+
343
+ override fun onCreate(savedInstanceState: Bundle?) {
344
+ super.onCreate(savedInstanceState)
345
+ binding = ActivityMainBinding.inflate(layoutInflater)
346
+ setContentView(binding.root)
347
+
348
+ auth = FirebaseAuth.getInstance()
349
+ db = FirebaseFirestore.getInstance()
350
+
351
+ // Check if user is logged in with admin code
352
+ if (auth.currentUser == null) {
353
+ startActivity(Intent(this, LoginActivity::class.java))
354
+ finish()
355
+ return
356
+ }
357
+
358
+ setupRecyclerView()
359
+ setupListeners()
360
+ loadMessages()
361
+ }
362
+
363
+ private fun setupRecyclerView() {
364
+ adapter = MessageAdapter(messages)
365
+ binding.recyclerView.apply {
366
+ layoutManager = LinearLayoutManager(this@MainActivity)
367
+ adapter = this@MainActivity.adapter
368
+ }
369
+ }
370
+
371
+ private fun setupListeners() {
372
+ binding.sendButton.setOnClickListener {
373
+ val messageText = binding.messageInput.text.toString().trim()
374
+ if (messageText.isNotEmpty()) {
375
+ sendMessage(messageText)
376
+ binding.messageInput.text.clear()
377
+ }
378
+ }
379
+ }
380
+
381
+ private fun sendMessage(text: String) {
382
+ val message = Message(
383
+ text = text,
384
+ senderId = auth.currentUser?.uid ?: "",
385
+ timestamp = System.currentTimeMillis()
386
+ )
387
+
388
+ db.collection("messages")
389
+ .add(message)
390
+ .addOnSuccessListener {
391
+ // Message sent successfully
392
+ }
393
+ .addOnFailureListener {
394
+ // Handle error
395
+ }
396
+ }
397
+
398
+ private fun loadMessages() {
399
+ db.collection("messages")
400
+ .orderBy("timestamp")
401
+ .addSnapshotListener { snapshot, error ->
402
+ if (error != null) return@addSnapshotListener
403
+
404
+ messages.clear()
405
+ snapshot?.documents?.forEach { doc ->
406
+ val message = doc.toObject(Message::class.java)
407
+ message?.let { messages.add(it) }
408
+ }
409
+ adapter.notifyDataSetChanged()
410
+ binding.recyclerView.scrollToPosition(messages.size - 1)
411
+ }
412
+ }
413
+ }
414
+
415
+ // LoginActivity.kt
416
+ package com.example.towhed
417
+
418
+ import android.content.Intent
419
+ import android.os.Bundle
420
+ import androidx.appcompat.app.AppCompatActivity
421
+ import com.example.towhed.databinding.ActivityLoginBinding
422
+ import com.google.firebase.auth.FirebaseAuth
423
+ import com.google.firebase.firestore.FirebaseFirestore
424
+
425
+ class LoginActivity : AppCompatActivity() {
426
+ private lateinit var binding: ActivityLoginBinding
427
+ private lateinit var auth: FirebaseAuth
428
+ private lateinit var db: FirebaseFirestore
429
+
430
+ override fun onCreate(savedInstanceState: Bundle?) {
431
+ super.onCreate(savedInstanceState)
432
+ binding = ActivityLoginBinding.inflate(layoutInflater)
433
+ setContentView(binding.root)
434
+
435
+ auth = FirebaseAuth.getInstance()
436
+ db = FirebaseFirestore.getInstance()
437
+
438
+ binding.loginButton.setOnClickListener {
439
+ val phone = binding.phoneInput.text.toString().trim()
440
+ val code = binding.codeInput.text.toString().trim()
441
+
442
+ if (phone.isEmpty() || code.isEmpty()) {
443
+ // Show error
444
+ return@setOnClickListener
445
+ }
446
+
447
+ verifyAdminCode(phone, code)
448
+ }
449
+
450
+ binding.adminLink.setOnClickListener {
451
+ startActivity(Intent(this, AdminActivity::class.java))
452
+ }
453
+ }
454
+
455
+ private fun verifyAdminCode(code: String) {
456
+ db.collection("admin_codes")
457
+ .whereEqualTo("code", code)
458
+ .limit(1)
459
+ .get()
460
+ .addOnSuccessListener { doc ->
461
+ if (doc.exists() && doc.getString("code") == code) {
462
+ // Code is valid, proceed with authentication
463
+ authenticateUser(phone)
464
+ } else {
465
+ // Show invalid code error
466
+ }
467
+ }
468
+ .addOnFailureListener {
469
+ // Handle error
470
+ }
471
+ }
472
+
473
+ private fun authenticateUser(phone: String) {
474
+ // Implement phone authentication with Firebase
475
+ // On success:
476
+ startActivity(Intent(this, MainActivity::class.java))
477
+ finish()
478
+ }
479
+ }
480
+
481
+ // AdminActivity.kt
482
+ package com.example.towhed
483
+
484
+ import android.os.Bundle
485
+ import androidx.appcompat.app.AppCompatActivity
486
+ import com.example.towhed.databinding.ActivityAdminBinding
487
+ import com.google.firebase.firestore.FirebaseFirestore
488
+ import java.util.*
489
+
490
+ class AdminActivity : AppCompatActivity() {
491
+ private lateinit var binding: ActivityAdminBinding
492
+ private lateinit var db: FirebaseFirestore
493
+
494
+ override fun onCreate(savedInstanceState: Bundle?) {
495
+ super.onCreate(savedInstanceState)
496
+ binding = ActivityAdminBinding.inflate(layoutInflater)
497
+ setContentView(binding.root)
498
+
499
+ db = FirebaseFirestore.getInstance()
500
+
501
+ binding.generateButton.setOnClickListener {
502
+ val phone = binding.phoneInput.text.toString().trim()
503
+ if (phone.isEmpty()) return@setOnClickListener
504
+
505
+ val code = generateRandomCode()
506
+ binding.codeOutput.setText(code)
507
+
508
+ saveAdminCode(phone, code)
509
+ }
510
+ }
511
+
512
+ private fun generateRandomCode(): String {
513
+ return (100000..999999).random().toString()
514
+ }
515
+
516
+ private fun saveAdminCode(phone: String, code: String) {
517
+ val data = hashMapOf(
518
+ "phone" to phone,
519
+ "code" to code,
520
+ "generatedAt" to System.currentTimeMillis()
521
+ )
522
+
523
+ db.collection("admin_codes")
524
+ .document(phone)
525
+ .set(data)
526
+ .addOnSuccessListener {
527
+ // Code saved successfully
528
+ }
529
+ .addOnFailureListener {
530
+ // Handle error
531
+ }
532
+ }
533
+ }
534
+
535
+ // Message.kt
536
+ data class Message(
537
+ val text: String = "",
538
+ val senderId: String = "",
539
+ val timestamp: Long = 0L
540
+ )
541
+
542
+ // MessageAdapter.kt
543
+ class MessageAdapter(private val messages: List&lt;Message&gt;) :
544
+ RecyclerView.Adapter&lt;MessageAdapter.MessageViewHolder&gt;() {
545
+
546
+ inner class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
547
+ fun bind(message: Message) {
548
+ // Bind message data to views
549
+ }
550
+ }
551
+
552
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
553
+ val view = LayoutInflater.from(parent.context)
554
+ .inflate(R.layout.item_message, parent, false)
555
+ return MessageViewHolder(view)
556
+ }
557
+
558
+ override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
559
+ holder.bind(messages[position])
560
+ }
561
+
562
+ override fun getItemCount(): Int = messages.size
563
+ }
564
+ </pre>
565
+ </div>
566
+
567
+ <div class="mt-6 bg-blue-50 p-4 rounded-md">
568
+ <h3 class="font-medium text-blue-800 mb-2">Implementation Notes:</h3>
569
+ <ul class="list-disc pl-5 text-blue-700 space-y-1">
570
+ <li>Uses Firebase Authentication for user management</li>
571
+ <li>Firestore database stores messages and admin codes</li>
572
+ <li>Admin codes are generated randomly and stored</li>
573
+ <li>Users must provide exact admin code to login</li>
574
+ <li>Real-time messaging with Firestore listeners</li>
575
+ <li>Clean architecture with separate activities</li>
576
+ </ul>
577
+ </div>
578
+
579
+ <button onclick="hideKotlinCode()" class="mt-6 w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition">
580
+ Close Code View
581
+ </button>
582
+ </div>
583
+ </div>
584
+
585
+ <!-- View Code Button -->
586
+ <div class="fixed bottom-4 left-4 z-10">
587
+ <button onclick="showKotlinCode()" class="bg-gray-800 text-white py-2 px-4 rounded-md hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition flex items-center">
588
+ <i class="fas fa-code mr-2"></i>
589
+ View Kotlin Code
590
+ </button>
591
+ </div>
592
+
593
+ <script>
594
+ // Show/hide admin panel
595
+ function showAdminPanel() {
596
+ document.getElementById('login-screen').classList.add('hidden');
597
+ document.getElementById('admin-panel').classList.remove('hidden');
598
+ }
599
+
600
+ function hideAdminPanel() {
601
+ document.getElementById('admin-panel').classList.add('hidden');
602
+ document.getElementById('login-screen').classList.remove('hidden');
603
+ }
604
+
605
+ // Admin functions
606
+ let currentCode = null;
607
+ let expiryInterval = null;
608
+
609
+ function generateCode() {
610
+ const username = document.getElementById('admin-username').value;
611
+ const password = document.getElementById('admin-password').value;
612
+
613
+ if (!username || !password) {
614
+ alert('Please enter admin credentials');
615
+ return;
616
+ }
617
+
618
+ // In a real app, verify admin credentials with backend here
619
+
620
+ const code = Math.floor(100000 + Math.random() * 900000);
621
+ currentCode = code;
622
+ document.getElementById('generated-code').value = code;
623
+
624
+ // Add to recent codes
625
+ const recentCodesDiv = document.getElementById('recent-codes');
626
+ const codeElement = document.createElement('div');
627
+ codeElement.className = 'py-1 border-b border-gray-200';
628
+ codeElement.innerHTML = `
629
+ <span class="font-mono">${code}</span>
630
+ <span class="text-gray-500 text-xs ml-2">${new Date().toLocaleTimeString()}</span>
631
+ `;
632
+ recentCodesDiv.prepend(codeElement);
633
+
634
+ // Start countdown timer (5 minutes)
635
+ let minutes = 4;
636
+ let seconds = 59;
637
+ document.getElementById('code-expiry').textContent = '5:00';
638
+
639
+ if (expiryInterval) clearInterval(expiryInterval);
640
+
641
+ expiryInterval = setInterval(() => {
642
+ if (seconds === 0) {
643
+ if (minutes === 0) {
644
+ clearInterval(expiryInterval);
645
+ document.getElementById('code-expiry').textContent = 'Expired';
646
+ currentCode = null;
647
+ return;
648
+ }
649
+ minutes--;
650
+ seconds = 59;
651
+ } else {
652
+ seconds--;
653
+ }
654
+
655
+ const formattedSeconds = seconds < 10 ? `0${seconds}` : seconds;
656
+ document.getElementById('code-expiry').textContent = `${minutes}:${formattedSeconds}`;
657
+ }, 1000);
658
+ }
659
+
660
+ function copyCode() {
661
+ if (!currentCode) {
662
+ alert('No code generated yet');
663
+ return;
664
+ }
665
+
666
+ navigator.clipboard.writeText(currentCode.toString())
667
+ .then(() => alert('Code copied to clipboard'))
668
+ .catch(() => alert('Failed to copy code'));
669
+ }
670
+
671
+ // Login function
672
+ function login() {
673
+ const code = document.getElementById('code').value;
674
+
675
+ if (code) {
676
+ // In a real app, you would verify with backend
677
+ document.getElementById('login-screen').classList.add('hidden');
678
+ document.getElementById('app-interface').classList.remove('hidden');
679
+ } else {
680
+ alert('Please enter both phone number and verification code');
681
+ }
682
+ }
683
+
684
+ // Tab switching
685
+ function showTab(tabName) {
686
+ if (tabName === 'posts') {
687
+ document.getElementById('posts-tab').classList.remove('hidden');
688
+ document.getElementById('messages-tab').classList.add('hidden');
689
+ // Update active tab styling
690
+ document.querySelectorAll('.flex.border-b button').forEach(btn => {
691
+ if (btn.textContent.includes('Posts')) {
692
+ btn.classList.add('text-blue-600', 'border-blue-600');
693
+ btn.classList.remove('text-gray-500');
694
+ } else {
695
+ btn.classList.remove('text-blue-600', 'border-blue-600');
696
+ btn.classList.add('text-gray-500');
697
+ }
698
+ });
699
+ } else {
700
+ document.getElementById('posts-tab').classList.add('hidden');
701
+ document.getElementById('messages-tab').classList.remove('hidden');
702
+ // Update active tab styling
703
+ document.querySelectorAll('.flex.border-b button').forEach(btn => {
704
+ if (btn.textContent.includes('Messages')) {
705
+ btn.classList.add('text-blue-600', 'border-blue-600');
706
+ btn.classList.remove('text-gray-500');
707
+ } else {
708
+ btn.classList.remove('text-blue-600', 'border-blue-600');
709
+ btn.classList.add('text-gray-500');
710
+ }
711
+ });
712
+ }
713
+ }
714
+
715
+ // Show/hide Kotlin code
716
+ function showKotlinCode() {
717
+ document.getElementById('kotlin-code').classList.remove('hidden');
718
+ }
719
+
720
+ function hideKotlinCode() {
721
+ document.getElementById('kotlin-code').classList.add('hidden');
722
+ }
723
+ </script>
724
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=ayham909/https-huggingface-co-organizations-towhed" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
725
+ </html>