commit 9861577589682028c56a1aa173f27a0fe5cd82d0 parent bb9dcd91a472055d09a46ca97a307bf562b732db Author: t3serakt <t3ss@posteo.de> Date: Wed, 9 Apr 2025 20:04:19 +0200 Added Lobby GUI. Diffstat:
14 files changed, 322 insertions(+), 30 deletions(-)
diff --git a/GNUnetMessenger/.idea/misc.xml b/GNUnetMessenger/.idea/misc.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ExternalStorageConfigurationManager" enabled="true" /> - <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> diff --git a/GNUnetMessenger/app/build.gradle.kts b/GNUnetMessenger/app/build.gradle.kts @@ -44,6 +44,8 @@ android { dependencies { + implementation(libs.zxingcore) + implementation(libs.zxingandroidembedded) implementation(libs.firebase.bom) implementation(libs.androidx.cardview) implementation(libs.androidx.core.ktx) @@ -56,4 +58,5 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + } \ No newline at end of file diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/MainActivity.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/MainActivity.kt @@ -2,6 +2,7 @@ package org.gnunet.gnunetmessenger import android.os.Bundle import android.view.Menu +import android.view.MenuItem import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.navigation.NavController @@ -23,7 +24,8 @@ class MainActivity : AppCompatActivity() { private lateinit var navController: NavController private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var handle: ChatHandle - private lateinit var currentAccount: ChatAccount + var currentAccount: ChatAccount? = null + private set override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -62,9 +64,36 @@ class MainActivity : AppCompatActivity() { } override fun onCreateOptionsMenu(menu: Menu?): Boolean { - // Fragment-spezifisches Menü wird vom Fragment selbst gesetzt - // Hier könntest du bei Bedarf globales Menü setzen - return super.onCreateOptionsMenu(menu) + menuInflater.inflate(R.menu.main_menu, menu) + val current = currentAccount + menu?.findItem(R.id.menu_current_account)?.title = "Account: ${current?.name ?: "?"}" + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.menu_current_account -> { + val action = NavGraphDirections.actionGlobalAccountDetailsFragment() + navController.navigate(action) + true + } + R.id.menu_create_lobby -> { + val action = NavGraphDirections.actionGlobalLobbyCreateFragment() + navController.navigate(action) + true + } + R.id.menu_settings -> { + // Beispiel: Navigation zu Einstellungen + // startActivity(Intent(this, SettingsActivity::class.java)) + true + } + R.id.menu_about -> { + // Beispiel: Über-Dialog anzeigen + // showAboutDialog() + true + } + else -> super.onOptionsItemSelected(item) + } } override fun onSupportNavigateUp(): Boolean { diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountOverviewFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountOverviewFragment.kt @@ -30,10 +30,6 @@ class AccountOverviewFragment : Fragment() { drawerLayout = binding.accountDrawerLayout - // Toolbar Setup - (activity as MainActivity).setSupportActionBar(binding.toolbar) - setHasOptionsMenu(true) - // Setup Chat list (dummy data vorerst) val chatList = listOf("Chat mit Alex", "Projektgruppe", "Family", "Plattform XYZ") val adapter = ChatListAdapter(chatList) { selectedChat -> @@ -44,23 +40,6 @@ class AccountOverviewFragment : Fragment() { binding.chatListRecyclerView.layoutManager = LinearLayoutManager(requireContext()) binding.chatListRecyclerView.adapter = adapter - // Menu Item Listener - binding.accountNavigationView.setNavigationItemSelectedListener { menuItem -> - when (menuItem.itemId) { - R.id.nav_account -> { - findNavController().navigate(AccountOverviewFragmentDirections.actionAccountOverviewFragmentToAccountDetailsFragment()) - } - R.id.nav_share_contact -> { - findNavController().navigate(AccountOverviewFragmentDirections.actionAccountOverviewFragmentToAccountDetailsFragment()) - } - R.id.nav_list_attributes -> { - findNavController().navigate(AccountOverviewFragmentDirections.actionAccountOverviewFragmentToAccountDetailsFragment()) - } - } - drawerLayout.closeDrawers() - true - } - return binding.root } diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/LobbyCreateFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/LobbyCreateFragment.kt @@ -0,0 +1,39 @@ +package org.gnunet.gnunetmessenger.ui.account + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.Button +import android.widget.Spinner +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import org.gnunet.gnunetmessenger.R +import java.util.UUID + +class LobbyCreateFragment : Fragment() { + + private val lifetimes = listOf("Off", "4 weeks", "1 week", "1 day", "8 hours", "5 minutes", "30 seconds") + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val view = inflater.inflate(R.layout.fragment_lobby_create, container, false) + + val spinner = view.findViewById<Spinner>(R.id.lifetime_spinner) + val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, lifetimes) + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + spinner.adapter = adapter + + view.findViewById<Button>(R.id.btn_cancel).setOnClickListener { + findNavController().popBackStack() + } + + view.findViewById<Button>(R.id.btn_generate).setOnClickListener { + val selectedLifetime = spinner.selectedItem.toString() + val action = LobbyCreateFragmentDirections.actionLobbyCreateFragmentToLobbyDisplayFragment(lobbyId = UUID.randomUUID().toString(), lifetime = selectedLifetime) + findNavController().navigate(action) + } + + return view + } +} diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/LobbyDisplayFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/LobbyDisplayFragment.kt @@ -0,0 +1,57 @@ +package org.gnunet.gnunetmessenger.ui.account + +import android.content.ClipboardManager +import android.content.ClipData +import android.graphics.Bitmap +import android.graphics.Color +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.TextView +import android.widget.ImageView +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import com.google.zxing.BarcodeFormat +import com.google.zxing.qrcode.QRCodeWriter +import org.gnunet.gnunetmessenger.R + +class LobbyDisplayFragment : Fragment() { + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val view = inflater.inflate(R.layout.fragment_lobby_display, container, false) + + val lobbyId = arguments?.getString("lobbyId") ?: "N/A" + + view.findViewById<TextView>(R.id.lobby_id_text).text = "Lobby ID: $lobbyId" + + val qrBitmap = generateQrCode(lobbyId) + view.findViewById<ImageView>(R.id.lobby_qr).setImageBitmap(qrBitmap) + + view.findViewById<Button>(R.id.btn_cancel).setOnClickListener { + findNavController().popBackStack() + } + + view.findViewById<Button>(R.id.btn_copy).setOnClickListener { + val clipboard = ContextCompat.getSystemService(requireContext(), ClipboardManager::class.java) + val clip = ClipData.newPlainText("Lobby ID", lobbyId) + clipboard?.setPrimaryClip(clip) + } + + return view + } + + private fun generateQrCode(text: String): Bitmap { + val size = 512 + val bits = QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, size, size) + val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565) + for (x in 0 until size) { + for (y in 0 until size) { + bitmap.setPixel(x, y, if (bits[x, y]) Color.BLACK else Color.WHITE) + } + } + return bitmap + } +} diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/util/LobbyDisplayHelper.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/util/LobbyDisplayHelper.kt @@ -0,0 +1,21 @@ +package org.gnunet.gnunetmessenger.util + +import android.graphics.Bitmap +import android.graphics.Color +import com.google.zxing.BarcodeFormat +import com.google.zxing.qrcode.QRCodeWriter + +object LobbyDisplayHelper { + fun generateQRCode(data: String): Bitmap { + val size = 512 + val qrCodeWriter = QRCodeWriter() + val bitMatrix = qrCodeWriter.encode(data, BarcodeFormat.QR_CODE, size, size) + val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565) + for (x in 0 until size) { + for (y in 0 until size) { + bitmap.setPixel(x, y, if (bitMatrix.get(x, y)) Color.BLACK else Color.WHITE) + } + } + return bitmap + } +} diff --git a/GNUnetMessenger/app/src/main/res/layout/fragment_lobby_create.xml b/GNUnetMessenger/app/src/main/res/layout/fragment_lobby_create.xml @@ -0,0 +1,52 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:padding="16dp" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <!-- TextView mit größerer Schrift und zusätzlichem Abstand --> + <TextView + android:id="@+id/lobby_notice" + android:text="@string/lobby_warning" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/holo_red_dark" + android:textSize="16sp" + android:layout_marginBottom="16dp" /> <!-- Fügt Abstand hinzu --> + + <!-- Spinner mit größerer Höhe und Padding --> + <Spinner + android:id="@+id/lifetime_spinner" + android:layout_width="match_parent" + android:layout_height="48dp" + android:entries="@array/lobby_lifetimes" + android:layout_marginTop="24dp" + android:padding="8dp" /> <!-- Padding hinzugefügt für besseren Touch-Bereich --> + + <!-- LinearLayout für Buttons --> + <LinearLayout + android:orientation="horizontal" + android:gravity="end" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="32dp"> + + <!-- Cancel Button mit größerer Höhe und Padding --> + <Button + android:id="@+id/btn_cancel" + android:text="Cancel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="16dp" + android:padding="12dp" /> <!-- Padding hinzugefügt --> + + <!-- Generate Button mit größerer Höhe und Padding --> + <Button + android:id="@+id/btn_generate" + android:text="Generate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:padding="12dp" /> <!-- Padding hinzugefügt --> + </LinearLayout> +</LinearLayout> diff --git a/GNUnetMessenger/app/src/main/res/layout/fragment_lobby_display.xml b/GNUnetMessenger/app/src/main/res/layout/fragment_lobby_display.xml @@ -0,0 +1,28 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:padding="16dp" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <include layout="@layout/view_lobby_info" /> + + <LinearLayout + android:orientation="horizontal" + android:gravity="end" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <Button + android:id="@+id/btn_cancel" + android:text="Cancel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <Button + android:id="@+id/btn_copy" + android:text="Copy" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp"/> + </LinearLayout> +</LinearLayout> diff --git a/GNUnetMessenger/app/src/main/res/layout/view_lobby_info.xml b/GNUnetMessenger/app/src/main/res/layout/view_lobby_info.xml @@ -0,0 +1,20 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:gravity="center" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/lobby_id_text" + android:textSize="18sp" + android:textStyle="bold" + android:layout_margin="8dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <ImageView + android:id="@+id/lobby_qr" + android:layout_width="200dp" + android:layout_height="200dp" + android:layout_margin="16dp" /> +</LinearLayout> diff --git a/GNUnetMessenger/app/src/main/res/menu/main_menu.xml b/GNUnetMessenger/app/src/main/res/menu/main_menu.xml @@ -1,6 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android" +<menu xmlns:tools="http://schemas.android.com/tools" + xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> + <!-- Aktueller Account-Name --> + <item + android:id="@+id/menu_current_account" + android:title="Account: Name" + app:showAsAction="never" + tools:ignore="HardcodedText" /> + + <!-- Create Lobby --> + <item + android:id="@+id/menu_create_lobby" + android:title="@string/create_lobby" + app:showAsAction="never" /> <item android:id="@+id/menu_settings" android:icon="@android:drawable/ic_menu_preferences" diff --git a/GNUnetMessenger/app/src/main/res/navigation/nav_graph.xml b/GNUnetMessenger/app/src/main/res/navigation/nav_graph.xml @@ -5,6 +5,7 @@ android:id="@+id/nav_graph" app:startDestination="@id/accountListFragment"> + <!-- Account List --> <fragment android:id="@+id/accountListFragment" android:name="org.gnunet.gnunetmessenger.ui.account.AccountListFragment" @@ -21,12 +22,14 @@ </action> </fragment> + <!-- Create Account --> <fragment android:id="@+id/createAccountFragment" android:name="org.gnunet.gnunetmessenger.ui.account.CreateAccountFragment" android:label="Create Account" tools:layout="@layout/fragment_create_account"/> + <!-- Account Overview --> <fragment android:id="@+id/accountOverviewFragment" android:name="org.gnunet.gnunetmessenger.ui.account.AccountOverviewFragment" @@ -41,19 +44,54 @@ android:name="chatName" app:argType="string" /> </action> - <action android:id="@+id/action_accountOverviewFragment_to_accountDetailsFragment" app:destination="@id/accountDetailsFragment" /> </fragment> + <!-- Chat Fragment --> <fragment android:id="@+id/chatFragment" android:name="org.gnunet.gnunetmessenger.ui.chat.ChatFragment" android:label="Chat" /> + <!-- Account Details --> <fragment android:id="@+id/accountDetailsFragment" android:name="org.gnunet.gnunetmessenger.ui.account.AccountDetailsFragment" android:label="Account Details" /> + + <!-- Lobby Create --> + <fragment + android:id="@+id/lobbyCreateFragment" + android:name="org.gnunet.gnunetmessenger.ui.account.LobbyCreateFragment" + android:label="Create Lobby" + tools:layout="@layout/fragment_lobby_create"> + <action + android:id="@+id/action_lobbyCreateFragment_to_lobbyDisplayFragment" + app:destination="@id/lobbyDisplayFragment" /> + </fragment> + + <!-- Lobby Display --> + <fragment + android:id="@+id/lobbyDisplayFragment" + android:name="org.gnunet.gnunetmessenger.ui.account.LobbyDisplayFragment" + android:label="Lobby Info" + tools:layout="@layout/fragment_lobby_display"> + <argument + android:name="lobbyId" + app:argType="string" /> + <argument + android:name="lifetime" + app:argType="string" /> + </fragment> + + <!-- Global Navigation for Menu Actions --> + <action + android:id="@+id/action_global_accountDetailsFragment" + app:destination="@id/accountDetailsFragment" /> + + <action + android:id="@+id/action_global_lobbyCreateFragment" + app:destination="@id/lobbyCreateFragment" /> </navigation> diff --git a/GNUnetMessenger/app/src/main/res/values/strings.xml b/GNUnetMessenger/app/src/main/res/values/strings.xml @@ -7,4 +7,15 @@ <string name="confirm">Confirm</string> <string name="settings">Settings</string> <string name="about">About</string> + <string name="create_lobby">Create Lobby</string> + <string name="lobby_warning">Please notice that everyone with access to the lobby\'s code can enter it</string> + <string-array name="lobby_lifetimes"> + <item>Off</item> + <item>4 weeks</item> + <item>1 week</item> + <item>1 day</item> + <item>8 hours</item> + <item>5 minutes</item> + <item>30 seconds</item> + </string-array> </resources> \ No newline at end of file diff --git a/GNUnetMessenger/gradle/libs.versions.toml b/GNUnetMessenger/gradle/libs.versions.toml @@ -10,10 +10,12 @@ espressoCore = "3.5.1" appcompat = "1.6.1" material = "1.10.0" navigation = "2.7.7" -navigationFragmentKtx = "2.8.9" -navigationUiKtx = "2.8.9" +zxing = "3.4.1" +zxingAndroidEmbedded = "4.1.0" [libraries] +zxingcore = { module = "com.google.zxing:core", version.ref = "zxing" } +zxingandroidembedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbedded" } androidx-core-ktx = { module = "androidx.core:core-ktx", version = "1.12.0" } androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version = "2.7.7" } androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version = "2.7.7" }